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