lvm.js

Wed, 24 Nov 2010 02:53:15 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Wed, 24 Nov 2010 02:53:15 +0000
changeset 139
055fe658d0b2
parent 138
f9bb0e212d28
child 140
2286f9b970b7
permissions
-rw-r--r--

Implement string.find (mostly) and string.sub

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;
110
6a6e5ef39eaf Implement OP_MUL (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 109
diff changeset
16 var OP_MUL = 14;
99
633e414a496c Implement OP_DIV (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 98
diff changeset
17 var OP_DIV = 15;
112
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
18 var OP_MOD = 16;
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
19 var OP_POW = 17;
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
20 var OP_UNM = 18;
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
21 var OP_NOT = 19;
116
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
22 var OP_LEN = 20;
101
f1247747f025 Implement OP_CONCAT (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 100
diff changeset
23 var OP_CONCAT = 21;
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
24 var OP_JMP = 22;
81
1deed5894ff6 Implement OP_EQ
Matthew Wild <mwild1@gmail.com>
parents: 80
diff changeset
25 var OP_EQ = 23;
58
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
26 var OP_LT = 24;
90
40edbc05fbb9 Implement OP_LE (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 89
diff changeset
27 var OP_LE = 25;
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
28 var OP_TEST = 26;
59
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
29 var OP_TESTSET = 27;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30 var OP_CALL = 28;
127
9a4c549c7828 Implement OP_TAILCALL - the last opcode!
Matthew Wild <mwild1@gmail.com>
parents: 125
diff changeset
31 var OP_TAILCALL = 29;
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
32 var OP_RETURN = 30;
34
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
33 var OP_FORLOOP = 31;
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
34 var OP_FORPREP = 32;
102
7bf985fd9e03 Implement OP_TFORLOOP
Matthew Wild <mwild1@gmail.com>
parents: 101
diff changeset
35 var OP_TFORLOOP = 33;
103
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
36 var OP_SETLIST = 34;
118
05d10aebb9f5 "Implement" OP_CLOSE
Matthew Wild <mwild1@gmail.com>
parents: 117
diff changeset
37 var OP_CLOSE = 35;
15
5240eaff785f Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents: 14
diff changeset
38 var OP_CLOSURE = 36;
123
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
39 var OP_VARARG = 37;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40
91
298efa276aff Disable debugMode, accidentally committed
Matthew Wild <mwild1@gmail.com>
parents: 90
diff changeset
41 var debugMode = false;
8
e7de6d1fee96 Add debugMode switch
Matthew Wild <mwild1@gmail.com>
parents: 7
diff changeset
42
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
43 function LValue(vm, type, value)
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 {
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
45 this.vm = vm;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 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
47 this.value = value;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 LValue.prototype = {
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 call: function (args)
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 {
128
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
53 var ret = this.vm.call(this, args);
49
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
54 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
55 ret = [];
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
56 return ret;
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
57 },
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
58 precall: function ()
052bd6e8daf6 Give LValue precall() and call() methods, give functions a vm property.
Matthew Wild <mwild1@gmail.com>
parents: 48
diff changeset
59 {
3
6f338fbf0abc Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents: 2
diff changeset
60 if(this.type == "function")
6f338fbf0abc Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents: 2
diff changeset
61 return this.value;
6f338fbf0abc Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents: 2
diff changeset
62 else
6f338fbf0abc Throw an error if trying to call a non-function
Matthew Wild <mwild1@gmail.com>
parents: 2
diff changeset
63 throw "Attempt to call a " + this.type + " value";
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
64 },
54
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
65 index: function (key, raw)
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66 {
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
67 if(this.type == "table")
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
68 {
54
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
69 var val;
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
70 if(key.value in this.value)
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
71 return this.value[key.value];
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
72 else if(raw != true && this.metatable && this.metatable.type != "nil")
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
73 {
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
74 var __index = this.metatable.index(this.vm.LValue("__index"));
60
430a0b155703 Support for tables in __index
Matthew Wild <mwild1@gmail.com>
parents: 59
diff changeset
75 if(__index.type == "function")
54
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
76 {
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
77 return this.vm.LValue(__index.call([this, key])[0]);
54
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
78 }
60
430a0b155703 Support for tables in __index
Matthew Wild <mwild1@gmail.com>
parents: 59
diff changeset
79 else if(__index.type != "nil")
430a0b155703 Support for tables in __index
Matthew Wild <mwild1@gmail.com>
parents: 59
diff changeset
80 return __index.index(key);
54
5e0bdf7f234f Support for __index metamethod
Matthew Wild <mwild1@gmail.com>
parents: 53
diff changeset
81 }
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
82 return this.vm.LValue(null);
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83 }
7
00ec5f6e7579 Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents: 6
diff changeset
84 else
00ec5f6e7579 Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents: 6
diff changeset
85 throw "Attempt to index a " + this.type + " value";
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
86 },
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
87 setIndex: function (key, value)
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
88 {
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
89 if(this.type == "table")
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
90 {
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
91 this.value[key.value] = value;
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
92 }
7
00ec5f6e7579 Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents: 6
diff changeset
93 else
00ec5f6e7579 Add errors for when trying to index non-tables
Matthew Wild <mwild1@gmail.com>
parents: 6
diff changeset
94 throw "Attempt to index a " + this.type + " value";
53
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
95 },
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
96 setMetatable: function (metatable)
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
97 {
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
98 if(metatable.type == "table")
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
99 this.metatable = metatable;
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
100 else if(metatable.type == "nil")
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
101 this.metatable = null;
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
102 else
71208f97d9ca Add LValue.setMetatable()
Matthew Wild <mwild1@gmail.com>
parents: 52
diff changeset
103 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
104 },
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
105 toString: function ()
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
106 {
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
107 switch(this.type)
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
108 {
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
109 case "nil":
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
110 return "nil";
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
111 default:
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
112 return this.value.toString();
6acdef1dfb92 Add LValue.toString()
Matthew Wild <mwild1@gmail.com>
parents: 60
diff changeset
113 }
72
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
114 },
86
97678a1565d4 Add LValue.truth() to return whether a value is (not(false) and not(nil))
Matthew Wild <mwild1@gmail.com>
parents: 85
diff changeset
115 truth: function ()
97678a1565d4 Add LValue.truth() to return whether a value is (not(false) and not(nil))
Matthew Wild <mwild1@gmail.com>
parents: 85
diff changeset
116 {
97678a1565d4 Add LValue.truth() to return whether a value is (not(false) and not(nil))
Matthew Wild <mwild1@gmail.com>
parents: 85
diff changeset
117 if(this.type == "nil" || (this.type == "boolean" && this.value == false))
97678a1565d4 Add LValue.truth() to return whether a value is (not(false) and not(nil))
Matthew Wild <mwild1@gmail.com>
parents: 85
diff changeset
118 return false;
97678a1565d4 Add LValue.truth() to return whether a value is (not(false) and not(nil))
Matthew Wild <mwild1@gmail.com>
parents: 85
diff changeset
119 return true;
97678a1565d4 Add LValue.truth() to return whether a value is (not(false) and not(nil))
Matthew Wild <mwild1@gmail.com>
parents: 85
diff changeset
120 },
72
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
121 add: function (op2)
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
122 {
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
123 var metamethod;
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
124 var __add = this.vm.LValue("__add");
72
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
125 if(this.metatable)
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
126 metamethod = this.metatable.index(__add);
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
127 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
128 metamethod = op2.metatable.index(__add);
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
129 if(metamethod && metamethod.type != "nil")
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
130 {
75
aaecd573ee30 Support for __add metamethod
Matthew Wild <mwild1@gmail.com>
parents: 74
diff changeset
131 return metamethod.call([this, op2]);
72
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
132 }
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
133 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
134 && (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
135 {
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
136 // Plain addition
76
d7d7a6bb90cd Fix OP_ADD code to use new LValue format
Matthew Wild <mwild1@gmail.com>
parents: 75
diff changeset
137 return this.vm.LValue(parseFloat(this.value, 10) + parseFloat(op2.value, 10));
72
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
138 }
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
139 else
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
140 throw "Attempt to perform arithmetic on a "+this.type+" and "+op2.type;
80
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
141 },
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
142 equals: function (op2)
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
143 {
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
144 if(this.type != op2.type)
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
145 return false;
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
146 if(this.value == op2.value)
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
147 return true;
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
148 var __eq = this.vm.LValue("__eq");
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
149 if(this.metatable && op2.metatable)
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
150 {
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
151 var metamethod1 = this.metatable.index(__eq);
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
152 var metamethod2 = op2.metatable.index(__eq);
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
153 if(metamethod1.equals(metamethod2))
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
154 {
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
155 var result = metamethod1.call([this, op2]);
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
156 return (result[0].type != "nil"
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
157 && (result[0].type != "boolean" || result[0].value == true)
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
158 );
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
159 }
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
160 }
beb0bb936aca Give LValue an equals() method, returns true/false if the value == the first argument (checks metamethod)
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
161 return false;
116
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
162 },
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
163 len: function ()
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
164 {
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
165 switch(this.type)
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
166 {
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
167 case "string":
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
168 case "table":
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
169 return this.value.length;
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
170 default:
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
171 throw "attempt to get length of a "+this.type+" value";
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
172 }
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
173 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
174 };
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
175
92
e9da9847121a Pass sourceName to child chunks (in binary files it's only set in the top-level chunk)
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
176 function LBinaryChunk(vm, chunk, start, sourceName)
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
177 {
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
178 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
179 this.pos = start||12;
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
180
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
181 this.sourceName = this.readString();
92
e9da9847121a Pass sourceName to child chunks (in binary files it's only set in the top-level chunk)
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
182 if(sourceName)
e9da9847121a Pass sourceName to child chunks (in binary files it's only set in the top-level chunk)
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
183 this.sourceName = sourceName;
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
184 this.lineDefined = this.readInt();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
185 this.lastLineDefined = this.readInt();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
186 this.numUpvalues = this.readByte();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
187 this.numParameters = this.readByte();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
188 this.isVararg = this.readByte();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
189 this.maxStackSize = this.readByte();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
190
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
191 this.instructions = [];
9
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 this.numInstructions = this.readInt();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
194 for(var i=0;i<this.numInstructions;i++)
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 var ins = this.readInt();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
197 this.instructions.push([
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
198 ins&0x3F, // Opcode
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
199 (ins>>6)&0xFF, // Field A
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
200 (ins>>23)&0x1FF, // Field B
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
201 (ins>>14)&0x1FF // Field C
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
202 ]);
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
203 if(debugMode)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
204 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
205 var pi = this.instructions[this.instructions.length-1];
128
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
206 //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
207 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
208 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
209
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
210 this.constants = [];
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
211
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
212 this.numConstants = this.readInt();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
213 for(var i=0;i<this.numConstants;i++)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
214 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
215 var type = this.readByte();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
216 switch(type)
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 case 0: // Nil
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
219 this.constants.push(new LValue(vm, "nil", null));
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
220 break;
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
221 case 1: // Boolean
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
222 this.constants.push(new LValue(vm, "boolean", this.readByte())); // FIXME type
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
223 break;
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
224 case 3: // Number
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
225 this.constants.push(new LValue(vm, "number", this.readNumber()));
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
226 break;
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
227 case 4: // String
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
228 this.constants.push(new LValue(vm, "string", this.readString()));
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
229 break;
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
230 default:
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
231 throw "Invalid constant type "+type+" in bytecode";
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
232 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
233 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
234
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
235 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
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.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
238 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
239 {
92
e9da9847121a Pass sourceName to child chunks (in binary files it's only set in the top-level chunk)
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
240 var p = new LBinaryChunk(vm, chunk, this.pos, this.sourceName);
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
241 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
242 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
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
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.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
246
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 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
248 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
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 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
251 }
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
252
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
253 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
254 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
255 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
256 {
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
257 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
258 }
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
259
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
260 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
261 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
262 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
263 {
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
264 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
265 }
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
266
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
267 return this;
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
268 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
269
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
270 LBinaryChunk.prototype = {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
271 readBytes: function (n)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
272 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
273 return this.chunk.slice(this.pos, this.pos+=n);
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
274 },
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
275 readByte: function ()
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
276 {
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
277 return this.readBytes(1).charCodeAt(0);
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
278 },
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
279 readInt: function ()
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
280 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
281 //FIXME: Endianness
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
282 return this.readByte() | (this.readByte()<<8)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
283 | (this.readByte()<<16) | (this.readByte()<<24);
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
284 },
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
285 readString: function ()
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
286 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
287 var len = this.readInt();
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
288 return this.readBytes(len).substring(0,len-1);
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
289 },
12
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
290 readNumber: function ()
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
291 {
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
292 //FIXME: Endianness
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
293 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
294 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
295
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
296 var sign = (bytes[0]>>7)&0x1;
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
297 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
298
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
299 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
300 + (bytes[2] * Math.pow(2,40))
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
301 + (bytes[3] * Math.pow(2,32))
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
302 + (bytes[4] * Math.pow(2,24))
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
303 + (bytes[5] * Math.pow(2,16))
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
304 + (bytes[6] * Math.pow(2,8))
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
305 + bytes[7];
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
306
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
307 if(exp != 0x000 && exp != 0x7FF)
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
308 {
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
309 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
310 return n;
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
311 }
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
312 else if(exp == 0x000)
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
313 {
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
314 return sign*0;
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
315 }
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
316 else
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
317 return frac==0?sign*Infinity:NaN;
7d748aba47ab Initial stab at reading Number constants from bytecode
Matthew Wild <mwild1@gmail.com>
parents: 11
diff changeset
318 }
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
319 };
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
320
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
321 function INS_OPCODE(ins)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
322 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
323 return ins[0];
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
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
326 function INS_A(ins)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
327 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
328 return ins[1];
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
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
331 function INS_B(ins)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
332 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
333 return ins[2];
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
334 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
335
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
336 function INS_C(ins)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
337 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
338 return ins[3];
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
339 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
340
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
341 function INS_Bx(ins)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
342 {
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
343 return ((INS_C(ins))|(INS_B(ins)<<9));
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
344 }
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 function INS_sBx(ins)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
347 {
32
035aacc192d8 Fix off-by-one in calculating the value of sBx
Matthew Wild <mwild1@gmail.com>
parents: 31
diff changeset
348 return (INS_Bx(ins)-0x1FFFF);
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
349 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
350
77
ab8ff064d808 Add new RK() helper and fix OP_ADD to use it (so it loads constants properly)
Matthew Wild <mwild1@gmail.com>
parents: 76
diff changeset
351 function RK(frame, R)
ab8ff064d808 Add new RK() helper and fix OP_ADD to use it (so it loads constants properly)
Matthew Wild <mwild1@gmail.com>
parents: 76
diff changeset
352 {
ab8ff064d808 Add new RK() helper and fix OP_ADD to use it (so it loads constants properly)
Matthew Wild <mwild1@gmail.com>
parents: 76
diff changeset
353 var keysource = (R&0x100)?frame.f.constants:frame.reg;
ab8ff064d808 Add new RK() helper and fix OP_ADD to use it (so it loads constants properly)
Matthew Wild <mwild1@gmail.com>
parents: 76
diff changeset
354 return keysource[R&0xff];
ab8ff064d808 Add new RK() helper and fix OP_ADD to use it (so it loads constants properly)
Matthew Wild <mwild1@gmail.com>
parents: 76
diff changeset
355 }
ab8ff064d808 Add new RK() helper and fix OP_ADD to use it (so it loads constants properly)
Matthew Wild <mwild1@gmail.com>
parents: 76
diff changeset
356
43
ecfa7896af35 Give LFunctions a vm property
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
357 function LFunction(vm, chunk, env)
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
358 {
131
cd1ba419c808 Create local function to use as chunk prototype
Matthew Wild <mwild1@gmail.com>
parents: 130
diff changeset
359 var F = function () {};
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
360 F.prototype = chunk;
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
361 var o = new F();
43
ecfa7896af35 Give LFunctions a vm property
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
362 o.vm = vm;
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
363 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
364 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
365 o.upvalues = [];
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
366 return o;
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
367 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
368
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
369 function LVM()
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
370 {
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
371 this.callstack = [];
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
372 this.stack = [];
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
373 return this;
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
374 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
375
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
376 LVM.prototype = {
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
377 LValue: function (value)
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
378 {
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
379 switch(typeof(value))
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
380 {
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
381 case "number":
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
382 return new LValue(this, "number", value);
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
383 case "string":
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
384 return new LValue(this, "string", value);
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
385 case "function":
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
386 return new LValue(this, "function", value);
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
387 case "object":
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
388 if(value == null)
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
389 return new LValue(this, "nil", value);
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
390 else
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
391 return new LValue(this, "table", value);
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
392 case "undefined":
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
393 return new LValue(this, "nil", null);
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
394 default:
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
395 throw "Not able to convert type " +
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
396 typeof(value)+" from Javascript to Lua";
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
397 }
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
398 },
128
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
399 call: function (func, args)
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
400 {
128
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
401 var f = func.precall();
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
402 if(typeof(f) == "function")
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
403 {
128
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
404 return f.apply(this, args);
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
405 }
130
88fa4df26e9d Better verification of function validity in LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 129
diff changeset
406 else if(f.instructions)
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
407 {
128
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
408 var frame = {f:f,pc:0,entry:true};
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
409 if(args)
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
410 frame.reg = args.slice(0);
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
411 else
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
412 frame.reg = [];
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
413 this.callstack.push(frame);
128
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
414 for(var i=frame.reg.length;i<f.maxStackSize;i++)
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
415 frame.reg[i] = this.LValue(null);
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
416 return this.run(frame);
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
417 }
130
88fa4df26e9d Better verification of function validity in LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 129
diff changeset
418 else
88fa4df26e9d Better verification of function validity in LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 129
diff changeset
419 throw "Attempt to call invalid function object: "+f.toString();
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
420 },
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
421 run: function(frame)
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
422 {
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
423 var instruction;
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
424 while(this.callstack.length>0)
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
425 {
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
426 instruction = frame.f.instructions[frame.pc++];
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
427 if(debugMode)
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
428 {
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
429 sys.puts("PC: "+(frame.pc-1)+" OP: "+instruction[0]);
106
04eb68b0f3e3 Prettier stack printing in debugMode
Matthew Wild <mwild1@gmail.com>
parents: 105
diff changeset
430 for(var i = 0; i < frame.reg.length; i++)
107
40b25248703b Fix exception in stack printing for some tests when debug mode is enabled
Matthew Wild <mwild1@gmail.com>
parents: 106
diff changeset
431 {
40b25248703b Fix exception in stack printing for some tests when debug mode is enabled
Matthew Wild <mwild1@gmail.com>
parents: 106
diff changeset
432 var entry = frame.reg[i];
40b25248703b Fix exception in stack printing for some tests when debug mode is enabled
Matthew Wild <mwild1@gmail.com>
parents: 106
diff changeset
433 if(entry && entry.type)
40b25248703b Fix exception in stack printing for some tests when debug mode is enabled
Matthew Wild <mwild1@gmail.com>
parents: 106
diff changeset
434 sys.puts("\t"+i+":\t("+entry.type+") "+entry.toString());
40b25248703b Fix exception in stack printing for some tests when debug mode is enabled
Matthew Wild <mwild1@gmail.com>
parents: 106
diff changeset
435 else
40b25248703b Fix exception in stack printing for some tests when debug mode is enabled
Matthew Wild <mwild1@gmail.com>
parents: 106
diff changeset
436 sys.puts("\t"+i+": "+entry);
40b25248703b Fix exception in stack printing for some tests when debug mode is enabled
Matthew Wild <mwild1@gmail.com>
parents: 106
diff changeset
437 }
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
438 }
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
439 switch(INS_OPCODE(instruction))
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
440 {
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
441 case OP_MOVE:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
442 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
443 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
444 case OP_LOADNIL:
10
ce2f27fa25a4 Use new notation for accessing instruction fields
Matthew Wild <mwild1@gmail.com>
parents: 9
diff changeset
445 for(var i = INS_A(instruction);i<=INS_B(instruction);i++)
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
446 frame.reg[i] = new LValue(this, "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
447 break;
39
53d5bf6654ba Implement OP_LOADBOOL
Matthew Wild <mwild1@gmail.com>
parents: 38
diff changeset
448 case OP_LOADBOOL:
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
449 frame.reg[INS_A(instruction)] = new LValue(this, "boolean", INS_B(instruction)!=0);
39
53d5bf6654ba Implement OP_LOADBOOL
Matthew Wild <mwild1@gmail.com>
parents: 38
diff changeset
450 if(INS_C(instruction)!=0)
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
451 frame.pc++;
39
53d5bf6654ba Implement OP_LOADBOOL
Matthew Wild <mwild1@gmail.com>
parents: 38
diff changeset
452 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
453 case OP_GETUPVAL:
132
5a928c1478ad OP_GETUPVALUE: Clone original LValue
Matthew Wild <mwild1@gmail.com>
parents: 131
diff changeset
454 var upvalue = frame.f.upvalues[INS_B(instruction)];
5a928c1478ad OP_GETUPVALUE: Clone original LValue
Matthew Wild <mwild1@gmail.com>
parents: 131
diff changeset
455 frame.reg[INS_A(instruction)] = new LValue(this, upvalue.type, upvalue.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
456 break;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
457 case OP_GETGLOBAL:
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
458 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
459 frame.reg[INS_A(instruction)] = frame.f.environment.index(name);
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
460 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
461 case OP_SETUPVAL:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
462 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
463 var upvalue = frame.f.upvalues[INS_B(instruction)];
26
5c7eafb47830 Implement OP_SETUPVALUE \o/
Matthew Wild <mwild1@gmail.com>
parents: 25
diff changeset
464 upvalue.type = reg.type;
5c7eafb47830 Implement OP_SETUPVALUE \o/
Matthew Wild <mwild1@gmail.com>
parents: 25
diff changeset
465 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
466 break;
6
418fd175eaed Implement OP_SETGLOBAL
Matthew Wild <mwild1@gmail.com>
parents: 5
diff changeset
467 case OP_SETGLOBAL:
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
468 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
469 frame.f.environment.setIndex(name, frame.reg[instruction[1]]);
6
418fd175eaed Implement OP_SETGLOBAL
Matthew Wild <mwild1@gmail.com>
parents: 5
diff changeset
470 break;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
471 case OP_LOADK:
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
472 var constant = frame.f.constants[INS_Bx(instruction)];
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
473 frame.reg[INS_A(instruction)] = new LValue(this, constant.type, constant.value);
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
474 break;
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
475 case OP_NEWTABLE:
115
1555cb5a97b3 Switch to [] for representing tables (for now)
Matthew Wild <mwild1@gmail.com>
parents: 114
diff changeset
476 frame.reg[INS_A(instruction)] = new LValue(this, "table", []);
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
477 break;
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
478 case OP_GETTABLE:
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
479 var C = INS_C(instruction);
114
82d7b057d330 Don't use this.LValue() inside the VM - it's for JS types only
Matthew Wild <mwild1@gmail.com>
parents: 113
diff changeset
480 var value = frame.reg[INS_B(instruction)].index(RK(frame, C));
82d7b057d330 Don't use this.LValue() inside the VM - it's for JS types only
Matthew Wild <mwild1@gmail.com>
parents: 113
diff changeset
481 frame.reg[INS_A(instruction)] = new LValue(this, value.type, value.value);
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
482 break;
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
483 case OP_SETTABLE:
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
484 var C = INS_C(instruction);
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
485 var B = INS_B(instruction);
85
25470393fe74 Fix OP_SETTABLE to use RK() helper
Matthew Wild <mwild1@gmail.com>
parents: 83
diff changeset
486 frame.reg[INS_A(instruction)].setIndex(RK(frame, B), RK(frame, C));
28
d14b47c3870f Support for OP_NEWTABLE, OP_GETTABLE, OP_SETTABLE
Matthew Wild <mwild1@gmail.com>
parents: 27
diff changeset
487 break;
123
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
488 case OP_VARARG:
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
489 var A = INS_A(instruction);
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
490 var prevframe = this.callstack[this.callstack.length-2];
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
491 var base = frame.retAt+frame.f.numParameters;
133
afce5a550d18 OP_VARARG: Fix off-by-one
Matthew Wild <mwild1@gmail.com>
parents: 132
diff changeset
492 var available = (prevframe.reg.length - base) - 1;
123
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
493 var wanted = INS_B(instruction)-1;
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
494 if(wanted < 0)
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
495 wanted = available;
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
496 for(var i = 0; i<wanted; i++)
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
497 {
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
498 if(i<available)
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
499 frame.reg[A+i] = prevframe.reg[base+i+1];
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
500 else
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
501 frame.reg[A+i] = new LValue(this, "nil", null);
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
502 }
f8518f015ec3 Implement OP_VARARG
Matthew Wild <mwild1@gmail.com>
parents: 122
diff changeset
503 break;
127
9a4c549c7828 Implement OP_TAILCALL - the last opcode!
Matthew Wild <mwild1@gmail.com>
parents: 125
diff changeset
504 case OP_TAILCALL:
9a4c549c7828 Implement OP_TAILCALL - the last opcode!
Matthew Wild <mwild1@gmail.com>
parents: 125
diff changeset
505 var f = frame.reg[INS_A(instruction)].precall();
134
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
506 if(typeof(f) != "function") // Can't tail-call native functions
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
507 {
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
508 var A = INS_A(instruction), B = INS_B(instruction);
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
509 var undefined, args;
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
510 if(B != 1)
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
511 args = frame.reg.slice(A+1, B==0?undefined:(A+B));
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
512 else
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
513 args = [];
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
514 if(args.length > f.numParameters)
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
515 args.length = f.numParameters;
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
516 for(var i=args.length;i<f.maxStackSize;i++)
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
517 args[i] = new LValue(this, "nil", null); // Patch frame for new function
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
518 frame.f = f; frame.pc = 0; frame.reg = args;
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
519 break;
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
520 }
2e2d08e3669c OP_TAILCALL: Fall through to OP_CALL for native functions
Matthew Wild <mwild1@gmail.com>
parents: 133
diff changeset
521 // Fall through...
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
522 case OP_CALL:
128
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
523 var f = frame.reg[INS_A(instruction)].precall(); // return JS or LFunction
63
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
524 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
525 var undefined;
113
1e49dfb8ccdc Fix OP_CALL to handle the case of B==1 (no parameters) and fix an off-by-one error that wouldn't fill the stack with nils properly
Matthew Wild <mwild1@gmail.com>
parents: 112
diff changeset
526 var args;
1e49dfb8ccdc Fix OP_CALL to handle the case of B==1 (no parameters) and fix an off-by-one error that wouldn't fill the stack with nils properly
Matthew Wild <mwild1@gmail.com>
parents: 112
diff changeset
527 if(B != 1)
1e49dfb8ccdc Fix OP_CALL to handle the case of B==1 (no parameters) and fix an off-by-one error that wouldn't fill the stack with nils properly
Matthew Wild <mwild1@gmail.com>
parents: 112
diff changeset
528 args = frame.reg.slice(A+1, B==0?undefined:(A+B));
1e49dfb8ccdc Fix OP_CALL to handle the case of B==1 (no parameters) and fix an off-by-one error that wouldn't fill the stack with nils properly
Matthew Wild <mwild1@gmail.com>
parents: 112
diff changeset
529 else
1e49dfb8ccdc Fix OP_CALL to handle the case of B==1 (no parameters) and fix an off-by-one error that wouldn't fill the stack with nils properly
Matthew Wild <mwild1@gmail.com>
parents: 112
diff changeset
530 args = [];
121
fe51bed4a718 OP_CALL: Don't push varargs into called function's stack
Matthew Wild <mwild1@gmail.com>
parents: 120
diff changeset
531 if(B != 0)
fe51bed4a718 OP_CALL: Don't push varargs into called function's stack
Matthew Wild <mwild1@gmail.com>
parents: 120
diff changeset
532 frame.reg.length = A+B;
2
253863ece36f Implement OP_MOVE, OP_LOADNIL and OP_RETURN. Also change the way OP_CALL is implemented, and update the test code with a more complicated (kind of) sample.
Matthew Wild <mwild1@gmail.com>
parents: 1
diff changeset
533 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
534 {
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
535 // JS native function
128
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
536 var ret = this.call(frame.reg[INS_A(instruction)], args);
79
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
537 // Insert ret to reg starting at R(A), with C-1 limit
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
538 var nresults = ret.length;
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
539 var nexpected;
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
540 if(C == 0)
63
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
541 {
79
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
542 nexpected = nresults;
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
543 frame.reg = frame.reg.slice(0, A+nexpected);
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
544 }
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
545 else
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
546 nexpected = C-1;
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
547 for(var i = 0;;i++)
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
548 {
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
549 if(i < nresults)
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
550 frame.reg[A+i] = ret[i];
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
551 else if(i < nexpected)
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
552 frame.reg[A+i] = new LValue(this, "nil", null);
63
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
553 else
79
94c0441b7321 Fix native function return values for the new calling interface
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
554 break;
63
be8bcd01409b New interface for native Javascript functions called from Lua
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
555 }
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
556 }
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
557 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
558 {
121
fe51bed4a718 OP_CALL: Don't push varargs into called function's stack
Matthew Wild <mwild1@gmail.com>
parents: 120
diff changeset
559 if(args.length > f.numParameters)
fe51bed4a718 OP_CALL: Don't push varargs into called function's stack
Matthew Wild <mwild1@gmail.com>
parents: 120
diff changeset
560 args.length = f.numParameters;
fe51bed4a718 OP_CALL: Don't push varargs into called function's stack
Matthew Wild <mwild1@gmail.com>
parents: 120
diff changeset
561 for(var i=args.length;i<f.maxStackSize;i++)
fe51bed4a718 OP_CALL: Don't push varargs into called function's stack
Matthew Wild <mwild1@gmail.com>
parents: 120
diff changeset
562 args[i] = new LValue(this, "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
563 // Lua function
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
564 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
565 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
566 entry:false};
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
567 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
568 }
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
569 break;
15
5240eaff785f Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents: 14
diff changeset
570 case OP_CLOSURE:
5240eaff785f Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents: 14
diff changeset
571 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
572 var chunk = frame.f.chunk.prototypes[prototype_id];
43
ecfa7896af35 Give LFunctions a vm property
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
573 var f = new LFunction(this, chunk, frame.f.environment);
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
574 frame.reg[INS_A(instruction)] = new LValue(this, "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
575 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
576 {
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
577 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
578 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
579 {
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
580 case OP_MOVE:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
581 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
582 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
583 case OP_GETUPVAL:
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
584 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
585 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
586 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
587 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
588 }
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
589 }
15
5240eaff785f Implement basic OP_CLOSURE (no support for upvalues yet)
Matthew Wild <mwild1@gmail.com>
parents: 14
diff changeset
590 break;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
591 case OP_RETURN:
19
8c9c1752272b OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents: 18
diff changeset
592 var oldFrame = this.callstack.pop();
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
593 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
594 var rets;
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
595 if(INS_B(instruction) == 0)
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
596 rets = oldFrame.reg.slice(INS_A(instruction));
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
597 else
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
598 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
599 if(!oldFrame.entry)
19
8c9c1752272b OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents: 18
diff changeset
600 {
8c9c1752272b OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents: 18
diff changeset
601 var i;
64
77552f3c2c39 Correct off-by-one in return value limits
Matthew Wild <mwild1@gmail.com>
parents: 63
diff changeset
602 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
603 frame.reg[oldFrame.retAt+i] = rets[i];
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
604 if(oldFrame.retAt+i<frame.reg.length)
135
77022489338a OP_RETURN: Pad out results with nils if we get less results than expected
Matthew Wild <mwild1@gmail.com>
parents: 134
diff changeset
605 frame.reg.length = (oldFrame.retAt+i);
77022489338a OP_RETURN: Pad out results with nils if we get less results than expected
Matthew Wild <mwild1@gmail.com>
parents: 134
diff changeset
606 if(i<oldFrame.retCount)
77022489338a OP_RETURN: Pad out results with nils if we get less results than expected
Matthew Wild <mwild1@gmail.com>
parents: 134
diff changeset
607 {
77022489338a OP_RETURN: Pad out results with nils if we get less results than expected
Matthew Wild <mwild1@gmail.com>
parents: 134
diff changeset
608 for(;i<oldFrame.retCount;i++)
77022489338a OP_RETURN: Pad out results with nils if we get less results than expected
Matthew Wild <mwild1@gmail.com>
parents: 134
diff changeset
609 frame.reg[oldFrame.retAt+i] = new LValue(this, "nil", null);
77022489338a OP_RETURN: Pad out results with nils if we get less results than expected
Matthew Wild <mwild1@gmail.com>
parents: 134
diff changeset
610 }
19
8c9c1752272b OP_RETURN: Support for return values from Lua functions \o/
Matthew Wild <mwild1@gmail.com>
parents: 18
diff changeset
611 }
47
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
612 else
b8c4273edbbb Support for return values from LVM.call()
Matthew Wild <mwild1@gmail.com>
parents: 46
diff changeset
613 return rets;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
614 break;
118
05d10aebb9f5 "Implement" OP_CLOSE
Matthew Wild <mwild1@gmail.com>
parents: 117
diff changeset
615 case OP_CLOSE:
05d10aebb9f5 "Implement" OP_CLOSE
Matthew Wild <mwild1@gmail.com>
parents: 117
diff changeset
616 // No-op, since we leave upvalue management to the GC
05d10aebb9f5 "Implement" OP_CLOSE
Matthew Wild <mwild1@gmail.com>
parents: 117
diff changeset
617 break;
36
9e7b57b0b78f Implement OP_SELF
Matthew Wild <mwild1@gmail.com>
parents: 35
diff changeset
618 case OP_SELF:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
619 var table = frame.reg[INS_B(instruction)];
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
620 frame.reg[INS_A(instruction)+1] = table;
36
9e7b57b0b78f Implement OP_SELF
Matthew Wild <mwild1@gmail.com>
parents: 35
diff changeset
621 var C = INS_C(instruction);
78
a856f1c3364f Update all opcodes to use RK() that need it
Matthew Wild <mwild1@gmail.com>
parents: 77
diff changeset
622 frame.reg[INS_A(instruction)] = table.index(RK(frame, C));
36
9e7b57b0b78f Implement OP_SELF
Matthew Wild <mwild1@gmail.com>
parents: 35
diff changeset
623 break;
34
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
624 case OP_FORPREP:
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
625 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
626 var A = INS_A(instruction);
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
627 frame.reg[A].value -= frame.reg[A+2].value;
34
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
628 break;
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
629 case OP_FORLOOP:
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
630 var A = INS_A(instruction);
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
631 var RA = frame.reg[A];
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
632 RA.value += frame.reg[A+2].value;
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
633 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
634 {
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
635 frame.pc += INS_sBx(instruction);
117
8f1045a7f1d6 Fix OP_FORLOOP to set the loop counter variable properly
Matthew Wild <mwild1@gmail.com>
parents: 116
diff changeset
636 frame.reg[A+3] = new LValue(this, "number", RA.value);
34
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
637 }
2c3d73c76d0f OP_FORPREP, OP_FORLOOP: Support for numerical for loops
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
638 break;
102
7bf985fd9e03 Implement OP_TFORLOOP
Matthew Wild <mwild1@gmail.com>
parents: 101
diff changeset
639 case OP_TFORLOOP:
7bf985fd9e03 Implement OP_TFORLOOP
Matthew Wild <mwild1@gmail.com>
parents: 101
diff changeset
640 var A = INS_A(instruction);
7bf985fd9e03 Implement OP_TFORLOOP
Matthew Wild <mwild1@gmail.com>
parents: 101
diff changeset
641 var C = INS_C(instruction);
128
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
642 var RA = frame.reg[A]; // Iterator function
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
643 var rets = this.call(RA, [frame.reg[A+1], frame.reg[A+2]]);
102
7bf985fd9e03 Implement OP_TFORLOOP
Matthew Wild <mwild1@gmail.com>
parents: 101
diff changeset
644 frame.reg.length = A+3;
7bf985fd9e03 Implement OP_TFORLOOP
Matthew Wild <mwild1@gmail.com>
parents: 101
diff changeset
645 for(var i = 0; i<C; i++)
7bf985fd9e03 Implement OP_TFORLOOP
Matthew Wild <mwild1@gmail.com>
parents: 101
diff changeset
646 frame.reg[A+3+i] = rets[i];
7bf985fd9e03 Implement OP_TFORLOOP
Matthew Wild <mwild1@gmail.com>
parents: 101
diff changeset
647 if(frame.reg[A+3].type != "nil")
7bf985fd9e03 Implement OP_TFORLOOP
Matthew Wild <mwild1@gmail.com>
parents: 101
diff changeset
648 frame.reg[A+2] = frame.reg[A+3];
7bf985fd9e03 Implement OP_TFORLOOP
Matthew Wild <mwild1@gmail.com>
parents: 101
diff changeset
649 else
7bf985fd9e03 Implement OP_TFORLOOP
Matthew Wild <mwild1@gmail.com>
parents: 101
diff changeset
650 frame.pc++; // Skip JMP to start
7bf985fd9e03 Implement OP_TFORLOOP
Matthew Wild <mwild1@gmail.com>
parents: 101
diff changeset
651 continue;
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
652 case OP_TEST:
45
4d2cf0b5235d Backed out changeset 741b953fcc5f (premature optimisations == bad)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
653 var RA = frame.reg[INS_A(instruction)];
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
654 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
655 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
656 frame.pc++;
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
657 break;
59
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
658 case OP_TESTSET:
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
659 var RB = frame.reg[INS_B(instruction)];
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
660 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
661 if(RB_bool == (INS_C(instruction)!=0))
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
662 frame.pc++;
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
663 else
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
664 frame.reg[INS_A(instruction)] = RB;
3ac959479e85 Implement OP_TESTSET
Matthew Wild <mwild1@gmail.com>
parents: 58
diff changeset
665 break;
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
666 case OP_JMP:
41
70eb0eb5e7e8 Split LVM.run() into LVM.call()/LVM.run()
Matthew Wild <mwild1@gmail.com>
parents: 40
diff changeset
667 frame.pc+=INS_sBx(instruction);
40
3a074ec1790f Implement OP_TEST and OP_JMP
Matthew Wild <mwild1@gmail.com>
parents: 39
diff changeset
668 break;
101
f1247747f025 Implement OP_CONCAT (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 100
diff changeset
669 case OP_CONCAT:
f1247747f025 Implement OP_CONCAT (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 100
diff changeset
670 var A = INS_A(instruction);
f1247747f025 Implement OP_CONCAT (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 100
diff changeset
671 var B = INS_B(instruction);
f1247747f025 Implement OP_CONCAT (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 100
diff changeset
672 var C = INS_C(instruction);
f1247747f025 Implement OP_CONCAT (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 100
diff changeset
673 var values = [];
f1247747f025 Implement OP_CONCAT (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 100
diff changeset
674 for(var i = B; i<=C; i++)
f1247747f025 Implement OP_CONCAT (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 100
diff changeset
675 values.push(frame.reg[i].value);
120
e058c18b9f85 Fix OP_CONCAT: missing break; and should supply empty separator to join()
Matthew Wild <mwild1@gmail.com>
parents: 119
diff changeset
676 frame.reg[A] = new LValue(this, "string", values.join(''));
e058c18b9f85 Fix OP_CONCAT: missing break; and should supply empty separator to join()
Matthew Wild <mwild1@gmail.com>
parents: 119
diff changeset
677 break;
58
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
678 case OP_ADD:
77
ab8ff064d808 Add new RK() helper and fix OP_ADD to use it (so it loads constants properly)
Matthew Wild <mwild1@gmail.com>
parents: 76
diff changeset
679 var RB = RK(frame, INS_B(instruction));
ab8ff064d808 Add new RK() helper and fix OP_ADD to use it (so it loads constants properly)
Matthew Wild <mwild1@gmail.com>
parents: 76
diff changeset
680 var RC = RK(frame, INS_C(instruction));
72
dc73a60b3c06 Give LValue an add() method, to eventually respect metamethods
Matthew Wild <mwild1@gmail.com>
parents: 71
diff changeset
681 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
682 break;
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
683 case OP_SUB:
95
c461e20b609a Fix OP_SUB to use RK() too...
Matthew Wild <mwild1@gmail.com>
parents: 93
diff changeset
684 var RB = RK(frame, INS_B(instruction));
c461e20b609a Fix OP_SUB to use RK() too...
Matthew Wild <mwild1@gmail.com>
parents: 93
diff changeset
685 var RC = RK(frame, INS_C(instruction));
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
686 frame.reg[INS_A(instruction)] = new LValue(this, "number", RB.value - RC.value);
58
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
687 break;
110
6a6e5ef39eaf Implement OP_MUL (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 109
diff changeset
688 case OP_MUL:
6a6e5ef39eaf Implement OP_MUL (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 109
diff changeset
689 var RB = RK(frame, INS_B(instruction));
6a6e5ef39eaf Implement OP_MUL (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 109
diff changeset
690 var RC = RK(frame, INS_C(instruction));
6a6e5ef39eaf Implement OP_MUL (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 109
diff changeset
691 frame.reg[INS_A(instruction)] = new LValue(this, "number", RB.value * RC.value);
6a6e5ef39eaf Implement OP_MUL (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 109
diff changeset
692 break;
99
633e414a496c Implement OP_DIV (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 98
diff changeset
693 case OP_DIV:
633e414a496c Implement OP_DIV (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 98
diff changeset
694 var RB = RK(frame, INS_B(instruction));
633e414a496c Implement OP_DIV (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 98
diff changeset
695 var RC = RK(frame, INS_C(instruction));
633e414a496c Implement OP_DIV (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 98
diff changeset
696 frame.reg[INS_A(instruction)] = new LValue(this, "number", RB.value / RC.value);
633e414a496c Implement OP_DIV (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 98
diff changeset
697 break;
112
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
698 case OP_MOD:
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
699 var RB = RK(frame, INS_B(instruction));
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
700 var RC = RK(frame, INS_C(instruction));
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
701 frame.reg[INS_A(instruction)] = new LValue(this, "number", RB.value % RC.value);
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
702 break;
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
703 case OP_POW:
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
704 var RB = RK(frame, INS_B(instruction));
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
705 var RC = RK(frame, INS_C(instruction));
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
706 frame.reg[INS_A(instruction)] = new LValue(this, "number", Math.pow(RB.value, RC.value));
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
707 break;
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
708 case OP_UNM:
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
709 var RB = frame.reg[INS_B(instruction)];
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
710 frame.reg[INS_A(instruction)] = new LValue(this, "number", -RB.value);
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
711 break;
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
712 case OP_NOT:
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
713 var RB = frame.reg[INS_B(instruction)];
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
714 frame.reg[INS_A(instruction)] = new LValue(this, "boolean", !RB.truth());
5318bb31b0ac Implement OP_MOD, OP_POW, OP_UNM, OP_NOT (no metamethods yet)
Matthew Wild <mwild1@gmail.com>
parents: 110
diff changeset
715 break;
116
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
716 case OP_LEN:
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
717 var RB = frame.reg[INS_B(instruction)];
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
718 frame.reg[INS_A(instruction)] = new LValue(this, "number", RB.len());
b78e86780939 Implement LValue.len() and OP_LEN (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 115
diff changeset
719 break;
89
a9cef9e01154 Fix OP_LT to respect A, and move OP_EQ to live next to it in the switch() for readability
Matthew Wild <mwild1@gmail.com>
parents: 88
diff changeset
720 case OP_EQ:
a9cef9e01154 Fix OP_LT to respect A, and move OP_EQ to live next to it in the switch() for readability
Matthew Wild <mwild1@gmail.com>
parents: 88
diff changeset
721 var A = INS_A(instruction);
88
350a87c42b9b Fix OP_LT to use RK()
Matthew Wild <mwild1@gmail.com>
parents: 87
diff changeset
722 var RB = RK(frame, INS_B(instruction));
350a87c42b9b Fix OP_LT to use RK()
Matthew Wild <mwild1@gmail.com>
parents: 87
diff changeset
723 var RC = RK(frame, INS_C(instruction));
89
a9cef9e01154 Fix OP_LT to respect A, and move OP_EQ to live next to it in the switch() for readability
Matthew Wild <mwild1@gmail.com>
parents: 88
diff changeset
724 if(RB.equals(RC) != (A!=0))
a9cef9e01154 Fix OP_LT to respect A, and move OP_EQ to live next to it in the switch() for readability
Matthew Wild <mwild1@gmail.com>
parents: 88
diff changeset
725 frame.pc++;
a9cef9e01154 Fix OP_LT to respect A, and move OP_EQ to live next to it in the switch() for readability
Matthew Wild <mwild1@gmail.com>
parents: 88
diff changeset
726 break;
a9cef9e01154 Fix OP_LT to respect A, and move OP_EQ to live next to it in the switch() for readability
Matthew Wild <mwild1@gmail.com>
parents: 88
diff changeset
727 case OP_LT:
a9cef9e01154 Fix OP_LT to respect A, and move OP_EQ to live next to it in the switch() for readability
Matthew Wild <mwild1@gmail.com>
parents: 88
diff changeset
728 var A = INS_A(instruction);
a9cef9e01154 Fix OP_LT to respect A, and move OP_EQ to live next to it in the switch() for readability
Matthew Wild <mwild1@gmail.com>
parents: 88
diff changeset
729 var RB = RK(frame, INS_B(instruction));
a9cef9e01154 Fix OP_LT to respect A, and move OP_EQ to live next to it in the switch() for readability
Matthew Wild <mwild1@gmail.com>
parents: 88
diff changeset
730 var RC = RK(frame, INS_C(instruction));
a9cef9e01154 Fix OP_LT to respect A, and move OP_EQ to live next to it in the switch() for readability
Matthew Wild <mwild1@gmail.com>
parents: 88
diff changeset
731 if(RB.value < RC.value != (A!=0))
58
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
732 frame.pc++;
40d0b0429428 Implement OP_ADD, OP_SUB, OP_LT
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
733 break;
90
40edbc05fbb9 Implement OP_LE (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 89
diff changeset
734 case OP_LE:
40edbc05fbb9 Implement OP_LE (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 89
diff changeset
735 var A = INS_A(instruction);
40edbc05fbb9 Implement OP_LE (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 89
diff changeset
736 var RB = RK(frame, INS_B(instruction));
40edbc05fbb9 Implement OP_LE (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 89
diff changeset
737 var RC = RK(frame, INS_C(instruction));
40edbc05fbb9 Implement OP_LE (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 89
diff changeset
738 if(RB.value <= RC.value != (A!=0))
40edbc05fbb9 Implement OP_LE (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 89
diff changeset
739 frame.pc++;
40edbc05fbb9 Implement OP_LE (no metamethod yet)
Matthew Wild <mwild1@gmail.com>
parents: 89
diff changeset
740 break;
103
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
741 case OP_SETLIST:
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
742 var A = INS_A(instruction);
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
743 var RA = frame.reg[A];
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
744 var B = INS_B(instruction);
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
745 var C = INS_C(instruction);
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
746 if(C == 0)
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
747 throw "Dynamic table construction not yet implemented";
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
748 // #define LFIELDS_PER_FLUSH 50 // Lua 5.1
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
749 var baseindex = (C-1)*50;
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
750 var index = new LValue(this, "number", 1);
136
0b31998aad53 OP_SETLIST: Implement support for B==0 (to top of stack)
Matthew Wild <mwild1@gmail.com>
parents: 135
diff changeset
751 var lim = B>0?B:((frame.reg.length-baseindex)-2);
0b31998aad53 OP_SETLIST: Implement support for B==0 (to top of stack)
Matthew Wild <mwild1@gmail.com>
parents: 135
diff changeset
752 for(var i = 1; i<=lim; index.value=(baseindex+(++i)))
103
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
753 RA.setIndex(index, frame.reg[A+i]);
5a0db53fc898 Implement OP_SETLIST
Matthew Wild <mwild1@gmail.com>
parents: 102
diff changeset
754 break;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
755 default:
11
1b3267149cbd Throw error on unhandled opcodes
Matthew Wild <mwild1@gmail.com>
parents: 10
diff changeset
756 throw "Unhandled opcode: "+INS_OPCODE(instruction);
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
757 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
758 }
96
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
759 },
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
760 registerLib: function (env, name, lib)
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
761 {
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
762 var t;
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
763 if(name)
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
764 {
115
1555cb5a97b3 Switch to [] for representing tables (for now)
Matthew Wild <mwild1@gmail.com>
parents: 114
diff changeset
765 t = this.LValue([]); // Create env[name] and put fns in there
96
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
766 env.setIndex(this.LValue(name), t);
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
767 }
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
768 else
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
769 t = env; // Import directly into env
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
770
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
771 for(var k in lib)
e4324d9a824c Add LVM().registerLib(env, name, lib) to register a table of native functions to an environment.
Matthew Wild <mwild1@gmail.com>
parents: 95
diff changeset
772 t.setIndex(this.LValue(k), this.LValue(lib[k]));
128
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
773 },
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
774 loadstring: function (chunk, env)
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
775 {
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
776 var c = new LBinaryChunk(this, chunk);
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
777 var f = new LFunction(this, c, env);
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
778 return new LValue(this, "function", f);
137
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
779 },
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
780 traceback: function ()
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
781 {
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
782 var trace = [];
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
783 for(var i=this.callstack.length-1; i>=0; i--)
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
784 {
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
785 var currframe = testvm.callstack[i];
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
786 var currfunc = currframe.f;
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
787 var sourceName = (currfunc.sourceName||"=?").substr(1);
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
788 var line = "?";
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
789 if(currfunc.sourceLines && currfunc.sourceLines[currframe.pc-1])
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
790 line = currfunc.sourceLines[currframe.pc-1];
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
791 trace.push({ sourceName: sourceName, line: line });
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
792 }
6872878601d9 Add LVM.traceback() function
Matthew Wild <mwild1@gmail.com>
parents: 136
diff changeset
793 return trace;
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
794 }
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
795 };
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
796
56
d02c7932cbf2 Move try {} block so it covers more of the VM initialization
Matthew Wild <mwild1@gmail.com>
parents: 55
diff changeset
797 try{
0
2fcdf7f16d71 Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
798 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
799
9
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
800 var fs=require("fs");
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
801 var sys=require("sys");
3f055c9ab80e Add a bytecode interpreter \o/
Matthew Wild <mwild1@gmail.com>
parents: 8
diff changeset
802
115
1555cb5a97b3 Switch to [] for representing tables (for now)
Matthew Wild <mwild1@gmail.com>
parents: 114
diff changeset
803 var _G = testvm.LValue([]);
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
804
67
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
805 // 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
806
67
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
807 var baselib = {
74
a4a6adee1459 New Lua<->native function interface, simpler. Added type() to baselib.
Matthew Wild <mwild1@gmail.com>
parents: 73
diff changeset
808 print: function ()
67
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
809 {
74
a4a6adee1459 New Lua<->native function interface, simpler. Added type() to baselib.
Matthew Wild <mwild1@gmail.com>
parents: 73
diff changeset
810 var args = Array.prototype.slice.call(arguments);
67
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
811 sys.print(args[0].toString());
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
812 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
813 sys.print("\t"+args[i].toString());
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
814 sys.print("\n");
74
a4a6adee1459 New Lua<->native function interface, simpler. Added type() to baselib.
Matthew Wild <mwild1@gmail.com>
parents: 73
diff changeset
815 return [];
67
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
816 },
74
a4a6adee1459 New Lua<->native function interface, simpler. Added type() to baselib.
Matthew Wild <mwild1@gmail.com>
parents: 73
diff changeset
817 setmetatable: function (table, metatable)
67
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
818 {
74
a4a6adee1459 New Lua<->native function interface, simpler. Added type() to baselib.
Matthew Wild <mwild1@gmail.com>
parents: 73
diff changeset
819 if(arguments.length!=2)
a4a6adee1459 New Lua<->native function interface, simpler. Added type() to baselib.
Matthew Wild <mwild1@gmail.com>
parents: 73
diff changeset
820 throw "setmetatable expects 2 arguments, got "+arguments.length;
a4a6adee1459 New Lua<->native function interface, simpler. Added type() to baselib.
Matthew Wild <mwild1@gmail.com>
parents: 73
diff changeset
821
a4a6adee1459 New Lua<->native function interface, simpler. Added type() to baselib.
Matthew Wild <mwild1@gmail.com>
parents: 73
diff changeset
822 table.setMetatable(metatable);
a4a6adee1459 New Lua<->native function interface, simpler. Added type() to baselib.
Matthew Wild <mwild1@gmail.com>
parents: 73
diff changeset
823 return [table];
a4a6adee1459 New Lua<->native function interface, simpler. Added type() to baselib.
Matthew Wild <mwild1@gmail.com>
parents: 73
diff changeset
824 },
a4a6adee1459 New Lua<->native function interface, simpler. Added type() to baselib.
Matthew Wild <mwild1@gmail.com>
parents: 73
diff changeset
825 type: function (o)
a4a6adee1459 New Lua<->native function interface, simpler. Added type() to baselib.
Matthew Wild <mwild1@gmail.com>
parents: 73
diff changeset
826 {
83
0e6b19731508 Fix type() in baselib to return an LValue
Matthew Wild <mwild1@gmail.com>
parents: 82
diff changeset
827 return [this.LValue(o.type)];
87
07d19518e89a Add assert() to baselib, real tests possible at last
Matthew Wild <mwild1@gmail.com>
parents: 86
diff changeset
828 },
07d19518e89a Add assert() to baselib, real tests possible at last
Matthew Wild <mwild1@gmail.com>
parents: 86
diff changeset
829 assert: function (expr, message)
07d19518e89a Add assert() to baselib, real tests possible at last
Matthew Wild <mwild1@gmail.com>
parents: 86
diff changeset
830 {
07d19518e89a Add assert() to baselib, real tests possible at last
Matthew Wild <mwild1@gmail.com>
parents: 86
diff changeset
831 if(!expr.truth())
119
ad42e6dd7cbd assert(): Throw "assertion failed" message when none supplied
Matthew Wild <mwild1@gmail.com>
parents: 118
diff changeset
832 if(message && message.truth())
ad42e6dd7cbd assert(): Throw "assertion failed" message when none supplied
Matthew Wild <mwild1@gmail.com>
parents: 118
diff changeset
833 throw message;
ad42e6dd7cbd assert(): Throw "assertion failed" message when none supplied
Matthew Wild <mwild1@gmail.com>
parents: 118
diff changeset
834 else
ad42e6dd7cbd assert(): Throw "assertion failed" message when none supplied
Matthew Wild <mwild1@gmail.com>
parents: 118
diff changeset
835 throw "assertion failed";
87
07d19518e89a Add assert() to baselib, real tests possible at last
Matthew Wild <mwild1@gmail.com>
parents: 86
diff changeset
836 return [expr];
67
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
837 }
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
838 };
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
839
97
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
840 var math = {
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
841 ldexp: function (m, e)
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
842 {
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
843 return [this.LValue(m.value*Math.pow(2, e.value))];
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
844 },
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
845 floor: function (x)
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
846 {
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
847 return [this.LValue(Math.floor(x.value))];
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
848 }
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
849 };
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
850
104
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
851 var _patternClasses = {
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
852 "a": "[A-Za-z]", "A": "[^A-Za-z]",
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
853 "p": "[\x21-\x2f\x3a-\x40\x5b-\x60\x7b-\x7e]",
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
854 "P": "[^\x21-\x2f\x3a-\x40\x5b-\x60\x7b-\x7e]",
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
855 "s": "[\x09-\x0d\x20]", "S": "[^\x09-\x0d\x20]",
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
856 "u": "[A-Z]", "U": "[^A-Z]",
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
857 "d": "[0-9]", "D": "[^0-9]",
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
858 "w": "[0-9A-Za-z]", "W": "[^0-9A-Za-z]",
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
859 "x": "[0-9A-Fa-f]", "X": "[^0-9A-Fa-f]",
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
860 "z": "[\x00]", "Z": "[^\x00]",
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
861 "l": "[a-z]", "L": "[^a-z]",
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
862 "c": "[\x00-\x1f\x7f]", "C": "[^\x00-\x1f\x7f]",
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
863 };
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
864
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
865 var _patternToRegExp = function (patt)
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
866 {
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
867 var regexp = "";
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
868 for(var i=0;i<patt.length;i++)
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
869 {
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
870 var c = patt[i];
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
871 if(c == "%")
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
872 {
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
873 c = patt[++i];
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
874 if(c == "b")
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
875 {
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
876 throw "%b not supported in patterns";
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
877 }
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
878 else if(c >= "0" && c <= "9")
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
879 {
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
880 regexp += ("\\"+c);
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
881 continue;
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
882 }
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
883 else
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
884 {
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
885 var cls = _patternClasses[c];
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
886 if(cls)
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
887 {
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
888 regexp += cls;
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
889 continue;
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
890 }
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
891 }
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
892 }
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
893 else if(c == "\\" || c == "/")
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
894 regexp += "\\"; // Escape escapes
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
895 regexp += c;
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
896 }
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
897 return new RegExp(regexp, "g");
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
898 };
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
899
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
900 var string = {
139
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
901 "char": function ()
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
902 {
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
903 var nArgs = arguments.length;
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
904 if(nArgs < 1)
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
905 throw "string.char(): Expects at least 1 parameter";
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
906 var results = [];
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
907 for(var i=0; i<nArgs; i++)
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
908 {
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
909 var code = arguments[i];
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
910 if(code.type != "number")
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
911 throw "string.char(): Argument #"+(i+1)+" expected number, got "+code.type;
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
912 results.push(String.fromCharCode(code.value));
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
913 }
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
914 return [this.LValue(results.join(''))];
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
915 },
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
916 find: function (str, patt, init, plain)
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
917 {
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
918 if(arguments.length > 2)
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
919 throw "string.find(): No more than the first 2 arguments supported";
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
920 var re = _patternToRegExp(patt.value);
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
921 var result = re.exec(str);
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
922 if(!result)
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
923 return [this.LValue(null)];
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
924 var start = result.index+1;
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
925 var end = start + result[0].length - 1;
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
926 var ret = [this.LValue(start), this.LValue(end)];
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
927 for(var i=1; i<result.length; i++)
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
928 ret.push(this.LValue(result[i]));
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
929 return ret;
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
930 },
104
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
931 gmatch: function (str, patt)
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
932 {
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
933 var re = _patternToRegExp(patt.value);
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
934 var matches = str.value.match(re)||[];
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
935 var curr = 0;
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
936 var iter = function ()
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
937 {
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
938 return [this.LValue(matches[curr++])];
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
939 };
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
940 return [this.LValue(iter)];
139
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
941 },
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
942 sub: function (str, from, to)
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
943 {
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
944 var result;
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
945 switch(arguments.length)
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
946 {
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
947 case 0:
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
948 case 1:
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
949 throw "string.sub(): Expected 2 or more arguments";
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
950 case 2:
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
951 result = str.value.substring(from.value);
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
952 case 3:
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
953 result = str.value.substring(from.value, to.value);
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
954 }
055fe658d0b2 Implement string.find (mostly) and string.sub
Matthew Wild <mwild1@gmail.com>
parents: 138
diff changeset
955 return [this.LValue(result)];
104
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
956 }
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
957 };
97
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
958 testvm.registerLib(_G, null, baselib);
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
959 testvm.registerLib(_G, "math", math);
104
c481f6bfb19b Add string lib, with gmatch function only for now
Matthew Wild <mwild1@gmail.com>
parents: 103
diff changeset
960 testvm.registerLib(_G, "string", string);
67
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
961
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
962 // Metatable on environment to print out nil global accesses
115
1555cb5a97b3 Switch to [] for representing tables (for now)
Matthew Wild <mwild1@gmail.com>
parents: 114
diff changeset
963 var mt = testvm.LValue([]);
55
89ecee2cbad1 Add test __index handler to catch use of nil globals
Matthew Wild <mwild1@gmail.com>
parents: 54
diff changeset
964 mt.setIndex(
73
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
965 testvm.LValue("__index"),
6b43d68abc94 Large overhaul - every LValue (and LBinaryChunk) now has a valid 'vm' property, so we know in which LVM to call it or its metamethods
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
966 testvm.LValue(function (t, k) { sys.puts("Access of nil global: "+k); })
55
89ecee2cbad1 Add test __index handler to catch use of nil globals
Matthew Wild <mwild1@gmail.com>
parents: 54
diff changeset
967 );
97
80cc68dd8222 Rename default_environment to _G, use registerLib() for baselib and add math lib with 2 ldexp, floor
Matthew Wild <mwild1@gmail.com>
parents: 96
diff changeset
968 _G.setMetatable(mt);
67
782274d793ac Formalise the beginnings of a baselib, add setmetatable.
Matthew Wild <mwild1@gmail.com>
parents: 66
diff changeset
969
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
970
128
29c56996fa03 Change LVM.call() to take an LValue rather than the raw native/LFunction object. Also add LVM.loadstring(chunk, env) and use that for loading luac.out.
Matthew Wild <mwild1@gmail.com>
parents: 127
diff changeset
971 var f = testvm.loadstring(fs.readFileSync("luac.out", "binary"), _G);
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
972
129
6784d462999f Indentation fix
Matthew Wild <mwild1@gmail.com>
parents: 128
diff changeset
973 var ret = testvm.call(f);
6784d462999f Indentation fix
Matthew Wild <mwild1@gmail.com>
parents: 128
diff changeset
974 if(ret)
6784d462999f Indentation fix
Matthew Wild <mwild1@gmail.com>
parents: 128
diff changeset
975 sys.puts("Returned: "+sys.inspect(ret));
6784d462999f Indentation fix
Matthew Wild <mwild1@gmail.com>
parents: 128
diff changeset
976
29
62f3df8ed204 Remove rawExceptions flag, always print exception's stack trace if it has one
Matthew Wild <mwild1@gmail.com>
parents: 28
diff changeset
977 }
62f3df8ed204 Remove rawExceptions flag, always print exception's stack trace if it has one
Matthew Wild <mwild1@gmail.com>
parents: 28
diff changeset
978 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
979 {
138
f9bb0e212d28 Replace error reporting code with calls to LVM.traceback()
Matthew Wild <mwild1@gmail.com>
parents: 137
diff changeset
980 var trace = testvm.traceback();
f9bb0e212d28 Replace error reporting code with calls to LVM.traceback()
Matthew Wild <mwild1@gmail.com>
parents: 137
diff changeset
981 var currframe = trace[0];
98
14d2400ec059 Don't try and print current position in the Lua script with no valid frame
Matthew Wild <mwild1@gmail.com>
parents: 97
diff changeset
982 if(currframe)
14d2400ec059 Don't try and print current position in the Lua script with no valid frame
Matthew Wild <mwild1@gmail.com>
parents: 97
diff changeset
983 {
138
f9bb0e212d28 Replace error reporting code with calls to LVM.traceback()
Matthew Wild <mwild1@gmail.com>
parents: 137
diff changeset
984 sys.print("lvm.js: "+currframe.sourceName+":"+currframe.line+": ");
98
14d2400ec059 Don't try and print current position in the Lua script with no valid frame
Matthew Wild <mwild1@gmail.com>
parents: 97
diff changeset
985 }
93
748b51e8f0d6 Print out location at which errors occur, yay!
Matthew Wild <mwild1@gmail.com>
parents: 92
diff changeset
986 sys.puts(e);
35
3de1d63ffdf7 Fix for error handling to handle string exceptions
Matthew Wild <mwild1@gmail.com>
parents: 34
diff changeset
987 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
988 sys.puts(e.stack);
44
f5244bce28ce Exit with failure code on error
Matthew Wild <mwild1@gmail.com>
parents: 43
diff changeset
989 process.exit(1);
5
c5c9c4f2d1d3 Print error on error
Matthew Wild <mwild1@gmail.com>
parents: 4
diff changeset
990 }

mercurial