Sat, 22 May 2010 20:05:58 +0100
Remove some, hmm, "debugging" code :)
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; |
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
|
5 | var OP_GETUPVAL = 4; |
0 | 6 | var OP_GETGLOBAL = 5; |
6 | 7 | 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
|
8 | var OP_SETUPVAL = 8; |
0 | 9 | 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
|
10 | var OP_RETURN = 30; |
15
5240eaff785f
Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents:
14
diff
changeset
|
11 | var OP_CLOSURE = 36; |
0 | 12 | |
8 | 13 | var debugMode = false; |
14 | ||
0 | 15 | function LValue(type, value) |
16 | { | |
17 | this.type = type||"nil"; | |
18 | this.value = value||null; | |
19 | } | |
20 | ||
21 | LValue.prototype = { | |
22 | call: function (args) | |
23 | { | |
3
6f338fbf0abc
Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
24 | if(this.type == "function") |
6f338fbf0abc
Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
25 | return this.value; |
6f338fbf0abc
Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
26 | else |
6f338fbf0abc
Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
27 | throw "Attempt to call a " + this.type + " value"; |
0 | 28 | }, |
29 | index: function (key) | |
30 | { | |
31 | if(this.type == "table") | |
32 | { | |
4
0eda73eda4ae
Return nil for non-existent table keys
Matthew Wild <mwild1@gmail.com>
parents:
3
diff
changeset
|
33 | var val = this.value[key.value]; |
0eda73eda4ae
Return nil for non-existent table keys
Matthew Wild <mwild1@gmail.com>
parents:
3
diff
changeset
|
34 | if(typeof(val) == "undefined") |
0eda73eda4ae
Return nil for non-existent table keys
Matthew Wild <mwild1@gmail.com>
parents:
3
diff
changeset
|
35 | return new LValue("nil", null); |
0eda73eda4ae
Return nil for non-existent table keys
Matthew Wild <mwild1@gmail.com>
parents:
3
diff
changeset
|
36 | return val; |
0 | 37 | } |
7
00ec5f6e7579
Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents:
6
diff
changeset
|
38 | else |
00ec5f6e7579
Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents:
6
diff
changeset
|
39 | throw "Attempt to index a " + this.type + " value"; |
0 | 40 | }, |
41 | setIndex: function (key, value) | |
42 | { | |
43 | if(this.type == "table") | |
44 | { | |
45 | this.value[key.value] = value; | |
46 | } | |
7
00ec5f6e7579
Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents:
6
diff
changeset
|
47 | else |
00ec5f6e7579
Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents:
6
diff
changeset
|
48 | throw "Attempt to index a " + this.type + " value"; |
0 | 49 | } |
50 | }; | |
51 | ||
52 | function LValueFromString(string) | |
53 | { | |
54 | return new LValue("string", string); | |
55 | } | |
56 | ||
57 | function LValueFromFunction(func) | |
58 | { | |
59 | return new LValue("function", func); | |
60 | } | |
61 | ||
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
|
62 | function LBinaryChunk(chunk, start) |
0 | 63 | { |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
64 | 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
|
65 | this.pos = start||12; |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
66 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
67 | this.sourceName = this.readString(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
68 | this.lineDefined = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
69 | this.lastLineDefined = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
70 | this.numUpvalues = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
71 | this.numParameters = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
72 | this.isVararg = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
73 | this.maxStackSize = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
74 | |
0 | 75 | this.instructions = []; |
9
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 | this.numInstructions = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
78 | for(var i=0;i<this.numInstructions;i++) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
79 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
80 | var ins = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
81 | this.instructions.push([ |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
82 | ins&0x3F, // Opcode |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
83 | (ins>>6)&0xFF, // Field A |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
84 | (ins>>23)&0x1FF, // Field B |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
85 | (ins>>14)&0x1FF // Field C |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
86 | ]); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
87 | if(debugMode) |
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 | var pi = this.instructions[this.instructions.length-1]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
90 | 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
|
91 | } |
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 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
94 | this.constants = []; |
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 | this.numConstants = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
97 | for(var i=0;i<this.numConstants;i++) |
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 | var type = this.readByte(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
100 | switch(type) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
101 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
102 | case 0: // Nil |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
103 | this.constants.push(new LValue("nil", null)); |
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 1: // Boolean |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
106 | this.constants.push(new LValue("boolean", this.readByte())); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
107 | break; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
108 | case 3: // Number |
12
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
109 | this.constants.push(new LValue("number", this.readNumber())); |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
110 | break; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
111 | case 4: // String |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
112 | this.constants.push(LValueFromString(this.readString())); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
113 | break; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
114 | default: |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
115 | throw "Invalid constant type "+type+" in bytecode"; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
116 | } |
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 | |
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
|
119 | 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
|
120 | |
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
|
121 | 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
|
122 | 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
|
123 | { |
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
|
124 | 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
|
125 | 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
|
126 | 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
|
127 | } |
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
|
128 | |
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
|
129 | 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
|
130 | |
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
|
131 | 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
|
132 | 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
|
133 | { |
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
|
134 | 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
|
135 | } |
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
|
136 | |
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
|
137 | 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
|
138 | 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
|
139 | 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
|
140 | { |
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
|
141 | 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
|
142 | } |
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
|
143 | |
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
|
144 | 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
|
145 | 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
|
146 | 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
|
147 | { |
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
|
148 | 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
|
149 | } |
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
|
150 | |
0 | 151 | return this; |
152 | } | |
153 | ||
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
154 | LBinaryChunk.prototype = { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
155 | readBytes: function (n) |
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 this.chunk.slice(this.pos, this.pos+=n); |
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 | readByte: function () |
0 | 160 | { |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
161 | return this.readBytes(1).charCodeAt(0); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
162 | }, |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
163 | readInt: function () |
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 | //FIXME: Endianness |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
166 | return this.readByte() | (this.readByte()<<8) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
167 | | (this.readByte()<<16) | (this.readByte()<<24); |
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 | readString: function () |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
170 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
171 | var len = this.readInt(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
172 | return this.readBytes(len).substring(0,len-1); |
0 | 173 | }, |
12
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
174 | readNumber: function () |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
175 | { |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
176 | //FIXME: Endianness |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
177 | 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
|
178 | 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
|
179 | |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
180 | var sign = (bytes[0]>>7)&0x1; |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
181 | 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
|
182 | |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
183 | 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
|
184 | + (bytes[2] * Math.pow(2,40)) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
185 | + (bytes[3] * Math.pow(2,32)) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
186 | + (bytes[4] * Math.pow(2,24)) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
187 | + (bytes[5] * Math.pow(2,16)) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
188 | + (bytes[6] * Math.pow(2,8)) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
189 | + bytes[7]; |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
190 | |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
191 | if(exp != 0x000 && exp != 0x7FF) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
192 | { |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
193 | 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
|
194 | return n; |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
195 | } |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
196 | else if(exp == 0x000) |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
197 | { |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
198 | return sign*0; |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
199 | } |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
200 | else |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
201 | return frac==0?sign*Infinity:NaN; |
7d748aba47ab
Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents:
11
diff
changeset
|
202 | } |
0 | 203 | }; |
204 | ||
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
205 | function INS_OPCODE(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
206 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
207 | return ins[0]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
208 | } |
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 | function INS_A(ins) |
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 | return ins[1]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
213 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
214 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
215 | function INS_B(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
216 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
217 | return ins[2]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
218 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
219 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
220 | function INS_C(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
221 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
222 | return ins[3]; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
223 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
224 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
225 | function INS_Bx(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
226 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
227 | return ((INS_C(ins))|(INS_B(ins)<<9)); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
228 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
229 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
230 | function INS_sBx(ins) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
231 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
232 | return INS_Bx(ins)+0x1FFFE; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
233 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
234 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
235 | function LFunction(chunk, env) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
236 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
237 | function F() {}; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
238 | F.prototype = chunk; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
239 | var o = new F(); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
240 | 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
|
241 | 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
|
242 | o.upvalues = []; |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
243 | return o; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
244 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
245 | |
0 | 246 | function LVM() |
247 | { | |
248 | this.callstack = []; | |
249 | this.stack = []; | |
250 | return this; | |
251 | } | |
252 | ||
253 | LVM.prototype = { | |
254 | run: function (lfFunction) | |
255 | { | |
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 | 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
|
257 | this.callstack.push(this.frame); |
0 | 258 | var instruction; |
259 | while(this.callstack.length>0) | |
260 | { | |
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
|
261 | instruction = this.frame.f.instructions[this.frame.pc++]; |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
262 | if(debugMode) |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
263 | { |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
264 | sys.puts("PC: "+(this.frame.pc-1)+" OP: "+instruction[0]); |
21
9b5cc503bc31
Switch from JSON.stringify for debug output to sys.inspect which doesn't bail out on circular references
Matthew Wild <mwild1@gmail.com>
parents:
20
diff
changeset
|
265 | sys.puts("STACK: "+sys.inspect(this.frame.reg)); |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
266 | } |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
267 | switch(INS_OPCODE(instruction)) |
0 | 268 | { |
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
|
269 | case OP_MOVE: |
10
ce2f27fa25a4
Use new notation for accessing instruction fields
Matthew Wild <mwild1@gmail.com>
parents:
9
diff
changeset
|
270 | this.frame.reg[INS_A(instruction)] = this.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
|
271 | 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
|
272 | case OP_LOADNIL: |
10
ce2f27fa25a4
Use new notation for accessing instruction fields
Matthew Wild <mwild1@gmail.com>
parents:
9
diff
changeset
|
273 | for(var i = INS_A(instruction);i<=INS_B(instruction);i++) |
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
|
274 | 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
|
275 | 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
|
276 | case OP_GETUPVAL: |
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
|
277 | this.frame.reg[INS_A(instruction)] = this.frame.f.upvalues[INS_B(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
|
278 | break; |
0 | 279 | case OP_GETGLOBAL: |
10
ce2f27fa25a4
Use new notation for accessing instruction fields
Matthew Wild <mwild1@gmail.com>
parents:
9
diff
changeset
|
280 | var name = this.frame.f.constants[INS_Bx(instruction)]; |
ce2f27fa25a4
Use new notation for accessing instruction fields
Matthew Wild <mwild1@gmail.com>
parents:
9
diff
changeset
|
281 | this.frame.reg[INS_A(instruction)] = this.frame.f.environment.index(name); |
0 | 282 | 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
|
283 | case OP_SETUPVAL: |
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 | throw "Setting upvalues not implemented yet, sorry :)"; |
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
|
285 | break; |
6 | 286 | case OP_SETGLOBAL: |
10
ce2f27fa25a4
Use new notation for accessing instruction fields
Matthew Wild <mwild1@gmail.com>
parents:
9
diff
changeset
|
287 | var name = this.frame.f.constants[INS_Bx(instruction)]; |
6 | 288 | this.frame.f.environment.setIndex(name, this.frame.reg[instruction[1]]); |
289 | break; | |
0 | 290 | case OP_LOADK: |
10
ce2f27fa25a4
Use new notation for accessing instruction fields
Matthew Wild <mwild1@gmail.com>
parents:
9
diff
changeset
|
291 | var value = this.frame.f.constants[INS_Bx(instruction)]; |
ce2f27fa25a4
Use new notation for accessing instruction fields
Matthew Wild <mwild1@gmail.com>
parents:
9
diff
changeset
|
292 | this.frame.reg[INS_A(instruction)] = value; |
0 | 293 | break; |
294 | case OP_CALL: | |
10
ce2f27fa25a4
Use new notation for accessing instruction fields
Matthew Wild <mwild1@gmail.com>
parents:
9
diff
changeset
|
295 | var f = this.frame.reg[INS_A(instruction)].call(); // 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
|
296 | var A = INS_A(instruction), B = INS_B(instruction), undefined; |
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
|
297 | var args = this.frame.reg.slice(A+1, B==0?undefined:(A+B)); |
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
|
298 | 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
|
299 | { |
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
|
300 | // 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
|
301 | 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
|
302 | } |
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
|
303 | 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
|
304 | { |
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
|
305 | // Lua function |
19
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
306 | this.frame = {f:f,pc:0,reg:args, |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
307 | retAt:INS_A(instruction),retCount:INS_C(instruction)}; |
16
9c8710ea2a5a
Implement OP_CALL for Lua functions (no return values yet)
Matthew Wild <mwild1@gmail.com>
parents:
15
diff
changeset
|
308 | this.callstack.push(this.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
|
309 | } |
0 | 310 | break; |
15
5240eaff785f
Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents:
14
diff
changeset
|
311 | case OP_CLOSURE: |
5240eaff785f
Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents:
14
diff
changeset
|
312 | var prototype_id = INS_Bx(instruction); |
5240eaff785f
Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents:
14
diff
changeset
|
313 | var chunk = this.frame.f.chunk.prototypes[prototype_id]; |
5240eaff785f
Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents:
14
diff
changeset
|
314 | var f = new LFunction(chunk, this.frame.f.environment); |
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
|
315 | 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
|
316 | { |
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
|
317 | var upval_instruction = this.frame.f.instructions[this.frame.pc++]; |
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
|
318 | 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
|
319 | { |
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
|
320 | case OP_MOVE: |
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
|
321 | f.upvalues[i] = this.frame.reg[INS_B(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
|
322 | 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
|
323 | case OP_GETUPVAL: |
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
|
324 | f.upvalues[i] = this.frame.f.upvalues[INS_B(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
|
325 | 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
|
326 | 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
|
327 | 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
|
328 | } |
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 | } |
15
5240eaff785f
Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents:
14
diff
changeset
|
330 | this.frame.reg[INS_A(instruction)] = new LValue("function", f); |
5240eaff785f
Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents:
14
diff
changeset
|
331 | break; |
0 | 332 | case OP_RETURN: |
19
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
333 | var oldFrame = this.callstack.pop(); |
17
ac02246fc1d1
Fix OP_RETURN to update this.frame
Matthew Wild <mwild1@gmail.com>
parents:
16
diff
changeset
|
334 | this.frame = this.callstack[this.callstack.length-1]; |
19
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
335 | if(this.frame) |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
336 | { |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
337 | var rets; |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
338 | if(INS_B(instruction) == 0) |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
339 | rets = oldFrame.reg.slice(INS_A(instruction)); |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
340 | else |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
341 | rets = oldFrame.reg.slice(INS_A(instruction),INS_A(instruction)+(INS_B(instruction)-1)); |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
342 | var i; |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
343 | for(i=0;(oldFrame.retCount == 0||i<oldFrame.retCount)&&i<rets.length;i++) |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
344 | this.frame.reg[oldFrame.retAt+i] = rets[i]; |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
345 | if(oldFrame.retAt+i<this.frame.reg.length) |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
346 | this.frame.reg.splice(0,oldFrame.retAt+i); |
8c9c1752272b
OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents:
18
diff
changeset
|
347 | } |
0 | 348 | break; |
349 | default: | |
11
1b3267149cbd
Throw error on unhandled opcodes
Matthew Wild <mwild1@gmail.com>
parents:
10
diff
changeset
|
350 | throw "Unhandled opcode: "+INS_OPCODE(instruction); |
0 | 351 | } |
352 | } | |
353 | } | |
354 | }; | |
355 | ||
356 | 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
|
357 | |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
358 | var fs=require("fs"); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
359 | var sys=require("sys"); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
360 | var c = new LBinaryChunk(fs.readFileSync("luac.out", "binary")); |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
361 | |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
362 | 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
|
363 | |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
364 | var print; |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
365 | if(typeof(document) == "object") |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
366 | print = function (a) { document.write(a+"<br/>") }; // Browser |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
367 | else |
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
368 | 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
|
369 | |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
370 | 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
|
371 | |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
372 | 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
|
373 | |
5 | 374 | try{ |
9
3f055c9ab80e
Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents:
8
diff
changeset
|
375 | testvm.run(f); |
5 | 376 | } |
377 | catch(e) | |
378 | { | |
379 | print("Error: " + e); | |
380 | } |