Fri, 28 May 2010 02:18:53 +0100
Give LValue precall() and call() methods, give functions a vm property.
0 | 1 | |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
2 | var OP_MOVE = 0; |
0 | 3 | var OP_LOADK = 1; |
39 | 4 | var OP_LOADBOOL = 2; |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
5 | var OP_LOADNIL = 3; |
20
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
6 | var OP_GETUPVAL = 4; |
0 | 7 | var OP_GETGLOBAL = 5; |
28
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
8 | var OP_GETTABLE = 6; |
6 | 9 | var OP_SETGLOBAL = 7; |
20
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
10 | var OP_SETUPVAL = 8; |
28
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
11 | var OP_SETTABLE = 9; |
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
12 | var OP_NEWTABLE = 10; |
36 | 13 | var OP_SELF = 11; |
40
3a074ec1790f
Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents:
39
diff
changeset
|
14 | var OP_JMP = 22; |
3a074ec1790f
Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents:
39
diff
changeset
|
15 | var OP_TEST = 26; |
0 | 16 | var OP_CALL = 28; |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
17 | var OP_RETURN = 30; |
34
2c3d73c76d0f
OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents:
33
diff
changeset
|
18 | var OP_FORLOOP = 31; |
2c3d73c76d0f
OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents:
33
diff
changeset
|
19 | var OP_FORPREP = 32; |
15
5240eaff785f
Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents:
14
diff
changeset
|
20 | var OP_CLOSURE = 36; |
0 | 21 | |
8 | 22 | var debugMode = false; |
23 | ||
0 | 24 | function LValue(type, value) |
25 | { | |
26 | this.type = type||"nil"; | |
37
62c1d9bf3000
Allow LValues with a value of 'false' to be create (it was converted to 'null')
Matthew Wild <mwild1@gmail.com>
parents:
36
diff
changeset
|
27 | this.value = value; |
0 | 28 | } |
29 | ||
30 | LValue.prototype = { | |
31 | call: function (args) | |
32 | { | |
49
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
33 | var f = this.precall(); |
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
34 | if(typeof(f) == "function") |
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
35 | var ret = f.apply(this.vm, args?args.map(function (a) { return a.value; }):[]); |
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
36 | else |
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
37 | var ret = this.vm.call(f); |
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
38 | if(typeof(ret) == "undefined") |
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
39 | ret = []; |
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
40 | return ret; |
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
41 | }, |
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
42 | precall: function () |
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
43 | { |
3
6f338fbf0abc
Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
44 | if(this.type == "function") |
6f338fbf0abc
Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
45 | return this.value; |
6f338fbf0abc
Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
46 | else |
6f338fbf0abc
Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
47 | throw "Attempt to call a " + this.type + " value"; |
0 | 48 | }, |
49 | index: function (key) | |
50 | { | |
51 | if(this.type == "table") | |
52 | { | |
4
0eda73eda4ae
Return nil for non-existent table keys
Matthew Wild <mwild1@gmail.com>
parents:
3
diff
changeset
|
53 | var val = this.value[key.value]; |
0eda73eda4ae
Return nil for non-existent table keys
Matthew Wild <mwild1@gmail.com>
parents:
3
diff
changeset
|
54 | if(typeof(val) == "undefined") |
0eda73eda4ae
Return nil for non-existent table keys
Matthew Wild <mwild1@gmail.com>
parents:
3
diff
changeset
|
55 | return new LValue("nil", null); |
0eda73eda4ae
Return nil for non-existent table keys
Matthew Wild <mwild1@gmail.com>
parents:
3
diff
changeset
|
56 | return val; |
0 | 57 | } |
7
00ec5f6e7579
Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents:
6
diff
changeset
|
58 | else |
00ec5f6e7579
Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents:
6
diff
changeset
|
59 | throw "Attempt to index a " + this.type + " value"; |
0 | 60 | }, |
61 | setIndex: function (key, value) | |
62 | { | |
63 | if(this.type == "table") | |
64 | { | |
65 | this.value[key.value] = value; | |
66 | } | |
7
00ec5f6e7579
Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents:
6
diff
changeset
|
67 | else |
00ec5f6e7579
Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents:
6
diff
changeset
|
68 | throw "Attempt to index a " + this.type + " value"; |
0 | 69 | } |
70 | }; | |
71 | ||
72 | function LValueFromString(string) | |
73 | { | |
74 | return new LValue("string", string); | |
75 | } | |
76 | ||
49
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
77 | function LValueFromFunction(vm, func) |
0 | 78 | { |
49
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
79 | var val = new LValue("function", func); |
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
80 | val.vm = vm; |
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
81 | return val; |
0 | 82 | } |
83 | ||
27
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
84 | function LValueFromValue(value) |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
85 | { |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
86 | switch(typeof(value)) |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
87 | { |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
88 | case "string": |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
89 | return new LValueFromString(value); |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
90 | case "function": |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
91 | return new LValueFromFunction(value); |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
92 | case "object": |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
93 | if(value == null) |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
94 | return new LValue("nil", value); |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
95 | default: |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
96 | sys.puts( "Not able to convert type " + |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
97 | typeof(value)+" from Javascript to Lua: "+sys.inspect(value)); |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
98 | throw "Not able to convert type " + |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
99 | typeof(value)+" from Javascript to Lua"; |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
100 | } |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
101 | } |
35a2203253a6
New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents:
26
diff
changeset
|
102 | |
13
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
103 | function LBinaryChunk(chunk, start) |
0 | 104 | { |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
105 | this.chunk = chunk; |
13
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
106 | this.pos = start||12; |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
107 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
108 | this.sourceName = this.readString(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
109 | this.lineDefined = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
110 | this.lastLineDefined = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
111 | this.numUpvalues = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
112 | this.numParameters = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
113 | this.isVararg = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
114 | this.maxStackSize = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
115 | |
0 | 116 | this.instructions = []; |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
117 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
118 | this.numInstructions = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
119 | for(var i=0;i<this.numInstructions;i++) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
120 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
121 | var ins = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
122 | this.instructions.push([ |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
123 | ins&0x3F, // Opcode |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
124 | (ins>>6)&0xFF, // Field A |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
125 | (ins>>23)&0x1FF, // Field B |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
126 | (ins>>14)&0x1FF // Field C |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
127 | ]); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
128 | if(debugMode) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
129 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
130 | var pi = this.instructions[this.instructions.length-1]; |
31
bc58527bac34
Print sBx field in bytecode dump (for debugging)
Matthew Wild <mwild1@gmail.com>
parents:
30
diff
changeset
|
131 | sys.puts("Pos: "+(this.pos-4)+" Ins: "+ins+" OP: "+INS_OPCODE(pi)+" A: "+INS_A(pi)+" B: "+INS_B(pi)+" C: "+INS_C(pi)+" Bx: "+INS_Bx(pi)+" sBx: "+(INS_Bx(pi)-0x1FFFE)); |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
132 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
133 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
134 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
135 | this.constants = []; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
136 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
137 | this.numConstants = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
138 | for(var i=0;i<this.numConstants;i++) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
139 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
140 | var type = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
141 | switch(type) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
142 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
143 | case 0: // Nil |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
144 | this.constants.push(new LValue("nil", null)); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
145 | break; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
146 | case 1: // Boolean |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
147 | this.constants.push(new LValue("boolean", this.readByte())); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
148 | break; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
149 | case 3: // Number |
12
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
150 | this.constants.push(new LValue("number", this.readNumber())); |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
151 | break; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
152 | case 4: // String |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
153 | this.constants.push(LValueFromString(this.readString())); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
154 | break; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
155 | default: |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
156 | throw "Invalid constant type "+type+" in bytecode"; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
157 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
158 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
159 | |
13
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
160 | this.prototypes = []; |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
161 | |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
162 | this.numPrototypes = this.readInt(); |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
163 | for(var i=0;i<this.numPrototypes;i++) |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
164 | { |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
165 | var p = new LBinaryChunk(chunk, this.pos); |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
166 | this.pos = p.pos; |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
167 | this.prototypes.push(p); |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
168 | } |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
169 | |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
170 | this.sourceLines = []; |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
171 | |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
172 | this.numSourceLines = this.readInt(); |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
173 | for(var i=0;i<this.numSourceLines;i++) |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
174 | { |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
175 | this.sourceLines.push(this.readInt()); |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
176 | } |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
177 | |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
178 | this.localList = []; |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
179 | this.numLocalList = this.readInt(); |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
180 | for(var i=0;i<this.numLocalList;i++) |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
181 | { |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
182 | this.localList.push([this.readString(),this.readInt(),this.readInt()]); |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
183 | } |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
184 | |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
185 | this.upvalueList = []; |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
186 | this.numUpvalueList = this.readInt(); |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
187 | for(var i=0;i<this.numUpvalueList;i++) |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
188 | { |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
189 | this.upvalueList.push(this.readString()); |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
190 | } |
f259da6951e8
Support for reading all fields in the chunk (including function prototypes, required for OP_CLOSURE)
Matthew Wild <mwild1@gmail.com>
parents:
12
diff
changeset
|
191 | |
0 | 192 | return this; |
193 | } | |
194 | ||
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
195 | LBinaryChunk.prototype = { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
196 | readBytes: function (n) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
197 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
198 | return this.chunk.slice(this.pos, this.pos+=n); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
199 | }, |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
200 | readByte: function () |
0 | 201 | { |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
202 | return this.readBytes(1).charCodeAt(0); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
203 | }, |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
204 | readInt: function () |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
205 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
206 | //FIXME: Endianness |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
207 | return this.readByte() | (this.readByte()<<8) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
208 | | (this.readByte()<<16) | (this.readByte()<<24); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
209 | }, |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
210 | readString: function () |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
211 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
212 | var len = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
213 | return this.readBytes(len).substring(0,len-1); |
0 | 214 | }, |
12
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
215 | readNumber: function () |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
216 | { |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
217 | //FIXME: Endianness |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
218 | var bytes = [this.readByte(),this.readByte(),this.readByte(),this.readByte(), |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
219 | this.readByte(),this.readByte(),this.readByte(),this.readByte()].reverse(); |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
220 | |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
221 | var sign = (bytes[0]>>7)&0x1; |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
222 | var exp = (bytes[0]&0x7F)<<4 | (bytes[1]&0xf0)>>4; |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
223 | |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
224 | var frac = ((bytes[1] & 0x0f) * Math.pow(2,48)) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
225 | + (bytes[2] * Math.pow(2,40)) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
226 | + (bytes[3] * Math.pow(2,32)) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
227 | + (bytes[4] * Math.pow(2,24)) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
228 | + (bytes[5] * Math.pow(2,16)) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
229 | + (bytes[6] * Math.pow(2,8)) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
230 | + bytes[7]; |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
231 | |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
232 | if(exp != 0x000 && exp != 0x7FF) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
233 | { |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
234 | var n = (sign==1?-1:1)*Math.pow(2,exp-1023)*(1+(frac/0x10000000000000)); |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
235 | return n; |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
236 | } |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
237 | else if(exp == 0x000) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
238 | { |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
239 | return sign*0; |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
240 | } |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
241 | else |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
242 | return frac==0?sign*Infinity:NaN; |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
243 | } |
0 | 244 | }; |
245 | ||
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
246 | function INS_OPCODE(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
247 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
248 | return ins[0]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
249 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
250 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
251 | function INS_A(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
252 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
253 | return ins[1]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
254 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
255 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
256 | function INS_B(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
257 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
258 | return ins[2]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
259 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
260 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
261 | function INS_C(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
262 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
263 | return ins[3]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
264 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
265 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
266 | function INS_Bx(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
267 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
268 | return ((INS_C(ins))|(INS_B(ins)<<9)); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
269 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
270 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
271 | function INS_sBx(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
272 | { |
32
035aacc192d8
Fix off-by-one in calculating the value of sBx
Matthew Wild <mwild1@gmail.com>
parents:
31
diff
changeset
|
273 | return (INS_Bx(ins)-0x1FFFF); |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
274 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
275 | |
43
ecfa7896af35
Give LFunctions a vm property
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
276 | function LFunction(vm, chunk, env) |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
277 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
278 | function F() {}; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
279 | F.prototype = chunk; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
280 | var o = new F(); |
43
ecfa7896af35
Give LFunctions a vm property
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
281 | o.vm = vm; |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
282 | o.environment = env; |
14
21a2fce50931
Add chunk property to LFunction to show which chunk it came from
Matthew Wild <mwild1@gmail.com>
parents:
13
diff
changeset
|
283 | o.chunk = chunk; |
20
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
284 | o.upvalues = []; |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
285 | return o; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
286 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
287 | |
0 | 288 | function LVM() |
289 | { | |
290 | this.callstack = []; | |
291 | this.stack = []; | |
292 | return this; | |
293 | } | |
294 | ||
295 | LVM.prototype = { | |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
296 | call: function (lfFunction) |
0 | 297 | { |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
298 | var frame = {f:lfFunction,pc:0,reg:[]}; |
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
299 | this.callstack.push(frame); |
38
ba347b4b655f
Initialise all stack slots to nil when calling a chunk
Matthew Wild <mwild1@gmail.com>
parents:
37
diff
changeset
|
300 | for(var i=0;i<lfFunction.maxStackSize;i++) |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
301 | frame.reg[i] = new LValue("nil", null); |
47
b8c4273edbbb
Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents:
46
diff
changeset
|
302 | return this.run(frame); |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
303 | }, |
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
304 | run: function(frame) |
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
305 | { |
0 | 306 | var instruction; |
307 | while(this.callstack.length>0) | |
308 | { | |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
309 | instruction = frame.f.instructions[frame.pc++]; |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
310 | if(debugMode) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
311 | { |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
312 | sys.puts("PC: "+(frame.pc-1)+" OP: "+instruction[0]); |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
313 | sys.puts("STACK: "+sys.inspect(frame.reg)); |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
314 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
315 | switch(INS_OPCODE(instruction)) |
0 | 316 | { |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
317 | case OP_MOVE: |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
318 | frame.reg[INS_A(instruction)] = frame.reg[INS_B(instruction)]; |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
319 | break; |
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
320 | case OP_LOADNIL: |
10
ce2f27fa25a4
Use new notation for accessing instruction fields
Matthew Wild <mwild1@gmail.com>
parents:
9
diff
changeset
|
321 | for(var i = INS_A(instruction);i<=INS_B(instruction);i++) |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
322 | frame.reg[i] = new LValue("nil", null); |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
323 | break; |
39 | 324 | case OP_LOADBOOL: |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
325 | frame.reg[INS_A(instruction)] = new LValue("boolean", INS_B(instruction)!=0); |
39 | 326 | if(INS_C(instruction)!=0) |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
327 | frame.pc++; |
39 | 328 | break; |
20
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
329 | case OP_GETUPVAL: |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
330 | frame.reg[INS_A(instruction)] = frame.f.upvalues[INS_B(instruction)]; |
20
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
331 | break; |
0 | 332 | case OP_GETGLOBAL: |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
333 | var name = frame.f.constants[INS_Bx(instruction)]; |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
334 | frame.reg[INS_A(instruction)] = frame.f.environment.index(name); |
0 | 335 | break; |
20
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
336 | case OP_SETUPVAL: |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
337 | var reg = frame.reg[INS_A(instruction)]; |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
338 | var upvalue = frame.f.upvalues[INS_B(instruction)]; |
26 | 339 | upvalue.type = reg.type; |
340 | upvalue.value = reg.value; | |
20
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
341 | break; |
6 | 342 | case OP_SETGLOBAL: |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
343 | var name = frame.f.constants[INS_Bx(instruction)]; |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
344 | frame.f.environment.setIndex(name, frame.reg[instruction[1]]); |
6 | 345 | break; |
0 | 346 | case OP_LOADK: |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
347 | var constant = frame.f.constants[INS_Bx(instruction)]; |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
348 | frame.reg[INS_A(instruction)] = new LValue(constant.type, constant.value); |
0 | 349 | break; |
28
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
350 | case OP_NEWTABLE: |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
351 | frame.reg[INS_A(instruction)] = new LValue("table", {}); |
28
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
352 | break; |
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
353 | case OP_GETTABLE: |
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
354 | var C = INS_C(instruction); |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
355 | var keysource = (C&256)?frame.f.constants:frame.reg; |
28
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
356 | var key = keysource[C&0xff]; |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
357 | var value = frame.reg[INS_B(instruction)].index(key).value; |
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
358 | frame.reg[INS_A(instruction)] = new LValueFromValue(value); |
28
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
359 | break; |
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
360 | case OP_SETTABLE: |
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
361 | var C = INS_C(instruction); |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
362 | var valuesource = (C&256)?frame.f.constants:frame.reg; |
28
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
363 | var value = valuesource[C&0xff]; |
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
364 | |
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
365 | var B = INS_B(instruction); |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
366 | var keysource = (B&256)?frame.f.constants:frame.reg; |
28
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
367 | var key = keysource[B&0xff]; |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
368 | frame.reg[INS_A(instruction)].setIndex(key, value); |
28
d14b47c3870f
Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents:
27
diff
changeset
|
369 | break; |
0 | 370 | case OP_CALL: |
49
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
371 | var f = frame.reg[INS_A(instruction)].precall(); // return JS or LValue |
18
ae0b4ec242a3
Support for B==0 in OP_CALL (signifies params are to top of the stack)
Matthew Wild <mwild1@gmail.com>
parents:
17
diff
changeset
|
372 | var A = INS_A(instruction), B = INS_B(instruction), undefined; |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
373 | var args = frame.reg.slice(A+1, B==0?undefined:(A+B)); |
38
ba347b4b655f
Initialise all stack slots to nil when calling a chunk
Matthew Wild <mwild1@gmail.com>
parents:
37
diff
changeset
|
374 | for(var i=args.length+1;i<f.maxStackSize;i++) |
ba347b4b655f
Initialise all stack slots to nil when calling a chunk
Matthew Wild <mwild1@gmail.com>
parents:
37
diff
changeset
|
375 | args[i] = new LValue("nil", null); |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
376 | if(typeof(f) == "function") |
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
377 | { |
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
378 | // JS native function |
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
379 | var ret = f.apply(null, args.map(function (a) { return a.value; })); |
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
380 | } |
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
381 | else |
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
382 | { |
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
383 | // Lua function |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
384 | frame = {f:f,pc:0,reg:args, |
19
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
385 | retAt:INS_A(instruction),retCount:INS_C(instruction)}; |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
386 | this.callstack.push(frame); |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
387 | } |
0 | 388 | break; |
15
5240eaff785f
Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents:
14
diff
changeset
|
389 | case OP_CLOSURE: |
5240eaff785f
Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents:
14
diff
changeset
|
390 | var prototype_id = INS_Bx(instruction); |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
391 | var chunk = frame.f.chunk.prototypes[prototype_id]; |
43
ecfa7896af35
Give LFunctions a vm property
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
392 | var f = new LFunction(this, chunk, frame.f.environment); |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
393 | frame.reg[INS_A(instruction)] = new LValue("function", f); |
20
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
394 | for(var i=0;i<chunk.numUpvalues;i++) |
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
395 | { |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
396 | var upval_instruction = frame.f.instructions[frame.pc++]; |
20
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
397 | switch(INS_OPCODE(upval_instruction)) |
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
398 | { |
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
399 | case OP_MOVE: |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
400 | f.upvalues[i] = frame.reg[INS_B(upval_instruction)]; |
20
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
401 | break; |
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
402 | case OP_GETUPVAL: |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
403 | f.upvalues[i] = frame.f.upvalues[INS_B(upval_instruction)]; |
20
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
404 | break; |
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
405 | default: |
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
406 | throw "Invalid upvalue opcode following OP_CLOSURE"; |
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
407 | } |
977ae93f612c
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents:
19
diff
changeset
|
408 | } |
15
5240eaff785f
Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents:
14
diff
changeset
|
409 | break; |
0 | 410 | case OP_RETURN: |
19
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
411 | var oldFrame = this.callstack.pop(); |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
412 | frame = this.callstack[this.callstack.length-1]; |
47
b8c4273edbbb
Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents:
46
diff
changeset
|
413 | var rets; |
b8c4273edbbb
Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents:
46
diff
changeset
|
414 | if(INS_B(instruction) == 0) |
b8c4273edbbb
Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents:
46
diff
changeset
|
415 | rets = oldFrame.reg.slice(INS_A(instruction)); |
b8c4273edbbb
Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents:
46
diff
changeset
|
416 | else |
b8c4273edbbb
Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents:
46
diff
changeset
|
417 | rets = oldFrame.reg.slice(INS_A(instruction),INS_A(instruction)+(INS_B(instruction)-1)); |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
418 | if(frame) |
19
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
419 | { |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
420 | var i; |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
421 | for(i=0;(oldFrame.retCount == 0||i<oldFrame.retCount)&&i<rets.length;i++) |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
422 | frame.reg[oldFrame.retAt+i] = rets[i]; |
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
423 | if(oldFrame.retAt+i<frame.reg.length) |
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
424 | frame.reg.splice(0,oldFrame.retAt+i); |
19
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
425 | } |
47
b8c4273edbbb
Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents:
46
diff
changeset
|
426 | else |
b8c4273edbbb
Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents:
46
diff
changeset
|
427 | return rets; |
0 | 428 | break; |
36 | 429 | case OP_SELF: |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
430 | var table = frame.reg[INS_B(instruction)]; |
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
431 | frame.reg[INS_A(instruction)+1] = table; |
36 | 432 | var C = INS_C(instruction); |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
433 | var keysource = (C&256)?frame.f.constants:frame.reg; |
36 | 434 | var key = keysource[C&0xff]; |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
435 | frame.reg[INS_A(instruction)] = table.index(key); |
36 | 436 | break; |
34
2c3d73c76d0f
OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents:
33
diff
changeset
|
437 | case OP_FORPREP: |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
438 | frame.pc+=(INS_sBx(instruction)); |
34
2c3d73c76d0f
OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents:
33
diff
changeset
|
439 | var A = INS_A(instruction); |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
440 | frame.reg[A].value -= frame.reg[A+2].value; |
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
441 | frame.reg[A+3] = new LValue("number", null); |
34
2c3d73c76d0f
OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents:
33
diff
changeset
|
442 | break; |
2c3d73c76d0f
OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents:
33
diff
changeset
|
443 | case OP_FORLOOP: |
2c3d73c76d0f
OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents:
33
diff
changeset
|
444 | var A = INS_A(instruction); |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
445 | var RA = frame.reg[A]; |
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
446 | RA.value += frame.reg[A+2].value; |
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
447 | if(RA.value <= frame.reg[A+1].value) |
34
2c3d73c76d0f
OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents:
33
diff
changeset
|
448 | { |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
449 | frame.pc += INS_sBx(instruction); |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
450 | frame.reg[A+3].value = RA.value; |
34
2c3d73c76d0f
OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents:
33
diff
changeset
|
451 | } |
2c3d73c76d0f
OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents:
33
diff
changeset
|
452 | break; |
40
3a074ec1790f
Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents:
39
diff
changeset
|
453 | case OP_TEST: |
45
4d2cf0b5235d
Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents:
42
diff
changeset
|
454 | var RA = frame.reg[INS_A(instruction)]; |
40
3a074ec1790f
Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents:
39
diff
changeset
|
455 | var RA_bool = RA.type == "nil" || (RA.type == "boolean" && RA.value == false); |
3a074ec1790f
Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents:
39
diff
changeset
|
456 | if(RA_bool == (INS_C(instruction)!=0)) |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
457 | frame.pc++; |
40
3a074ec1790f
Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents:
39
diff
changeset
|
458 | break; |
3a074ec1790f
Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents:
39
diff
changeset
|
459 | case OP_JMP: |
41
70eb0eb5e7e8
Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents:
40
diff
changeset
|
460 | frame.pc+=INS_sBx(instruction); |
40
3a074ec1790f
Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents:
39
diff
changeset
|
461 | break; |
0 | 462 | default: |
11
1b3267149cbd
Throw error on unhandled opcodes
Matthew Wild <mwild1@gmail.com>
parents:
10
diff
changeset
|
463 | throw "Unhandled opcode: "+INS_OPCODE(instruction); |
0 | 464 | } |
465 | } | |
466 | } | |
467 | }; | |
468 | ||
469 | var testvm = new LVM(); | |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
470 | |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
471 | var fs=require("fs"); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
472 | var sys=require("sys"); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
473 | var c = new LBinaryChunk(fs.readFileSync("luac.out", "binary")); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
474 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
475 | var default_environment = new LValue("table", {}); |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
476 | |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
477 | var print; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
478 | if(typeof(document) == "object") |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
479 | print = function (a) { document.write(a+"<br/>") }; // Browser |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
480 | else |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
481 | print = require("sys").puts; // Nodejs |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
482 | |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
483 | default_environment.setIndex(LValueFromString("print"), LValueFromFunction(print)); |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
484 | |
49
052bd6e8daf6
Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents:
48
diff
changeset
|
485 | var f = new LFunction(testvm, c, default_environment); |
2
253863ece36f
Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents:
1
diff
changeset
|
486 | |
29
62f3df8ed204
Remove rawExceptions flag, always print exception's stack trace if it has one
Matthew Wild <mwild1@gmail.com>
parents:
28
diff
changeset
|
487 | try{ |
48 | 488 | var ret = testvm.call(f); |
489 | if(ret) | |
490 | sys.puts("Returned: "+sys.inspect(ret)); | |
29
62f3df8ed204
Remove rawExceptions flag, always print exception's stack trace if it has one
Matthew Wild <mwild1@gmail.com>
parents:
28
diff
changeset
|
491 | } |
62f3df8ed204
Remove rawExceptions flag, always print exception's stack trace if it has one
Matthew Wild <mwild1@gmail.com>
parents:
28
diff
changeset
|
492 | catch(e) |
25
9e62bc13b30d
Add new debug option - rawExceptions - to prevent catching exceptions thrown by the VM, use for debugging the VM.
Matthew Wild <mwild1@gmail.com>
parents:
24
diff
changeset
|
493 | { |
29
62f3df8ed204
Remove rawExceptions flag, always print exception's stack trace if it has one
Matthew Wild <mwild1@gmail.com>
parents:
28
diff
changeset
|
494 | print("Error: " + e); |
35
3de1d63ffdf7
Fix for error handling to handle string exceptions
Matthew Wild <mwild1@gmail.com>
parents:
34
diff
changeset
|
495 | if(typeof(e) == "object" && "stack" in e) |
29
62f3df8ed204
Remove rawExceptions flag, always print exception's stack trace if it has one
Matthew Wild <mwild1@gmail.com>
parents:
28
diff
changeset
|
496 | print(e.stack); |
44
f5244bce28ce
Exit with failure code on error
Matthew Wild <mwild1@gmail.com>
parents:
43
diff
changeset
|
497 | process.exit(1); |
5 | 498 | } |