lvm.js

Fri, 19 Nov 2010 13:09:25 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Fri, 19 Nov 2010 13:09:25 +0000
changeset 72
dc73a60b3c06
parent 71
768d8fb574bb
child 73
6b43d68abc94
permissions
-rw-r--r--

Give LValue an add() method, to eventually respect metamethods

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;
39
53d5bf6654ba Implement OP_LOADBOOL
Matthew Wild <mwild1@gmail.com>
parents: 38
diff changeset
4 var OP_LOADBOOL = 2;
2
253863ece36f Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents: 1
diff changeset
5 var OP_LOADNIL = 3;
20
977ae93f612c Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents: 19
diff changeset
6 var OP_GETUPVAL = 4;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 var OP_GETGLOBAL = 5;
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
8 var OP_GETTABLE = 6;
6
418fd175eaed Implement OP_SETGLOBAL
Matthew Wild <mwild1@gmail.com>
parents: 5
diff changeset
9 var OP_SETGLOBAL = 7;
20
977ae93f612c Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents: 19
diff changeset
10 var OP_SETUPVAL = 8;
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
11 var OP_SETTABLE = 9;
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
12 var OP_NEWTABLE = 10;
36
9e7b57b0b78f Implement OP_SELF
Matthew Wild <mwild1@gmail.com>
parents: 35
diff changeset
13 var OP_SELF = 11;
58
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
14 var OP_ADD = 12;
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
15 var OP_SUB = 13;
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
16 var OP_JMP = 22;
58
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
17 var OP_LT = 24;
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
18 var OP_TEST = 26;
59
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
19 var OP_TESTSET = 27;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20 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
21 var OP_RETURN = 30;
34
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
22 var OP_FORLOOP = 31;
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
23 var OP_FORPREP = 32;
15
5240eaff785f Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents: 14
diff changeset
24 var OP_CLOSURE = 36;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25
8
e7de6d1fee96 Add debugMode switch
Matthew Wild <mwild1@gmail.com>
parents: 7
diff changeset
26 var debugMode = false;
e7de6d1fee96 Add debugMode switch
Matthew Wild <mwild1@gmail.com>
parents: 7
diff changeset
27
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28 function LValue(type, value)
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 {
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30 this.type = type||"nil";
37
62c1d9bf3000 Allow LValues with a value of 'false' to be create (it was converted to 'null')
Matthew Wild <mwild1@gmail.com>
parents: 36
diff changeset
31 this.value = value;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34 LValue.prototype = {
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35 call: function (args)
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 {
49
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
37 var f = this.precall();
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
38 if(typeof(f) == "function")
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
39 var ret = f.apply(this.vm, args?args.map(function (a) { return a.value; }):[]);
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
40 else
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
41 var ret = this.vm.call(f);
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
42 if(typeof(ret) == "undefined")
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
43 ret = [];
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
44 return ret;
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
45 },
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
46 precall: function ()
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
47 {
3
6f338fbf0abc Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents: 2
diff changeset
48 if(this.type == "function")
6f338fbf0abc Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents: 2
diff changeset
49 return this.value;
6f338fbf0abc Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents: 2
diff changeset
50 else
6f338fbf0abc Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents: 2
diff changeset
51 throw "Attempt to call a " + this.type + " value";
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 },
54
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
53 index: function (key, raw)
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 {
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 if(this.type == "table")
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56 {
54
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
57 var val;
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
58 if(key.value in this.value)
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
59 return this.value[key.value];
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
60 else if(raw != true && this.metatable && this.metatable.type != "nil")
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
61 {
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
62 var __index = this.metatable.index(new LValue("string", "__index"));
60
430a0b155703 Support for tables in __index
Matthew Wild <mwild1@gmail.com>
parents: 59
diff changeset
63 if(__index.type == "function")
54
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
64 {
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
65 return LValueFromValue(__index.call([this, key])[0]);
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
66 }
60
430a0b155703 Support for tables in __index
Matthew Wild <mwild1@gmail.com>
parents: 59
diff changeset
67 else if(__index.type != "nil")
430a0b155703 Support for tables in __index
Matthew Wild <mwild1@gmail.com>
parents: 59
diff changeset
68 return __index.index(key);
54
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
69 }
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
70 return new LValue("nil", null);
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
71 }
7
00ec5f6e7579 Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents: 6
diff changeset
72 else
00ec5f6e7579 Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents: 6
diff changeset
73 throw "Attempt to index a " + this.type + " value";
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 },
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 setIndex: function (key, value)
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76 {
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77 if(this.type == "table")
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78 {
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
79 this.value[key.value] = value;
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 }
7
00ec5f6e7579 Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents: 6
diff changeset
81 else
00ec5f6e7579 Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents: 6
diff changeset
82 throw "Attempt to index a " + this.type + " value";
53
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
83 },
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
84 setMetatable: function (metatable)
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
85 {
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
86 if(metatable.type == "table")
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
87 this.metatable = metatable;
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
88 else if(metatable.type == "nil")
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
89 this.metatable = null;
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
90 else
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
91 throw "Attempt to set a "+metatable.type+" value as a metatable";
61
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
92 },
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
93 toString: function ()
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
94 {
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
95 switch(this.type)
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
96 {
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
97 case "nil":
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
98 return "nil";
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
99 default:
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
100 return this.value.toString();
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
101 }
72
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
102 },
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
103 add: function (op2)
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
104 {
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
105 var metamethod;
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
106 var __add = LValueFromString("__add");
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
107 if(this.metatable)
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
108 metamethod = this.metatable.index(__add);
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
109 if((!metamethod || metamethod.type == "nil") && op2.metatable)
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
110 metamethod = op2.metatable.index(__add);
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
111 if(metamethod && metamethod.type != "nil")
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
112 {
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
113 }
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
114 else if((this.type == "number" || this.type == "string")
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
115 && (op2.type == "number" || op2.type == "string"))
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
116 {
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
117 // Plain addition
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
118 return new LValue("number", parseFloat(this.value, 10) + parseFloat(op2.value));
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
119 }
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
120 else
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
121 throw "Attempt to perform arithmetic on a "+this.type+" and "+op2.type;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
122 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
123 };
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
124
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
125 function LValueFromString(string)
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
126 {
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
127 return new LValue("string", string);
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
128 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
129
49
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
130 function LValueFromFunction(vm, func)
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
131 {
49
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
132 var val = new LValue("function", func);
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
133 val.vm = vm;
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
134 return val;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
135 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
136
27
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
137 function LValueFromValue(value)
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
138 {
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
139 switch(typeof(value))
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
140 {
62
8cb403eeea79 Support for numbers in LValueFromValue()
Matthew Wild <mwild1@gmail.com>
parents: 61
diff changeset
141 case "number":
8cb403eeea79 Support for numbers in LValueFromValue()
Matthew Wild <mwild1@gmail.com>
parents: 61
diff changeset
142 return new LValue("number", value);
27
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
143 case "string":
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
144 return new LValueFromString(value);
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
145 case "function":
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
146 return new LValueFromFunction(value);
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
147 case "object":
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
148 if(value == null)
50
4612c85cdc01 LValueFromValue handles undefined and objects/arrays
Matthew Wild <mwild1@gmail.com>
parents: 49
diff changeset
149 return new LValue("nil", null);
4612c85cdc01 LValueFromValue handles undefined and objects/arrays
Matthew Wild <mwild1@gmail.com>
parents: 49
diff changeset
150 else
4612c85cdc01 LValueFromValue handles undefined and objects/arrays
Matthew Wild <mwild1@gmail.com>
parents: 49
diff changeset
151 return new LValue("table", value);
4612c85cdc01 LValueFromValue handles undefined and objects/arrays
Matthew Wild <mwild1@gmail.com>
parents: 49
diff changeset
152 case "undefined":
4612c85cdc01 LValueFromValue handles undefined and objects/arrays
Matthew Wild <mwild1@gmail.com>
parents: 49
diff changeset
153 return new LValue("nil", null);
27
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
154 default:
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
155 sys.puts( "Not able to convert type " +
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
156 typeof(value)+" from Javascript to Lua: "+sys.inspect(value));
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
157 throw "Not able to convert type " +
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
158 typeof(value)+" from Javascript to Lua";
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
159 }
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
160 }
35a2203253a6 New LValueFromValue() to convert from any Javascript value (almost) to a LValue
Matthew Wild <mwild1@gmail.com>
parents: 26
diff changeset
161
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
162 function LBinaryChunk(chunk, start)
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
163 {
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
164 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
165 this.pos = start||12;
9
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 this.sourceName = this.readString();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
168 this.lineDefined = this.readInt();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
169 this.lastLineDefined = this.readInt();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
170 this.numUpvalues = this.readByte();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
171 this.numParameters = this.readByte();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
172 this.isVararg = this.readByte();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
173 this.maxStackSize = this.readByte();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
174
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
175 this.instructions = [];
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
176
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
177 this.numInstructions = this.readInt();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
178 for(var i=0;i<this.numInstructions;i++)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
179 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
180 var ins = this.readInt();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
181 this.instructions.push([
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
182 ins&0x3F, // Opcode
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
183 (ins>>6)&0xFF, // Field A
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
184 (ins>>23)&0x1FF, // Field B
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
185 (ins>>14)&0x1FF // Field C
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
186 ]);
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
187 if(debugMode)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
188 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
189 var pi = this.instructions[this.instructions.length-1];
31
bc58527bac34 Print sBx field in bytecode dump (for debugging)
Matthew Wild <mwild1@gmail.com>
parents: 30
diff changeset
190 sys.puts("Pos: "+(this.pos-4)+" Ins: "+ins+" OP: "+INS_OPCODE(pi)+" A: "+INS_A(pi)+" B: "+INS_B(pi)+" C: "+INS_C(pi)+" Bx: "+INS_Bx(pi)+" sBx: "+(INS_Bx(pi)-0x1FFFE));
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
191 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
192 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
193
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
194 this.constants = [];
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
195
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
196 this.numConstants = this.readInt();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
197 for(var i=0;i<this.numConstants;i++)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
198 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
199 var type = this.readByte();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
200 switch(type)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
201 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
202 case 0: // Nil
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
203 this.constants.push(new LValue("nil", null));
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
204 break;
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
205 case 1: // Boolean
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
206 this.constants.push(new LValue("boolean", this.readByte()));
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
207 break;
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
208 case 3: // Number
12
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
209 this.constants.push(new LValue("number", this.readNumber()));
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
210 break;
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
211 case 4: // String
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
212 this.constants.push(LValueFromString(this.readString()));
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
213 break;
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
214 default:
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
215 throw "Invalid constant type "+type+" in bytecode";
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 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
218
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
219 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
220
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
221 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
222 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
223 {
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
224 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
225 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
226 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
227 }
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
228
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
229 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
230
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
231 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
232 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
233 {
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
234 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
235 }
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
236
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
237 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
238 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
239 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
240 {
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
241 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
242 }
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
243
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
244 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
245 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
246 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
247 {
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
248 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
249 }
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
250
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
251 return this;
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
252 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
253
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
254 LBinaryChunk.prototype = {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
255 readBytes: function (n)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
256 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
257 return this.chunk.slice(this.pos, this.pos+=n);
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
258 },
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
259 readByte: function ()
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
260 {
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
261 return this.readBytes(1).charCodeAt(0);
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
262 },
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
263 readInt: function ()
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 //FIXME: Endianness
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
266 return this.readByte() | (this.readByte()<<8)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
267 | (this.readByte()<<16) | (this.readByte()<<24);
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
268 },
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
269 readString: function ()
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
270 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
271 var len = this.readInt();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
272 return this.readBytes(len).substring(0,len-1);
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
273 },
12
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
274 readNumber: function ()
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
275 {
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
276 //FIXME: Endianness
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
277 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
278 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
279
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
280 var sign = (bytes[0]>>7)&0x1;
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
281 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
282
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
283 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
284 + (bytes[2] * Math.pow(2,40))
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
285 + (bytes[3] * Math.pow(2,32))
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
286 + (bytes[4] * Math.pow(2,24))
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
287 + (bytes[5] * Math.pow(2,16))
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
288 + (bytes[6] * Math.pow(2,8))
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
289 + bytes[7];
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
290
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
291 if(exp != 0x000 && exp != 0x7FF)
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
292 {
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
293 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
294 return n;
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
295 }
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
296 else if(exp == 0x000)
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
297 {
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
298 return sign*0;
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
299 }
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
300 else
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
301 return frac==0?sign*Infinity:NaN;
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
302 }
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
303 };
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
304
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
305 function INS_OPCODE(ins)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
306 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
307 return ins[0];
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
308 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
309
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
310 function INS_A(ins)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
311 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
312 return ins[1];
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
313 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
314
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
315 function INS_B(ins)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
316 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
317 return ins[2];
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
318 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
319
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
320 function INS_C(ins)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
321 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
322 return ins[3];
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
323 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
324
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
325 function INS_Bx(ins)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
326 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
327 return ((INS_C(ins))|(INS_B(ins)<<9));
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
328 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
329
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
330 function INS_sBx(ins)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
331 {
32
035aacc192d8 Fix off-by-one in calculating the value of sBx
Matthew Wild <mwild1@gmail.com>
parents: 31
diff changeset
332 return (INS_Bx(ins)-0x1FFFF);
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
333 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
334
43
ecfa7896af35 Give LFunctions a vm property
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
335 function LFunction(vm, chunk, env)
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
336 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
337 function F() {};
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
338 F.prototype = chunk;
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
339 var o = new F();
43
ecfa7896af35 Give LFunctions a vm property
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
340 o.vm = vm;
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
341 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
342 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
343 o.upvalues = [];
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
344 return o;
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
345 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
346
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
347 function LVM()
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
348 {
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
349 this.callstack = [];
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
350 this.stack = [];
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
351 return this;
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
352 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
353
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
354 LVM.prototype = {
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
355 call: function (lfFunction)
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
356 {
51
b429e7a73de7 More reliable detection of when we're at a native/Lua call boundary
Matthew Wild <mwild1@gmail.com>
parents: 50
diff changeset
357 var frame = {f:lfFunction,pc:0,reg:[],entry:true};
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
358 this.callstack.push(frame);
38
ba347b4b655f Initialise all stack slots to nil when calling a chunk
Matthew Wild <mwild1@gmail.com>
parents: 37
diff changeset
359 for(var i=0;i<lfFunction.maxStackSize;i++)
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
360 frame.reg[i] = new LValue("nil", null);
47
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
361 return this.run(frame);
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
362 },
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
363 run: function(frame)
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
364 {
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
365 var instruction;
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
366 while(this.callstack.length>0)
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
367 {
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
368 instruction = frame.f.instructions[frame.pc++];
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
369 if(debugMode)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
370 {
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
371 sys.puts("PC: "+(frame.pc-1)+" OP: "+instruction[0]);
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
372 sys.puts("STACK: "+sys.inspect(frame.reg));
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
373 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
374 switch(INS_OPCODE(instruction))
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
375 {
2
253863ece36f Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents: 1
diff changeset
376 case OP_MOVE:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
377 frame.reg[INS_A(instruction)] = frame.reg[INS_B(instruction)];
2
253863ece36f Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents: 1
diff changeset
378 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
379 case OP_LOADNIL:
10
ce2f27fa25a4 Use new notation for accessing instruction fields
Matthew Wild <mwild1@gmail.com>
parents: 9
diff changeset
380 for(var i = INS_A(instruction);i<=INS_B(instruction);i++)
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
381 frame.reg[i] = new LValue("nil", null);
2
253863ece36f Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents: 1
diff changeset
382 break;
39
53d5bf6654ba Implement OP_LOADBOOL
Matthew Wild <mwild1@gmail.com>
parents: 38
diff changeset
383 case OP_LOADBOOL:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
384 frame.reg[INS_A(instruction)] = new LValue("boolean", INS_B(instruction)!=0);
39
53d5bf6654ba Implement OP_LOADBOOL
Matthew Wild <mwild1@gmail.com>
parents: 38
diff changeset
385 if(INS_C(instruction)!=0)
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
386 frame.pc++;
39
53d5bf6654ba Implement OP_LOADBOOL
Matthew Wild <mwild1@gmail.com>
parents: 38
diff changeset
387 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
388 case OP_GETUPVAL:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
389 frame.reg[INS_A(instruction)] = frame.f.upvalues[INS_B(instruction)];
20
977ae93f612c Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents: 19
diff changeset
390 break;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
391 case OP_GETGLOBAL:
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
392 var name = frame.f.constants[INS_Bx(instruction)];
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
393 frame.reg[INS_A(instruction)] = frame.f.environment.index(name);
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
394 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
395 case OP_SETUPVAL:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
396 var reg = frame.reg[INS_A(instruction)];
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
397 var upvalue = frame.f.upvalues[INS_B(instruction)];
26
5c7eafb47830 Implement OP_SETUPVALUE \o/
Matthew Wild <mwild1@gmail.com>
parents: 25
diff changeset
398 upvalue.type = reg.type;
5c7eafb47830 Implement OP_SETUPVALUE \o/
Matthew Wild <mwild1@gmail.com>
parents: 25
diff changeset
399 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
400 break;
6
418fd175eaed Implement OP_SETGLOBAL
Matthew Wild <mwild1@gmail.com>
parents: 5
diff changeset
401 case OP_SETGLOBAL:
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
402 var name = frame.f.constants[INS_Bx(instruction)];
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
403 frame.f.environment.setIndex(name, frame.reg[instruction[1]]);
6
418fd175eaed Implement OP_SETGLOBAL
Matthew Wild <mwild1@gmail.com>
parents: 5
diff changeset
404 break;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
405 case OP_LOADK:
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
406 var constant = frame.f.constants[INS_Bx(instruction)];
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
407 frame.reg[INS_A(instruction)] = new LValue(constant.type, constant.value);
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
408 break;
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
409 case OP_NEWTABLE:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
410 frame.reg[INS_A(instruction)] = new LValue("table", {});
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
411 break;
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
412 case OP_GETTABLE:
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
413 var C = INS_C(instruction);
71
768d8fb574bb Change some decimal constants to hex for consistency
Matthew Wild <mwild1@gmail.com>
parents: 68
diff changeset
414 var keysource = (C&0x100)?frame.f.constants:frame.reg;
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
415 var key = keysource[C&0xff];
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
416 var value = frame.reg[INS_B(instruction)].index(key).value;
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
417 frame.reg[INS_A(instruction)] = new LValueFromValue(value);
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
418 break;
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
419 case OP_SETTABLE:
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
420 var C = INS_C(instruction);
71
768d8fb574bb Change some decimal constants to hex for consistency
Matthew Wild <mwild1@gmail.com>
parents: 68
diff changeset
421 var valuesource = (C&0x100)?frame.f.constants:frame.reg;
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
422 var value = valuesource[C&0xff];
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
423
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
424 var B = INS_B(instruction);
71
768d8fb574bb Change some decimal constants to hex for consistency
Matthew Wild <mwild1@gmail.com>
parents: 68
diff changeset
425 var keysource = (B&0x100)?frame.f.constants:frame.reg;
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
426 var key = keysource[B&0xff];
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
427 frame.reg[INS_A(instruction)].setIndex(key, value);
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
428 break;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
429 case OP_CALL:
49
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
430 var f = frame.reg[INS_A(instruction)].precall(); // return JS or LValue
63
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
431 var A = INS_A(instruction), B = INS_B(instruction), C = INS_C(instruction);
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
432 var undefined;
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
433 var args = frame.reg.slice(A+1, B==0?undefined:(A+B));
38
ba347b4b655f Initialise all stack slots to nil when calling a chunk
Matthew Wild <mwild1@gmail.com>
parents: 37
diff changeset
434 for(var i=args.length+1;i<f.maxStackSize;i++)
ba347b4b655f Initialise all stack slots to nil when calling a chunk
Matthew Wild <mwild1@gmail.com>
parents: 37
diff changeset
435 args[i] = new LValue("nil", null);
2
253863ece36f Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents: 1
diff changeset
436 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
437 {
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
438 // JS native function
63
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
439 var ret = f.apply(this, [args]);
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
440 for(var i = 0; i < (C-1); i++) //FIXME: Handle C == 0
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
441 {
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
442 if(i < ret && i < args.length)
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
443 frame.reg[A+i] = args[i];
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
444 else
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
445 frame.reg[A+i] = new LValue("nil", null);
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
446 }
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
447 }
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
448 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
449 {
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
450 // Lua function
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
451 frame = {f:f,pc:0,reg:args,
51
b429e7a73de7 More reliable detection of when we're at a native/Lua call boundary
Matthew Wild <mwild1@gmail.com>
parents: 50
diff changeset
452 retAt:INS_A(instruction),retCount:INS_C(instruction),
b429e7a73de7 More reliable detection of when we're at a native/Lua call boundary
Matthew Wild <mwild1@gmail.com>
parents: 50
diff changeset
453 entry:false};
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
454 this.callstack.push(frame);
2
253863ece36f Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents: 1
diff changeset
455 }
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
456 break;
15
5240eaff785f Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents: 14
diff changeset
457 case OP_CLOSURE:
5240eaff785f Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents: 14
diff changeset
458 var prototype_id = INS_Bx(instruction);
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
459 var chunk = frame.f.chunk.prototypes[prototype_id];
43
ecfa7896af35 Give LFunctions a vm property
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
460 var f = new LFunction(this, chunk, frame.f.environment);
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
461 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
462 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
463 {
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
464 var upval_instruction = frame.f.instructions[frame.pc++];
20
977ae93f612c Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents: 19
diff changeset
465 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
466 {
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
467 case OP_MOVE:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
468 f.upvalues[i] = frame.reg[INS_B(upval_instruction)];
20
977ae93f612c Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents: 19
diff changeset
469 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
470 case OP_GETUPVAL:
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
471 f.upvalues[i] = frame.f.upvalues[INS_B(upval_instruction)];
20
977ae93f612c Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
Matthew Wild <mwild1@gmail.com>
parents: 19
diff changeset
472 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
473 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
474 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
475 }
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
476 }
15
5240eaff785f Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents: 14
diff changeset
477 break;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
478 case OP_RETURN:
19
8c9c1752272b OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents: 18
diff changeset
479 var oldFrame = this.callstack.pop();
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
480 frame = this.callstack[this.callstack.length-1];
47
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
481 var rets;
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
482 if(INS_B(instruction) == 0)
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
483 rets = oldFrame.reg.slice(INS_A(instruction));
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
484 else
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
485 rets = oldFrame.reg.slice(INS_A(instruction),INS_A(instruction)+(INS_B(instruction)-1));
51
b429e7a73de7 More reliable detection of when we're at a native/Lua call boundary
Matthew Wild <mwild1@gmail.com>
parents: 50
diff changeset
486 if(!oldFrame.entry)
19
8c9c1752272b OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents: 18
diff changeset
487 {
8c9c1752272b OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents: 18
diff changeset
488 var i;
64
77552f3c2c39 Correct off-by-one in return value limits
Matthew Wild <mwild1@gmail.com>
parents: 63
diff changeset
489 for(i=0;(oldFrame.retCount == 0||i<(oldFrame.retCount-1))&&i<rets.length;i++)
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
490 frame.reg[oldFrame.retAt+i] = rets[i];
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
491 if(oldFrame.retAt+i<frame.reg.length)
65
134ddfbb2005 splice != slice. Dear Javascript, this is only one reason for why I don't like you.
Matthew Wild <mwild1@gmail.com>
parents: 64
diff changeset
492 frame.reg.slice(0,oldFrame.retAt+i);
19
8c9c1752272b OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents: 18
diff changeset
493 }
47
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
494 else
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
495 return rets;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
496 break;
36
9e7b57b0b78f Implement OP_SELF
Matthew Wild <mwild1@gmail.com>
parents: 35
diff changeset
497 case OP_SELF:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
498 var table = frame.reg[INS_B(instruction)];
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
499 frame.reg[INS_A(instruction)+1] = table;
36
9e7b57b0b78f Implement OP_SELF
Matthew Wild <mwild1@gmail.com>
parents: 35
diff changeset
500 var C = INS_C(instruction);
71
768d8fb574bb Change some decimal constants to hex for consistency
Matthew Wild <mwild1@gmail.com>
parents: 68
diff changeset
501 var keysource = (C&0x100)?frame.f.constants:frame.reg;
66
d02e5e93aeef Add FIXME for something that works, but shouldn't...
Matthew Wild <mwild1@gmail.com>
parents: 65
diff changeset
502 var key = keysource[C&0xff]; // FIXME: Should this be made an LValue?
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
503 frame.reg[INS_A(instruction)] = table.index(key);
36
9e7b57b0b78f Implement OP_SELF
Matthew Wild <mwild1@gmail.com>
parents: 35
diff changeset
504 break;
34
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
505 case OP_FORPREP:
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
506 frame.pc+=(INS_sBx(instruction));
34
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
507 var A = INS_A(instruction);
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
508 frame.reg[A].value -= frame.reg[A+2].value;
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
509 frame.reg[A+3] = new LValue("number", null);
34
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
510 break;
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
511 case OP_FORLOOP:
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
512 var A = INS_A(instruction);
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
513 var RA = frame.reg[A];
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
514 RA.value += frame.reg[A+2].value;
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
515 if(RA.value <= frame.reg[A+1].value)
34
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
516 {
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
517 frame.pc += INS_sBx(instruction);
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
518 frame.reg[A+3].value = RA.value;
34
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
519 }
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
520 break;
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
521 case OP_TEST:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
522 var RA = frame.reg[INS_A(instruction)];
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
523 var RA_bool = RA.type == "nil" || (RA.type == "boolean" && RA.value == false);
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
524 if(RA_bool == (INS_C(instruction)!=0))
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
525 frame.pc++;
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
526 break;
59
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
527 case OP_TESTSET:
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
528 var RB = frame.reg[INS_B(instruction)];
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
529 var RB_bool = RB.type == "nil" || (RB.type == "boolean" && RB.value == false);
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
530 if(RB_bool == (INS_C(instruction)!=0))
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
531 frame.pc++;
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
532 else
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
533 frame.reg[INS_A(instruction)] = RB;
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
534 break;
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
535 case OP_JMP:
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
536 frame.pc+=INS_sBx(instruction);
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
537 break;
58
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
538 case OP_ADD:
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
539 var RB = frame.reg[INS_B(instruction)];
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
540 var RC = frame.reg[INS_C(instruction)];
72
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
541 frame.reg[INS_A(instruction)] = RB.add(RC);
58
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
542 break;
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
543 case OP_SUB:
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
544 var RB = frame.reg[INS_B(instruction)];
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
545 var RC = frame.reg[INS_C(instruction)];
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
546 frame.reg[INS_A(instruction)] = new LValue("number", RB.value - RC.value);
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
547 break;
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
548 case OP_LT:
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
549 var RB = frame.reg[INS_B(instruction)];
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
550 var RC = frame.reg[INS_C(instruction)];
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
551 if(RB.value < RC.value)
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
552 frame.pc++;
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
553 break;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
554 default:
11
1b3267149cbd Throw error on unhandled opcodes
Matthew Wild <mwild1@gmail.com>
parents: 10
diff changeset
555 throw "Unhandled opcode: "+INS_OPCODE(instruction);
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
556 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
557 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
558 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
559 };
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
560
56
d02c7932cbf2 Move try {} block so it covers more of the VM initialization
Matthew Wild <mwild1@gmail.com>
parents: 55
diff changeset
561 try{
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
562 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
563
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
564 var fs=require("fs");
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
565 var sys=require("sys");
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
566 var c = new LBinaryChunk(fs.readFileSync("luac.out", "binary"));
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
567
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
568 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
569
67
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
570 // Standard library
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
571
67
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
572 var baselib = {
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
573 print: function (args)
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
574 {
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
575 sys.print(args[0].toString());
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
576 for(var i = 1; i<args.length; i++)
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
577 sys.print("\t"+args[i].toString());
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
578 sys.print("\n");
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
579 return 0;
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
580 },
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
581 setmetatable: function (args)
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
582 {
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
583 if(args.length!=2)
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
584 throw "setmetatable expects 2 arguments, got "+args.length;
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
585 args[0].setMetatable(args[1]);
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
586 return 1;
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
587 }
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
588 };
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
589
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
590 for(var name in baselib)
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
591 {
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
592 default_environment.setIndex(LValueFromString(name), LValueFromFunction(testvm, baselib[name]));
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
593 }
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
594
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
595 // Metatable on environment to print out nil global accesses
55
89ecee2cbad1 Add test __index handler to catch use of nil globals
Matthew Wild <mwild1@gmail.com>
parents: 54
diff changeset
596 var mt = new LValue("table", {});
89ecee2cbad1 Add test __index handler to catch use of nil globals
Matthew Wild <mwild1@gmail.com>
parents: 54
diff changeset
597 mt.setIndex(
89ecee2cbad1 Add test __index handler to catch use of nil globals
Matthew Wild <mwild1@gmail.com>
parents: 54
diff changeset
598 LValueFromString("__index"),
89ecee2cbad1 Add test __index handler to catch use of nil globals
Matthew Wild <mwild1@gmail.com>
parents: 54
diff changeset
599 LValueFromFunction(testvm, function (t, k) { sys.puts("Access of nil global: "+k); })
89ecee2cbad1 Add test __index handler to catch use of nil globals
Matthew Wild <mwild1@gmail.com>
parents: 54
diff changeset
600 );
89ecee2cbad1 Add test __index handler to catch use of nil globals
Matthew Wild <mwild1@gmail.com>
parents: 54
diff changeset
601 default_environment.setMetatable(mt);
67
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
602
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
603
49
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
604 var f = new LFunction(testvm, c, default_environment);
2
253863ece36f Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents: 1
diff changeset
605
48
31787f1bd76c Show return values on exit
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
606 var ret = testvm.call(f);
31787f1bd76c Show return values on exit
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
607 if(ret)
31787f1bd76c Show return values on exit
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
608 sys.puts("Returned: "+sys.inspect(ret));
29
62f3df8ed204 Remove rawExceptions flag, always print exception's stack trace if it has one
Matthew Wild <mwild1@gmail.com>
parents: 28
diff changeset
609 }
62f3df8ed204 Remove rawExceptions flag, always print exception's stack trace if it has one
Matthew Wild <mwild1@gmail.com>
parents: 28
diff changeset
610 catch(e)
25
9e62bc13b30d Add new debug option - rawExceptions - to prevent catching exceptions thrown by the VM, use for debugging the VM.
Matthew Wild <mwild1@gmail.com>
parents: 24
diff changeset
611 {
68
5b815d3591e2 Switch to sys.puts for all output for now, leaving browser compatibility for the moment.
Matthew Wild <mwild1@gmail.com>
parents: 67
diff changeset
612 sys.puts("Error: " + e);
35
3de1d63ffdf7 Fix for error handling to handle string exceptions
Matthew Wild <mwild1@gmail.com>
parents: 34
diff changeset
613 if(typeof(e) == "object" && "stack" in e)
68
5b815d3591e2 Switch to sys.puts for all output for now, leaving browser compatibility for the moment.
Matthew Wild <mwild1@gmail.com>
parents: 67
diff changeset
614 sys.puts(e.stack);
44
f5244bce28ce Exit with failure code on error
Matthew Wild <mwild1@gmail.com>
parents: 43
diff changeset
615 process.exit(1);
5
c5c9c4f2d1d3 Print error on error
Matthew Wild <mwild1@gmail.com>
parents: 4
diff changeset
616 }

mercurial