Tue, 06 Apr 2010 14:49:52 +0100
Add a bytecode interpreter \o/
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; |
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
|
4 | var OP_LOADNIL = 3; |
0 | 5 | var OP_GETGLOBAL = 5; |
6 | 6 | var OP_SETGLOBAL = 7; |
0 | 7 | 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
|
8 | var OP_RETURN = 30; |
0 | 9 | |
8 | 10 | var debugMode = false; |
11 | ||
0 | 12 | function LValue(type, value) |
13 | { | |
14 | this.type = type||"nil"; | |
15 | this.value = value||null; | |
16 | } | |
17 | ||
18 | LValue.prototype = { | |
19 | call: function (args) | |
20 | { | |
3
6f338fbf0abc
Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
21 | if(this.type == "function") |
6f338fbf0abc
Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
22 | return this.value; |
6f338fbf0abc
Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
23 | else |
6f338fbf0abc
Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
24 | throw "Attempt to call a " + this.type + " value"; |
0 | 25 | }, |
26 | index: function (key) | |
27 | { | |
28 | if(this.type == "table") | |
29 | { | |
4
0eda73eda4ae
Return nil for non-existent table keys
Matthew Wild <mwild1@gmail.com>
parents:
3
diff
changeset
|
30 | var val = this.value[key.value]; |
0eda73eda4ae
Return nil for non-existent table keys
Matthew Wild <mwild1@gmail.com>
parents:
3
diff
changeset
|
31 | if(typeof(val) == "undefined") |
0eda73eda4ae
Return nil for non-existent table keys
Matthew Wild <mwild1@gmail.com>
parents:
3
diff
changeset
|
32 | return new LValue("nil", null); |
0eda73eda4ae
Return nil for non-existent table keys
Matthew Wild <mwild1@gmail.com>
parents:
3
diff
changeset
|
33 | return val; |
0 | 34 | } |
7
00ec5f6e7579
Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents:
6
diff
changeset
|
35 | else |
00ec5f6e7579
Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents:
6
diff
changeset
|
36 | throw "Attempt to index a " + this.type + " value"; |
0 | 37 | }, |
38 | setIndex: function (key, value) | |
39 | { | |
40 | if(this.type == "table") | |
41 | { | |
42 | this.value[key.value] = value; | |
43 | } | |
7
00ec5f6e7579
Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents:
6
diff
changeset
|
44 | else |
00ec5f6e7579
Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents:
6
diff
changeset
|
45 | throw "Attempt to index a " + this.type + " value"; |
0 | 46 | } |
47 | }; | |
48 | ||
49 | function LValueFromString(string) | |
50 | { | |
51 | return new LValue("string", string); | |
52 | } | |
53 | ||
54 | function LValueFromFunction(func) | |
55 | { | |
56 | return new LValue("function", func); | |
57 | } | |
58 | ||
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
59 | function LBinaryChunk(chunk) |
0 | 60 | { |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
61 | this.chunk = chunk; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
62 | this.pos = 12; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
63 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
64 | this.sourceName = this.readString(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
65 | this.lineDefined = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
66 | this.lastLineDefined = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
67 | this.numUpvalues = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
68 | this.numParameters = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
69 | this.isVararg = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
70 | this.maxStackSize = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
71 | |
0 | 72 | this.instructions = []; |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
73 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
74 | this.numInstructions = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
75 | for(var i=0;i<this.numInstructions;i++) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
76 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
77 | var ins = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
78 | this.instructions.push([ |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
79 | ins&0x3F, // Opcode |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
80 | (ins>>6)&0xFF, // Field A |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
81 | (ins>>23)&0x1FF, // Field B |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
82 | (ins>>14)&0x1FF // Field C |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
83 | ]); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
84 | if(debugMode) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
85 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
86 | var pi = this.instructions[this.instructions.length-1]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
87 | 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)); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
88 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
89 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
90 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
91 | this.constants = []; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
92 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
93 | this.numConstants = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
94 | for(var i=0;i<this.numConstants;i++) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
95 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
96 | var type = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
97 | switch(type) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
98 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
99 | case 0: // Nil |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
100 | this.constants.push(new LValue("nil", null)); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
101 | break; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
102 | case 1: // Boolean |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
103 | this.constants.push(new LValue("boolean", this.readByte())); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
104 | break; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
105 | case 3: // Number |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
106 | break; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
107 | case 4: // String |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
108 | this.constants.push(LValueFromString(this.readString())); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
109 | break; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
110 | default: |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
111 | throw "Invalid constant type "+type+" in bytecode"; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
112 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
113 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
114 | |
0 | 115 | return this; |
116 | } | |
117 | ||
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
118 | LBinaryChunk.prototype = { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
119 | readBytes: function (n) |
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 | return this.chunk.slice(this.pos, this.pos+=n); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
122 | }, |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
123 | readByte: function () |
0 | 124 | { |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
125 | return this.readBytes(1).charCodeAt(0); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
126 | }, |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
127 | readInt: function () |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
128 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
129 | //FIXME: Endianness |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
130 | return this.readByte() | (this.readByte()<<8) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
131 | | (this.readByte()<<16) | (this.readByte()<<24); |
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 | readString: function () |
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 | var len = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
136 | return this.readBytes(len).substring(0,len-1); |
0 | 137 | }, |
138 | }; | |
139 | ||
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
140 | function INS_OPCODE(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
141 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
142 | return ins[0]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
143 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
144 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
145 | function INS_A(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
146 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
147 | return ins[1]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
148 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
149 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
150 | function INS_B(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
151 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
152 | return ins[2]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
153 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
154 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
155 | function INS_C(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
156 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
157 | return ins[3]; |
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 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
160 | function INS_Bx(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
161 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
162 | return ((INS_C(ins))|(INS_B(ins)<<9)); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
163 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
164 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
165 | function INS_sBx(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
166 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
167 | return INS_Bx(ins)+0x1FFFE; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
168 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
169 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
170 | function LFunction(chunk, env) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
171 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
172 | function F() {}; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
173 | F.prototype = chunk; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
174 | var o = new F(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
175 | o.environment = env; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
176 | return o; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
177 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
178 | |
0 | 179 | function LVM() |
180 | { | |
181 | this.callstack = []; | |
182 | this.stack = []; | |
183 | return this; | |
184 | } | |
185 | ||
186 | LVM.prototype = { | |
187 | run: function (lfFunction) | |
188 | { | |
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
|
189 | this.frame = {f:lfFunction,pc:0,reg:[]}; |
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
|
190 | this.callstack.push(this.frame); |
0 | 191 | var instruction; |
192 | while(this.callstack.length>0) | |
193 | { | |
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
|
194 | instruction = this.frame.f.instructions[this.frame.pc++]; |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
195 | if(debugMode) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
196 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
197 | sys.puts("PC: "+(this.frame.pc-1)+" OP: "+instruction[0]); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
198 | sys.puts("STACK: "+JSON.stringify(this.frame.reg)); |
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 | switch(INS_OPCODE(instruction)) |
0 | 201 | { |
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
|
202 | case OP_MOVE: |
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
|
203 | this.frame.reg[instruction[1]] = this.frame.reg[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
|
204 | 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
|
205 | case OP_LOADNIL: |
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
|
206 | for(var i = instruction[1];i<=instruction[2];i++) |
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
|
207 | this.frame.reg[i] = new LValue("nil", null); |
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
|
208 | break; |
0 | 209 | case OP_GETGLOBAL: |
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
|
210 | var name = this.frame.f.constants[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
|
211 | this.frame.reg[instruction[1]] = this.frame.f.environment.index(name); |
0 | 212 | break; |
6 | 213 | case OP_SETGLOBAL: |
214 | var name = this.frame.f.constants[instruction[2]]; | |
215 | this.frame.f.environment.setIndex(name, this.frame.reg[instruction[1]]); | |
216 | break; | |
0 | 217 | case OP_LOADK: |
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
|
218 | var value = this.frame.f.constants[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
|
219 | this.frame.reg[instruction[1]] = value; |
0 | 220 | break; |
221 | case OP_CALL: | |
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
|
222 | var f = this.frame.reg[instruction[1]].call(); // return JS or LValue |
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
|
223 | var args = this.frame.reg.splice(instruction[1]+1, instruction[1]+(instruction[2]-1)); |
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
|
224 | 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
|
225 | { |
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
|
226 | // 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
|
227 | 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
|
228 | } |
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
|
229 | 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
|
230 | { |
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
|
231 | // Lua 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
|
232 | } |
0 | 233 | break; |
234 | case OP_RETURN: | |
235 | this.callstack.pop(); | |
236 | break; | |
237 | default: | |
238 | } | |
239 | } | |
240 | } | |
241 | }; | |
242 | ||
243 | 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
|
244 | |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
245 | var fs=require("fs"); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
246 | var sys=require("sys"); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
247 | var c = new LBinaryChunk(fs.readFileSync("luac.out", "binary")); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
248 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
249 | 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
|
250 | |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
251 | var print; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
252 | if(typeof(document) == "object") |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
253 | print = function (a) { document.write(a+"<br/>") }; // Browser |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
254 | else |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
255 | 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
|
256 | |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
257 | 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
|
258 | |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
259 | var f = new LFunction(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
|
260 | |
5 | 261 | try{ |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
262 | testvm.run(f); |
5 | 263 | } |
264 | catch(e) | |
265 | { | |
266 | print("Error: " + e); | |
267 | } |