lvm.js

Tue, 06 Apr 2010 14:51:25 +0100

author
Matthew Wild <mwild1@gmail.com>
date
Tue, 06 Apr 2010 14:51:25 +0100
changeset 11
1b3267149cbd
parent 10
ce2f27fa25a4
child 12
7d748aba47ab
permissions
-rw-r--r--

Throw error on unhandled opcodes

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

mercurial