1717#include < foundation.h>
1818#include < foundation-auto.h>
1919
20- #include " libscript/script.h"
20+ #include < libscript/script.h>
21+
2122#include " script-private.h"
2223
24+ #include " script-bytecode.hpp"
25+
2326// //////////////////////////////////////////////////////////////////////////////
2427
25- // Each bytecode which the VM understands is described by its own 'info' entry.
26- //
27- // The opcode is that which is used in the module file.
28- // The name is the human readable form of the opcode.
29- // The format is a string describing the parameters to the opcode:
30- // l - label
31- // r - register (param, local or temp)
32- // c - constant pool index
33- // d - fetchable definition (variable, constant, handler)
34- // h - handler definition
35- // v - variable definition
36- // The final char of the description string can be one of:
37- // ? - the final parameter is optional
38- // * - the final parameter type is expected 0-n times
39- // % - the final parameter type is expected 0-2n times
40-
41- struct MCScriptBytecodeInfo
42- {
43- MCScriptBytecodeOp opcode;
44- const char *name;
45- const char *format;
28+ // Utility functor, used to fetch the bytecode info struct for the given
29+ // opcode.
30+ struct MCScriptDescribeBytecodeOp_Impl
31+ {
32+ public:
33+ template <typename OpStruct>
34+ bool Visit (const MCScriptBytecodeOpInfo*& r_info) const
35+ {
36+ r_info = &OpStruct::Describe ();
37+ return true ;
38+ }
4639};
4740
48- static const MCScriptBytecodeInfo kBytecodeInfo [] =
49- {
50- { kMCScriptBytecodeOpJump , " jump" , " l" },
51- { kMCScriptBytecodeOpJumpIfFalse , " jump_if_false" , " rl" },
52- { kMCScriptBytecodeOpJumpIfTrue , " jump_if_true" , " rl" },
53- { kMCScriptBytecodeOpAssignConstant , " assign_constant" , " rc" },
54- { kMCScriptBytecodeOpAssign , " assign" , " rr" },
55- { kMCScriptBytecodeOpReturn , " return" , " r?" },
56- { kMCScriptBytecodeOpInvoke , " invoke" , " hrr*" },
57- { kMCScriptBytecodeOpInvokeIndirect , " invoke_indirect" , " rrr*" },
58- { kMCScriptBytecodeOpFetch , " fetch" , " rd" },
59- { kMCScriptBytecodeOpStore , " store" , " rv" },
60- { kMCScriptBytecodeOpAssignList , " assign_list" , " rr*" },
61- { kMCScriptBytecodeOpAssignArray , " assign_array" , " rr%" },
62- { kMCScriptBytecodeOpReset , " reset" , " rr*" },
41+ static bool
42+ MCScriptDescribeBytecodeOp (uindex_t p_opcode,
43+ const MCScriptBytecodeOpInfo*& r_info)
44+ {
45+ if (p_opcode > kMCScriptBytecodeOp__Last ||
46+ !MCScriptBytecodeDispatchR ((MCScriptBytecodeOp)p_opcode,
47+ MCScriptDescribeBytecodeOp_Impl (),
48+ r_info))
49+ {
50+ return false ;
51+ }
52+
53+ return true ;
54+ }
55+
56+ // ////////
57+
58+ class MCScriptCopyBytecodeNames_Impl
59+ {
60+ public:
61+ template <typename OpStruct>
62+ bool Visit (MCProperListRef x_bytecode_names) const
63+ {
64+ if (!MCProperListPushElementOntoBack (x_bytecode_names,
65+ MCSTR (OpStruct::Describe ().name )))
66+ return false ;
67+
68+ return true ;
69+ }
6370};
64- static const int kBytecodeCount = sizeof (kBytecodeInfo ) / sizeof (kBytecodeInfo [0 ]);
6571
6672bool MCScriptCopyBytecodeNames (MCProperListRef& r_bytecode_names)
6773{
68- MCAutoProperListRef t_bytecode_names;
69- if (!MCProperListCreateMutable (&t_bytecode_names))
70- return false ;
71-
72- for (int i = 0 ; i < kBytecodeCount ; i++)
73- {
74- MCNewAutoNameRef t_name;
75- if (!MCProperListPushElementOntoBack (*t_bytecode_names,
76- MCSTR (kBytecodeInfo [i].name )))
77- return false ;
78- }
79-
80- r_bytecode_names = t_bytecode_names.Take ();
81-
82- return true ;
83- }
74+ MCAutoProperListRef t_bytecode_names;
75+ if (!MCProperListCreateMutable (&t_bytecode_names))
76+ return false ;
77+
78+ MCProperListRef t_bytecode_names_arg = *t_bytecode_names;
79+ if (!MCScriptBytecodeForEach (MCScriptCopyBytecodeNames_Impl (),
80+ t_bytecode_names_arg))
81+ return false ;
82+
83+ r_bytecode_names = t_bytecode_names.Take ();
84+
85+ return true ;
86+ }
87+
88+ // ////////
89+
90+ struct MCScriptLookupBytecode_Impl
91+ {
92+ public:
93+ struct Args
94+ {
95+ const char *name;
96+ uindex_t & _opcode;
97+
98+ Args (const char *p_name,
99+ uindex_t & r_opcode)
100+ : name(p_name),
101+ _opcode (r_opcode)
102+ {
103+ }
104+ };
105+
106+ template <typename OpStruct>
107+ bool Visit (Args p_args) const
108+ {
109+ if (0 != strcmp (p_args.name , OpStruct::Describe ().name ))
110+ return true ;
111+
112+ p_args._opcode = (uindex_t )OpStruct::Describe ().code ;
113+
114+ return false ;
115+ }
116+ };
84117
85118bool MCScriptLookupBytecode (const char *p_name, uindex_t & r_opcode)
86119{
87- for (uindex_t i = 0 ; i < kBytecodeCount ; i++)
88- {
89- if (0 != strcmp (p_name, kBytecodeInfo [i] . name))
90- continue ;
91-
92- r_opcode = i;
93-
94- return true ;
95- }
96-
97- return false ;
120+ // If we get all the way through the bytecodes without returning false, then
121+ // it means it wasn't found.
122+ MCScriptLookupBytecode_Impl::Args t_args (p_name,
123+ r_opcode);
124+ if (MCScriptBytecodeForEach (MCScriptLookupBytecode_Impl (),
125+ t_args))
126+ return false ;
127+
128+ return true ;
98129}
99130
131+ // ////////
132+
100133const char *MCScriptDescribeBytecode (uindex_t p_opcode)
101134{
102- if (p_opcode >= kBytecodeCount )
103- return " <unknown> " ;
104-
105- return kBytecodeInfo [p_opcode]. name ;
135+ const MCScriptBytecodeOpInfo *t_info;
136+ if (! MCScriptDescribeBytecodeOp (p_opcode, t_info))
137+ return " <unknown> " ;
138+ return t_info-> name ;
106139}
107140
141+ // ////////
142+
108143MCScriptBytecodeParameterType MCScriptDescribeBytecodeParameter (uindex_t p_opcode, uindex_t p_index)
109144{
110- if (p_opcode >= kBytecodeCount )
111- return kMCScriptBytecodeParameterTypeUnknown ;
145+ const MCScriptBytecodeOpInfo *t_info;
146+ if (!MCScriptDescribeBytecodeOp (p_opcode, t_info))
147+ return kMCScriptBytecodeParameterTypeUnknown ;
112148
113149 const char *t_desc;
114- t_desc = kBytecodeInfo [p_opcode]. format ;
150+ t_desc = t_info-> format ;
115151
116152 size_t t_desc_length;
117153 t_desc_length = strlen (t_desc);
@@ -163,11 +199,12 @@ MCScriptBytecodeParameterType MCScriptDescribeBytecodeParameter(uindex_t p_opcod
163199
164200bool MCScriptCheckBytecodeParameterCount (uindex_t p_opcode, uindex_t p_proposed_count)
165201{
166- if (p_opcode >= kBytecodeCount )
167- return false ;
202+ const MCScriptBytecodeOpInfo *t_info;
203+ if (!MCScriptDescribeBytecodeOp (p_opcode, t_info))
204+ return kMCScriptBytecodeParameterTypeUnknown ;
168205
169206 const char *t_desc;
170- t_desc = kBytecodeInfo [p_opcode]. format ;
207+ t_desc = t_info-> format ;
171208
172209 size_t t_desc_length;
173210 t_desc_length = strlen (t_desc);
@@ -1615,13 +1652,14 @@ void MCScriptEmitBytecodeInModuleA(MCScriptModuleBuilderRef self, uindex_t p_opc
16151652{
16161653 if (self == nil || !self -> valid)
16171654 return ;
1618-
1619- if (p_opcode >= kBytecodeCount ||
1620- !MCScriptCheckBytecodeParameterCount (p_opcode, p_argument_count))
1621- {
1622- self -> valid = false ;
1623- return ;
1624- }
1655+
1656+ const MCScriptBytecodeOpInfo *t_info;
1657+ if (!MCScriptDescribeBytecodeOp (p_opcode, t_info) ||
1658+ !MCScriptCheckBytecodeParameterCount (p_opcode, p_argument_count))
1659+ {
1660+ self -> valid = false ;
1661+ return ;
1662+ }
16251663
16261664 for (uindex_t i = 0 ; i < p_argument_count; i++)
16271665 {
@@ -1630,14 +1668,14 @@ void MCScriptEmitBytecodeInModuleA(MCScriptModuleBuilderRef self, uindex_t p_opc
16301668 i);
16311669 switch (t_param_type)
16321670 {
1633- case kMCScriptBytecodeParameterTypeUnknown :
1671+ case kMCScriptBytecodeParameterTypeUnknown :
16341672 self -> valid = false ;
16351673 return ;
16361674
16371675 case kMCScriptBytecodeParameterTypeLabel :
16381676 if (p_arguments[i] == 0 ||
16391677 p_arguments[i] > self -> label_count)
1640- {
1678+ {
16411679 self -> valid = false ;
16421680 return ;
16431681 }
@@ -1649,31 +1687,31 @@ void MCScriptEmitBytecodeInModuleA(MCScriptModuleBuilderRef self, uindex_t p_opc
16491687
16501688 case kMCScriptBytecodeParameterTypeConstant :
16511689 if (p_arguments[i] >= self -> module . value_count)
1652- {
1690+ {
16531691 self -> valid = false ;
16541692 return ;
16551693 }
16561694 break ;
16571695
16581696 case kMCScriptBytecodeParameterTypeDefinition :
16591697 if (!__is_valid_definition (self, p_arguments[i]))
1660- {
1698+ {
16611699 self -> valid = false ;
16621700 return ;
16631701 }
16641702 break ;
16651703
16661704 case kMCScriptBytecodeParameterTypeVariable :
16671705 if (!__is_valid_variable_definition (self, p_arguments[i]))
1668- {
1706+ {
16691707 self -> valid = false ;
16701708 return ;
16711709 }
16721710 break ;
16731711
16741712 case kMCScriptBytecodeParameterTypeHandler :
16751713 if (!__is_valid_handler_definition (self, p_arguments[i]))
1676- {
1714+ {
16771715 self -> valid = false ;
16781716 return ;
16791717 }
@@ -1682,7 +1720,7 @@ void MCScriptEmitBytecodeInModuleA(MCScriptModuleBuilderRef self, uindex_t p_opc
16821720 }
16831721
16841722 __begin_instruction (self,
1685- kBytecodeInfo [p_opcode] . opcode );
1723+ t_info-> code );
16861724 for (uindex_t i = 0 ; i < p_argument_count; i++)
16871725 __continue_instruction (self,
16881726 p_arguments[i]);
0 commit comments