Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit e785ff9

Browse files
committed
[[ Script ]] Rework LCB VM implementation
This patch contains a significant rework of the LCB VM implementation. Most notably, individual bytecodes are now described as individual structs, and the main operations of description (for building), validation and execution for each bytecode is within the struct.
1 parent 2eb725e commit e785ff9

14 files changed

+6737
-2795
lines changed

libscript/libscript.gyp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
'libscript_private_headers':
1717
[
1818
'src/script-private.h',
19+
'src/script-bytecode.hpp',
20+
'src/script-execute.hpp',
21+
'src/script-validate.hpp',
1922
],
2023

2124
'libscript_sources':
@@ -25,6 +28,8 @@
2528
'src/script-module.cpp',
2629
'src/script-object.cpp',
2730
'src/script-package.cpp',
31+
'src/script-execute.cpp',
32+
'src/script-error.cpp',
2833
],
2934
},
3035

libscript/src/script-builder.cpp

Lines changed: 127 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -17,101 +17,137 @@
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

6672
bool 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

85118
bool 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+
100133
const 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+
108143
MCScriptBytecodeParameterType 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

164200
bool 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

Comments
 (0)