diff options
-rw-r--r-- | lapi.c | 18 | ||||
-rw-r--r-- | lcode.c | 1045 | ||||
-rw-r--r-- | lcode.h | 49 | ||||
-rw-r--r-- | ldebug.c | 360 | ||||
-rw-r--r-- | ldebug.h | 27 | ||||
-rw-r--r-- | lfunc.c | 11 | ||||
-rw-r--r-- | lgc.c | 8 | ||||
-rw-r--r-- | llimits.h | 89 | ||||
-rw-r--r-- | lobject.h | 8 | ||||
-rw-r--r-- | lopcodes.h | 219 | ||||
-rw-r--r-- | lparser.c | 558 | ||||
-rw-r--r-- | lparser.h | 32 | ||||
-rw-r--r-- | ltests.c | 133 | ||||
-rw-r--r-- | lvm.c | 476 | ||||
-rw-r--r-- | lvm.h | 7 |
15 files changed, 1599 insertions, 1441 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 1.140 2001/04/17 17:35:54 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 1.141 2001/04/23 16:35:45 roberto Exp roberto $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -184,9 +184,10 @@ LUA_API int lua_iscfunction (lua_State *L, int index) { | |||
184 | LUA_API int lua_isnumber (lua_State *L, int index) { | 184 | LUA_API int lua_isnumber (lua_State *L, int index) { |
185 | TObject *o; | 185 | TObject *o; |
186 | int i; | 186 | int i; |
187 | TObject n; | ||
187 | lua_lock(L); | 188 | lua_lock(L); |
188 | o = luaA_indexAcceptable(L, index); | 189 | o = luaA_indexAcceptable(L, index); |
189 | i = (o == NULL) ? 0 : (tonumber(o) == 0); | 190 | i = (o != NULL && (ttype(o) == LUA_TNUMBER || luaV_tonumber(o, &n))); |
190 | lua_unlock(L); | 191 | lua_unlock(L); |
191 | return i; | 192 | return i; |
192 | } | 193 | } |
@@ -234,13 +235,18 @@ LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { | |||
234 | 235 | ||
235 | 236 | ||
236 | LUA_API lua_Number lua_tonumber (lua_State *L, int index) { | 237 | LUA_API lua_Number lua_tonumber (lua_State *L, int index) { |
237 | StkId o; | 238 | const TObject *o; |
238 | lua_Number n; | 239 | TObject n; |
240 | lua_Number res; | ||
239 | lua_lock(L); | 241 | lua_lock(L); |
240 | o = luaA_indexAcceptable(L, index); | 242 | o = luaA_indexAcceptable(L, index); |
241 | n = (o == NULL || tonumber(o)) ? 0 : nvalue(o); | 243 | if (o != NULL && |
244 | (ttype(o) == LUA_TNUMBER || (o = luaV_tonumber(o, &n)) != NULL)) | ||
245 | res = nvalue(o); | ||
246 | else | ||
247 | res = 0; | ||
242 | lua_unlock(L); | 248 | lua_unlock(L); |
243 | return n; | 249 | return res; |
244 | } | 250 | } |
245 | 251 | ||
246 | LUA_API const l_char *lua_tostring (lua_State *L, int index) { | 252 | LUA_API const l_char *lua_tostring (lua_State *L, int index) { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 1.67 2001/04/06 18:25:00 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.68 2001/04/23 16:35:45 roberto Exp roberto $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -11,6 +11,7 @@ | |||
11 | #include "lua.h" | 11 | #include "lua.h" |
12 | 12 | ||
13 | #include "lcode.h" | 13 | #include "lcode.h" |
14 | #include "ldebug.h" | ||
14 | #include "ldo.h" | 15 | #include "ldo.h" |
15 | #include "llex.h" | 16 | #include "llex.h" |
16 | #include "lmem.h" | 17 | #include "lmem.h" |
@@ -19,6 +20,12 @@ | |||
19 | #include "lparser.h" | 20 | #include "lparser.h" |
20 | 21 | ||
21 | 22 | ||
23 | #define hasjumps(e) ((e)->t != (e)->f) | ||
24 | |||
25 | #define getcode(fs,e) ((fs)->f->code[(e)->u.i.info]) | ||
26 | |||
27 | |||
28 | |||
22 | void luaK_error (LexState *ls, const l_char *msg) { | 29 | void luaK_error (LexState *ls, const l_char *msg) { |
23 | luaX_error(ls, msg, ls->t.token); | 30 | luaX_error(ls, msg, ls->t.token); |
24 | } | 31 | } |
@@ -33,12 +40,27 @@ static Instruction previous_instruction (FuncState *fs) { | |||
33 | if (fs->pc > fs->lasttarget) /* no jumps to current position? */ | 40 | if (fs->pc > fs->lasttarget) /* no jumps to current position? */ |
34 | return fs->f->code[fs->pc-1]; /* returns previous instruction */ | 41 | return fs->f->code[fs->pc-1]; /* returns previous instruction */ |
35 | else | 42 | else |
36 | return CREATE_0(-1); /* no optimizations after an invalid instruction */ | 43 | return (Instruction)(-1);/* no optimizations after an invalid instruction */ |
44 | } | ||
45 | |||
46 | |||
47 | void luaK_nil (FuncState *fs, int from, int n) { | ||
48 | Instruction previous = previous_instruction(fs); | ||
49 | if (GET_OPCODE(previous) == OP_LOADNIL) { | ||
50 | int pfrom = GETARG_A(previous); | ||
51 | int pto = GETARG_B(previous); | ||
52 | if (pfrom <= from && from <= pto+1) { /* can connect both? */ | ||
53 | if (from+n-1 > pto) | ||
54 | SETARG_B(fs->f->code[fs->pc-1], from+n-1); | ||
55 | return; | ||
56 | } | ||
57 | } | ||
58 | luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ | ||
37 | } | 59 | } |
38 | 60 | ||
39 | 61 | ||
40 | int luaK_jump (FuncState *fs) { | 62 | int luaK_jump (FuncState *fs) { |
41 | int j = luaK_code1(fs, OP_JMP, NO_JUMP); | 63 | int j = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); |
42 | if (j == fs->lasttarget) { /* possible jumps to this jump? */ | 64 | if (j == fs->lasttarget) { /* possible jumps to this jump? */ |
43 | luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ | 65 | luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ |
44 | fs->jlt = NO_JUMP; | 66 | fs->jlt = NO_JUMP; |
@@ -47,36 +69,33 @@ int luaK_jump (FuncState *fs) { | |||
47 | } | 69 | } |
48 | 70 | ||
49 | 71 | ||
72 | static int luaK_condjump (FuncState *fs, OpCode op, int B, int C) { | ||
73 | luaK_codeABC(fs, op, NO_REG, B, C); | ||
74 | return luaK_codeAsBc(fs, OP_CJMP, 0, NO_JUMP); | ||
75 | } | ||
76 | |||
77 | |||
50 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { | 78 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { |
51 | Instruction *jmp = &fs->f->code[pc]; | 79 | Instruction *jmp = &fs->f->code[pc]; |
52 | if (dest == NO_JUMP) | 80 | if (dest == NO_JUMP) |
53 | SETARG_S(*jmp, NO_JUMP); /* point to itself to represent end of list */ | 81 | SETARG_sBc(*jmp, NO_JUMP); /* point to itself to represent end of list */ |
54 | else { /* jump is relative to position following jump instruction */ | 82 | else { /* jump is relative to position following jump instruction */ |
55 | int offset = dest-(pc+1); | 83 | int offset = dest-(pc+1); |
56 | if (abs(offset) > MAXARG_S) | 84 | if (abs(offset) > MAXARG_sBc) |
57 | luaK_error(fs->ls, l_s("control structure too long")); | 85 | luaK_error(fs->ls, l_s("control structure too long")); |
58 | SETARG_S(*jmp, offset); | 86 | SETARG_sBc(*jmp, offset); |
59 | } | 87 | } |
60 | } | 88 | } |
61 | 89 | ||
62 | 90 | ||
63 | /* | 91 | /* |
64 | ** prep-for instructions (OP_FORPREP & OP_LFORPREP) have a negated jump, | 92 | ** prep-for instructions (OP_FORPREP & OP_TFORPREP) have a negated jump, |
65 | ** as they simulate the real jump... | 93 | ** as they simulate the real jump... |
66 | */ | 94 | */ |
67 | void luaK_fixfor (FuncState *fs, int pc, int dest) { | 95 | void luaK_fixfor (FuncState *fs, int pc, int dest) { |
68 | Instruction *jmp = &fs->f->code[pc]; | 96 | Instruction *jmp = &fs->f->code[pc]; |
69 | int offset = dest-(pc+1); | 97 | int offset = dest-(pc+1); |
70 | SETARG_S(*jmp, -offset); | 98 | SETARG_sBc(*jmp, -offset); |
71 | } | ||
72 | |||
73 | |||
74 | static int luaK_getjump (FuncState *fs, int pc) { | ||
75 | int offset = GETARG_S(fs->f->code[pc]); | ||
76 | if (offset == NO_JUMP) /* point to itself represents end of list */ | ||
77 | return NO_JUMP; /* end of list */ | ||
78 | else | ||
79 | return (pc+1)+offset; /* turn offset into absolute position */ | ||
80 | } | 99 | } |
81 | 100 | ||
82 | 101 | ||
@@ -96,609 +115,677 @@ int luaK_getlabel (FuncState *fs) { | |||
96 | } | 115 | } |
97 | 116 | ||
98 | 117 | ||
99 | void luaK_deltastack (FuncState *fs, int delta) { | 118 | static int luaK_getjump (FuncState *fs, int pc) { |
100 | fs->stacklevel += delta; | 119 | int offset = GETARG_sBc(fs->f->code[pc]); |
101 | if (fs->stacklevel > fs->f->maxstacksize) { | 120 | if (offset == NO_JUMP) /* point to itself represents end of list */ |
102 | if (fs->stacklevel > MAXSTACK) | 121 | return NO_JUMP; /* end of list */ |
103 | luaK_error(fs->ls, l_s("function or expression too complex")); | 122 | else |
104 | fs->f->maxstacksize = (short)fs->stacklevel; | 123 | return (pc+1)+offset; /* turn offset into absolute position */ |
105 | } | ||
106 | } | 124 | } |
107 | 125 | ||
108 | 126 | ||
109 | void luaK_kstr (LexState *ls, int c) { | 127 | static Instruction *getjumpcontrol (FuncState *fs, int pc) { |
110 | luaK_code1(ls->fs, OP_PUSHSTRING, c); | 128 | Instruction *pi = &fs->f->code[pc]; |
129 | OpCode op = GET_OPCODE(*pi); | ||
130 | if (op == OP_CJMP) | ||
131 | return pi-1; | ||
132 | else { | ||
133 | lua_assert(op == OP_JMP || op == OP_FORLOOP || op == OP_TFORLOOP); | ||
134 | return pi; | ||
135 | } | ||
111 | } | 136 | } |
112 | 137 | ||
113 | 138 | ||
114 | static int number_constant (FuncState *fs, lua_Number r) { | 139 | static int need_value (FuncState *fs, int list, OpCode op) { |
115 | /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ | 140 | /* check whether list has any jump different from `op' */ |
116 | Proto *f = fs->f; | 141 | for (; list != NO_JUMP; list = luaK_getjump(fs, list)) |
117 | int c = fs->nknum; | 142 | if (GET_OPCODE(*getjumpcontrol(fs, list)) != op) return 1; |
118 | int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS; | 143 | return 0; /* not found */ |
119 | while (--c >= lim) | ||
120 | if (f->knum[c] == r) return c; | ||
121 | /* not found; create a new entry */ | ||
122 | luaM_growvector(fs->L, f->knum, fs->nknum, f->sizeknum, lua_Number, | ||
123 | MAXARG_U, l_s("constant table overflow")); | ||
124 | c = fs->nknum++; | ||
125 | f->knum[c] = r; | ||
126 | return c; | ||
127 | } | 144 | } |
128 | 145 | ||
129 | 146 | ||
130 | void luaK_number (FuncState *fs, lua_Number f) { | 147 | static void luaK_patchlistaux (FuncState *fs, int list, |
131 | if (f <= (lua_Number)MAXARG_S && (lua_Number)(int)f == f) | 148 | int ttarget, int treg, int ftarget, int freg, int dtarget) { |
132 | luaK_code1(fs, OP_PUSHINT, (int)f); /* f has a short integer value */ | 149 | while (list != NO_JUMP) { |
133 | else | 150 | int next = luaK_getjump(fs, list); |
134 | luaK_code1(fs, OP_PUSHNUM, number_constant(fs, f)); | 151 | Instruction *i = getjumpcontrol(fs, list); |
152 | switch (GET_OPCODE(*i)) { | ||
153 | case OP_TESTT: { | ||
154 | SETARG_A(*i, treg); | ||
155 | luaK_fixjump(fs, list, ttarget); | ||
156 | break; | ||
157 | } | ||
158 | case OP_TESTF: { | ||
159 | SETARG_A(*i, freg); | ||
160 | luaK_fixjump(fs, list, ftarget); | ||
161 | break; | ||
162 | } | ||
163 | default: { | ||
164 | luaK_fixjump(fs, list, dtarget); /* jump to default target */ | ||
165 | break; | ||
166 | } | ||
167 | } | ||
168 | list = next; | ||
169 | } | ||
135 | } | 170 | } |
136 | 171 | ||
137 | 172 | ||
138 | void luaK_adjuststack (FuncState *fs, int n) { | 173 | void luaK_patchlist (FuncState *fs, int list, int target) { |
139 | if (n > 0) | 174 | if (target == fs->lasttarget) /* same target that list `jlt'? */ |
140 | luaK_code1(fs, OP_POP, n); | 175 | luaK_concat(fs, &fs->jlt, list); /* delay fixing */ |
141 | else | 176 | else |
142 | luaK_code1(fs, OP_PUSHNIL, -n); | 177 | luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); |
143 | } | 178 | } |
144 | 179 | ||
145 | 180 | ||
146 | int luaK_lastisopen (FuncState *fs) { | 181 | void luaK_concat (FuncState *fs, int *l1, int l2) { |
147 | /* check whether last instruction is an open function call */ | 182 | if (*l1 == NO_JUMP) |
148 | Instruction i = previous_instruction(fs); | 183 | *l1 = l2; |
149 | if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) | 184 | else { |
150 | return 1; | 185 | int list = *l1; |
151 | else return 0; | 186 | int next; |
187 | while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */ | ||
188 | list = next; | ||
189 | luaK_fixjump(fs, list, l2); | ||
190 | } | ||
152 | } | 191 | } |
153 | 192 | ||
154 | 193 | ||
155 | void luaK_setcallreturns (FuncState *fs, int nresults) { | 194 | void luaK_reserveregs (FuncState *fs, int n) { |
156 | if (luaK_lastisopen(fs)) { /* expression is an open function call? */ | 195 | fs->freereg += n; |
157 | SETARG_B(fs->f->code[fs->pc-1], nresults); /* set number of results */ | 196 | if (fs->freereg > fs->f->maxstacksize) { |
158 | luaK_deltastack(fs, nresults); /* push results */ | 197 | if (fs->freereg >= MAXSTACK) |
198 | luaK_error(fs->ls, l_s("function or expression too complex")); | ||
199 | fs->f->maxstacksize = (short)fs->freereg; | ||
159 | } | 200 | } |
160 | } | 201 | } |
161 | 202 | ||
162 | 203 | ||
163 | static int discharge (FuncState *fs, expdesc *var) { | 204 | static void freereg (FuncState *fs, int reg) { |
164 | switch (var->k) { | 205 | if (reg >= fs->nactloc && reg < MAXSTACK) { |
165 | case VLOCAL: | 206 | fs->freereg--; |
166 | luaK_code1(fs, OP_GETLOCAL, var->u.index); | 207 | lua_assert(reg == fs->freereg); |
167 | break; | ||
168 | case VGLOBAL: | ||
169 | luaK_code1(fs, OP_GETGLOBAL, var->u.index); | ||
170 | break; | ||
171 | case VINDEXED: | ||
172 | luaK_code0(fs, OP_GETTABLE); | ||
173 | break; | ||
174 | case VEXP: | ||
175 | return 0; /* nothing to do */ | ||
176 | } | 208 | } |
177 | var->k = VEXP; | ||
178 | var->u.l.t = var->u.l.f = NO_JUMP; | ||
179 | return 1; | ||
180 | } | 209 | } |
181 | 210 | ||
182 | 211 | ||
183 | static void discharge1 (FuncState *fs, expdesc *var) { | 212 | static void freeexp (FuncState *fs, expdesc *e) { |
184 | discharge(fs, var); | 213 | if (e->k == VNONRELOC) |
185 | /* if it has jumps then it is already discharged */ | 214 | freereg(fs, e->u.i.info); |
186 | if (var->u.l.t == NO_JUMP && var->u.l.f == NO_JUMP) | ||
187 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ | ||
188 | } | 215 | } |
189 | 216 | ||
190 | 217 | ||
191 | void luaK_storevar (LexState *ls, const expdesc *var) { | 218 | static int addk (FuncState *fs, TObject *k) { |
192 | FuncState *fs = ls->fs; | 219 | Proto *f = fs->f; |
193 | switch (var->k) { | 220 | luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, |
194 | case VLOCAL: | 221 | MAXARG_Bc, l_s("constant table overflow")); |
195 | luaK_code1(fs, OP_SETLOCAL, var->u.index); | 222 | setobj(&f->k[fs->nk], k); |
196 | break; | 223 | return fs->nk++; |
197 | case VGLOBAL: | 224 | } |
198 | luaK_code1(fs, OP_SETGLOBAL, var->u.index); | 225 | |
199 | break; | 226 | |
200 | case VINDEXED: /* table is at top-3; pop 3 elements after operation */ | 227 | int luaK_stringk (FuncState *fs, TString *s) { |
201 | luaK_code2(fs, OP_SETTABLE, 3, 3); | 228 | Proto *f = fs->f; |
202 | break; | 229 | int c = s->u.s.constindex; |
203 | default: | 230 | if (c >= fs->nk || ttype(&f->k[c]) != LUA_TSTRING || tsvalue(&f->k[c]) != s) { |
204 | lua_assert(0); /* invalid var kind to store */ | 231 | TObject o; |
232 | setsvalue(&o, s); | ||
233 | c = addk(fs, &o); | ||
234 | s->u.s.constindex = c; /* hint for next time */ | ||
205 | } | 235 | } |
236 | return c; | ||
206 | } | 237 | } |
207 | 238 | ||
208 | 239 | ||
209 | static OpCode invertjump (OpCode op) { | 240 | static int number_constant (FuncState *fs, lua_Number r) { |
210 | switch (op) { | 241 | /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ |
211 | case OP_JMPNE: return OP_JMPEQ; | 242 | TObject o; |
212 | case OP_JMPEQ: return OP_JMPNE; | 243 | Proto *f = fs->f; |
213 | case OP_JMPLT: return OP_JMPGE; | 244 | int c = fs->nk; |
214 | case OP_JMPLE: return OP_JMPGT; | 245 | int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS; |
215 | case OP_JMPGT: return OP_JMPLE; | 246 | while (--c >= lim) { |
216 | case OP_JMPGE: return OP_JMPLT; | 247 | if (ttype(&f->k[c]) == LUA_TNUMBER && nvalue(&f->k[c]) == r) |
217 | case OP_JMPT: case OP_JMPONT: return OP_JMPF; | 248 | return c; |
218 | case OP_JMPF: case OP_JMPONF: return OP_JMPT; | ||
219 | default: | ||
220 | lua_assert(0); /* invalid jump instruction */ | ||
221 | return OP_JMP; /* to avoid warnings */ | ||
222 | } | 249 | } |
250 | /* not found; create a new entry */ | ||
251 | setnvalue(&o, r); | ||
252 | return addk(fs, &o); | ||
223 | } | 253 | } |
224 | 254 | ||
225 | 255 | ||
226 | static void luaK_patchlistaux (FuncState *fs, int list, int target, | 256 | void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) { |
227 | OpCode special, int special_target) { | 257 | if (e->k == VCALL) { /* expression is an open function call? */ |
228 | Instruction *code = fs->f->code; | 258 | SETARG_C(getcode(fs, e), nresults); /* set number of results */ |
229 | while (list != NO_JUMP) { | 259 | if (nresults == 1) { /* `regular' expression? */ |
230 | int next = luaK_getjump(fs, list); | 260 | e->k = VNONRELOC; |
231 | Instruction *i = &code[list]; | 261 | e->u.i.info = GETARG_A(getcode(fs, e)); |
232 | OpCode op = GET_OPCODE(*i); | ||
233 | if (op == special) /* this `op' already has a value */ | ||
234 | luaK_fixjump(fs, list, special_target); | ||
235 | else { | ||
236 | luaK_fixjump(fs, list, target); /* do the patch */ | ||
237 | if (op == OP_JMPONT) /* remove eventual values */ | ||
238 | SET_OPCODE(*i, OP_JMPT); | ||
239 | else if (op == OP_JMPONF) | ||
240 | SET_OPCODE(*i, OP_JMPF); | ||
241 | } | 262 | } |
242 | list = next; | ||
243 | } | 263 | } |
244 | } | 264 | } |
245 | 265 | ||
246 | 266 | ||
247 | void luaK_patchlist (FuncState *fs, int list, int target) { | 267 | static void dischargevars (FuncState *fs, expdesc *e) { |
248 | if (target == fs->lasttarget) /* same target that list `jlt'? */ | 268 | switch (e->k) { |
249 | luaK_concat(fs, &fs->jlt, list); /* delay fixing */ | 269 | case VLOCAL: { |
250 | else | 270 | e->k = VNONRELOC; |
251 | luaK_patchlistaux(fs, list, target, OP_ADD, 0); | 271 | break; |
272 | } | ||
273 | case VGLOBAL: { | ||
274 | e->u.i.info = luaK_codeABc(fs, OP_GETGLOBAL, 0, e->u.i.info); | ||
275 | e->k = VRELOCABLE; | ||
276 | break; | ||
277 | } | ||
278 | case VINDEXED: { | ||
279 | freereg(fs, e->u.i.aux); | ||
280 | freereg(fs, e->u.i.info); | ||
281 | e->u.i.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.i.info, e->u.i.aux); | ||
282 | e->k = VRELOCABLE; | ||
283 | break; | ||
284 | } | ||
285 | case VCALL: { | ||
286 | luaK_setcallreturns(fs, e, 1); | ||
287 | break; | ||
288 | } | ||
289 | default: break; /* there is one value available (somewhere) */ | ||
290 | } | ||
252 | } | 291 | } |
253 | 292 | ||
254 | 293 | ||
255 | static int need_value (FuncState *fs, int list, OpCode hasvalue) { | 294 | static int code_label (FuncState *fs, OpCode op, int A, int sBc) { |
256 | /* check whether list has a jump without a value */ | 295 | luaK_getlabel(fs); /* those instructions may be jump targets */ |
257 | for (; list != NO_JUMP; list = luaK_getjump(fs, list)) | 296 | return luaK_codeAsBc(fs, op, A, sBc); |
258 | if (GET_OPCODE(fs->f->code[list]) != hasvalue) return 1; | ||
259 | return 0; /* not found */ | ||
260 | } | 297 | } |
261 | 298 | ||
262 | 299 | ||
263 | void luaK_concat (FuncState *fs, int *l1, int l2) { | 300 | static void dischargejumps (FuncState *fs, expdesc *e, int reg) { |
264 | if (*l1 == NO_JUMP) | 301 | if (hasjumps(e)) { |
265 | *l1 = l2; | 302 | int final; /* position after whole expression */ |
266 | else { | 303 | int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ |
267 | int list = *l1; | 304 | int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ |
268 | int next; | 305 | if (need_value(fs, e->f, OP_TESTF) || need_value(fs, e->t, OP_TESTT)) { |
269 | while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */ | 306 | /* expression needs values */ |
270 | list = next; | 307 | if (e->k != VJMP) |
271 | luaK_fixjump(fs, list, l2); | 308 | code_label(fs, OP_JMP, 0, 2); /* to jump over both pushes */ |
309 | p_nil = code_label(fs, OP_NILJMP, reg, 0); | ||
310 | p_1 = code_label(fs, OP_LOADINT, reg, 1); | ||
311 | } | ||
312 | final = luaK_getlabel(fs); | ||
313 | luaK_patchlistaux(fs, e->f, p_nil, NO_REG, final, reg, p_nil); | ||
314 | luaK_patchlistaux(fs, e->t, final, reg, p_1, NO_REG, p_1); | ||
272 | } | 315 | } |
316 | e->f = e->t = NO_JUMP; | ||
273 | } | 317 | } |
274 | 318 | ||
275 | 319 | ||
276 | static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { | 320 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) { |
277 | int prevpos; /* position of last instruction */ | 321 | dischargevars(fs, e); |
278 | Instruction *previous; | 322 | switch (e->k) { |
279 | int *golist, *exitlist; | 323 | case VNIL: { |
280 | if (!invert) { | 324 | luaK_nil(fs, reg, 1); |
281 | golist = &v->u.l.f; /* go if false */ | 325 | break; |
282 | exitlist = &v->u.l.t; /* exit if true */ | 326 | } |
283 | } | 327 | case VNUMBER: { |
284 | else { | 328 | lua_Number f = e->u.n; |
285 | golist = &v->u.l.t; /* go if true */ | 329 | int i = (int)f; |
286 | exitlist = &v->u.l.f; /* exit if false */ | 330 | if ((lua_Number)i == f && -MAXARG_sBc <= i && i <= MAXARG_sBc) |
331 | luaK_codeAsBc(fs, OP_LOADINT, reg, i); /* f has a small int value */ | ||
332 | else | ||
333 | luaK_codeABc(fs, OP_LOADK, reg, number_constant(fs, f)); | ||
334 | break; | ||
335 | } | ||
336 | case VK: { | ||
337 | luaK_codeABc(fs, OP_LOADK, reg, e->u.i.info); | ||
338 | break; | ||
339 | } | ||
340 | case VRELOCABLE: { | ||
341 | Instruction *pc = &getcode(fs, e); | ||
342 | SETARG_A(*pc, reg); | ||
343 | break; | ||
344 | } | ||
345 | default: return; | ||
287 | } | 346 | } |
288 | discharge1(fs, v); | 347 | e->u.i.info = reg; |
289 | prevpos = fs->pc-1; | 348 | e->k = VNONRELOC; |
290 | previous = &fs->f->code[prevpos]; | 349 | } |
291 | lua_assert(*previous==previous_instruction(fs)); /* no jump allowed here */ | 350 | |
292 | if (!ISJUMP(GET_OPCODE(*previous))) | 351 | |
293 | prevpos = luaK_code1(fs, jump, NO_JUMP); | 352 | static void discharge2anyreg (FuncState *fs, expdesc *e) { |
294 | else { /* last instruction is already a jump */ | 353 | if (e->k != VNONRELOC) { |
295 | if (invert) | 354 | luaK_reserveregs(fs, 1); |
296 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | 355 | discharge2reg(fs, e, fs->freereg-1); |
297 | } | 356 | } |
298 | luaK_concat(fs, exitlist, prevpos); /* insert last jump in `exitlist' */ | ||
299 | luaK_patchlist(fs, *golist, luaK_getlabel(fs)); | ||
300 | *golist = NO_JUMP; | ||
301 | } | 357 | } |
302 | 358 | ||
303 | 359 | ||
304 | void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue) { | 360 | static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) { |
305 | luaK_testgo(fs, v, 1, keepvalue ? OP_JMPONF : OP_JMPF); | 361 | discharge2reg(fs, e, reg); |
362 | switch (e->k) { | ||
363 | case VVOID: { | ||
364 | return; /* nothing to do... */ | ||
365 | } | ||
366 | case VNONRELOC: { | ||
367 | if (reg != e->u.i.info) | ||
368 | luaK_codeABC(fs, OP_MOVE, reg, e->u.i.info, 0); | ||
369 | break; | ||
370 | } | ||
371 | case VJMP: { | ||
372 | luaK_concat(fs, &e->t, e->u.i.info); /* put this jump in `t' list */ | ||
373 | break; | ||
374 | } | ||
375 | default: { | ||
376 | lua_assert(0); /* cannot happen */ | ||
377 | break; | ||
378 | } | ||
379 | } | ||
380 | dischargejumps(fs, e, reg); | ||
381 | e->u.i.info = reg; | ||
382 | e->k = VNONRELOC; | ||
306 | } | 383 | } |
307 | 384 | ||
308 | 385 | ||
309 | static void luaK_goiffalse (FuncState *fs, expdesc *v) { | 386 | void luaK_exp2nextreg (FuncState *fs, expdesc *e) { |
310 | luaK_testgo(fs, v, 0, OP_JMPONT); | 387 | int reg; |
388 | dischargevars(fs, e); | ||
389 | freeexp(fs, e); | ||
390 | reg = fs->freereg; | ||
391 | luaK_reserveregs(fs, 1); | ||
392 | luaK_exp2reg(fs, e, reg); | ||
311 | } | 393 | } |
312 | 394 | ||
313 | 395 | ||
314 | static int code_label (FuncState *fs, OpCode op, int arg) { | 396 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { |
315 | luaK_getlabel(fs); /* those instructions may be jump targets */ | 397 | dischargevars(fs, e); |
316 | return luaK_code1(fs, op, arg); | 398 | if (e->k == VNONRELOC) { |
317 | } | 399 | if (!hasjumps(e)) return e->u.i.info; /* exp is already in a register */ |
318 | 400 | if (e->u.i.info >= fs->nactloc) { /* reg. is not a local? */ | |
319 | 401 | dischargejumps(fs, e, e->u.i.info); /* put value on it */ | |
320 | void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { | 402 | return e->u.i.info; |
321 | FuncState *fs = ls->fs; | ||
322 | if (!discharge(fs, v)) { /* `v' is an expression? */ | ||
323 | OpCode previous = GET_OPCODE(fs->f->code[fs->pc-1]); | ||
324 | if (!ISJUMP(previous) && v->u.l.f == NO_JUMP && v->u.l.t == NO_JUMP) { | ||
325 | /* expression has no jumps */ | ||
326 | if (onlyone) | ||
327 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ | ||
328 | } | ||
329 | else { /* expression has jumps */ | ||
330 | int final; /* position after whole expression */ | ||
331 | int j = NO_JUMP; /* eventual jump over values */ | ||
332 | int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ | ||
333 | int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ | ||
334 | if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF) | ||
335 | || need_value(fs, v->u.l.t, OP_JMPONT)) { | ||
336 | /* expression needs values */ | ||
337 | if (ISJUMP(previous)) | ||
338 | luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in t. list */ | ||
339 | else { | ||
340 | j = code_label(fs, OP_JMP, NO_JUMP); /* to jump over both pushes */ | ||
341 | /* correct stack for compiler and symbolic execution */ | ||
342 | luaK_adjuststack(fs, 1); | ||
343 | } | ||
344 | p_nil = code_label(fs, OP_PUSHNILJMP, 0); | ||
345 | p_1 = code_label(fs, OP_PUSHINT, 1); | ||
346 | luaK_patchlist(fs, j, luaK_getlabel(fs)); | ||
347 | } | ||
348 | final = luaK_getlabel(fs); | ||
349 | luaK_patchlistaux(fs, v->u.l.f, p_nil, OP_JMPONF, final); | ||
350 | luaK_patchlistaux(fs, v->u.l.t, p_1, OP_JMPONT, final); | ||
351 | v->u.l.f = v->u.l.t = NO_JUMP; | ||
352 | } | 403 | } |
353 | } | 404 | } |
405 | luaK_exp2nextreg(fs, e); /* default */ | ||
406 | return e->u.i.info; | ||
354 | } | 407 | } |
355 | 408 | ||
356 | 409 | ||
357 | void luaK_prefix (LexState *ls, UnOpr op, expdesc *v) { | 410 | void luaK_exp2val (FuncState *fs, expdesc *e) { |
358 | FuncState *fs = ls->fs; | 411 | if (hasjumps(e)) |
359 | if (op == OPR_MINUS) { | 412 | luaK_exp2anyreg(fs, e); |
360 | luaK_tostack(ls, v, 1); | 413 | else |
361 | luaK_code0(fs, OP_MINUS); | 414 | dischargevars(fs, e); |
362 | } | ||
363 | else { /* op == NOT */ | ||
364 | Instruction *previous; | ||
365 | discharge1(fs, v); | ||
366 | previous = &fs->f->code[fs->pc-1]; | ||
367 | if (ISJUMP(GET_OPCODE(*previous))) | ||
368 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | ||
369 | else | ||
370 | luaK_code0(fs, OP_NOT); | ||
371 | /* interchange true and false lists */ | ||
372 | { int temp = v->u.l.f; v->u.l.f = v->u.l.t; v->u.l.t = temp; } | ||
373 | } | ||
374 | } | 415 | } |
375 | 416 | ||
376 | 417 | ||
377 | void luaK_infix (LexState *ls, BinOpr op, expdesc *v) { | 418 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
378 | FuncState *fs = ls->fs; | 419 | luaK_exp2val(fs, e); |
379 | switch (op) { | 420 | if (e->k == VNUMBER && fs->nk + MAXSTACK <= MAXARG_C) { |
380 | case OPR_AND: | 421 | e->u.i.info = number_constant(fs, e->u.n); |
381 | luaK_goiftrue(fs, v, 1); | 422 | e->k = VK; |
382 | break; | ||
383 | case OPR_OR: | ||
384 | luaK_goiffalse(fs, v); | ||
385 | break; | ||
386 | default: | ||
387 | luaK_tostack(ls, v, 1); /* all other binary operators need a value */ | ||
388 | } | 423 | } |
424 | else if (!(e->k == VK && e->u.i.info + MAXSTACK <= MAXARG_C)) | ||
425 | luaK_exp2anyreg(fs, e); /* not a constant in the right range */ | ||
426 | return (e->k == VK) ? e->u.i.info+MAXSTACK : e->u.i.info; | ||
389 | } | 427 | } |
390 | 428 | ||
391 | 429 | ||
392 | 430 | void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) { | |
393 | static const struct { | 431 | switch (var->k) { |
394 | OpCode opcode; /* opcode for each binary operator */ | 432 | case VLOCAL: { |
395 | int arg; /* default argument for the opcode */ | 433 | freeexp(fs, exp); |
396 | } codes[] = { /* ORDER OPR */ | 434 | luaK_exp2reg(fs, exp, var->u.i.info); |
397 | {OP_ADD, 0}, {OP_SUB, 0}, {OP_MULT, 0}, {OP_DIV, 0}, | ||
398 | {OP_POW, 0}, {OP_CONCAT, 2}, | ||
399 | {OP_JMPNE, NO_JUMP}, {OP_JMPEQ, NO_JUMP}, | ||
400 | {OP_JMPLT, NO_JUMP}, {OP_JMPLE, NO_JUMP}, | ||
401 | {OP_JMPGT, NO_JUMP}, {OP_JMPGE, NO_JUMP} | ||
402 | }; | ||
403 | |||
404 | |||
405 | void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2) { | ||
406 | FuncState *fs = ls->fs; | ||
407 | switch (op) { | ||
408 | case OPR_AND: { | ||
409 | lua_assert(v1->u.l.t == NO_JUMP); /* list must be closed */ | ||
410 | discharge1(fs, v2); | ||
411 | v1->u.l.t = v2->u.l.t; | ||
412 | luaK_concat(fs, &v1->u.l.f, v2->u.l.f); | ||
413 | break; | 435 | break; |
414 | } | 436 | } |
415 | case OPR_OR: { | 437 | case VGLOBAL: { |
416 | lua_assert(v1->u.l.f == NO_JUMP); /* list must be closed */ | 438 | int e = luaK_exp2anyreg(fs, exp); |
417 | discharge1(fs, v2); | 439 | freereg(fs, e); |
418 | v1->u.l.f = v2->u.l.f; | 440 | luaK_codeABc(fs, OP_SETGLOBAL, e, var->u.i.info); |
419 | luaK_concat(fs, &v1->u.l.t, v2->u.l.t); | 441 | break; |
442 | } | ||
443 | case VINDEXED: { | ||
444 | int e = luaK_exp2anyreg(fs, exp); | ||
445 | freereg(fs, e); | ||
446 | luaK_codeABC(fs, OP_SETTABLE, e, var->u.i.info, var->u.i.aux); | ||
420 | break; | 447 | break; |
421 | } | 448 | } |
422 | default: { | 449 | default: { |
423 | luaK_tostack(ls, v2, 1); /* `v2' must be a value */ | 450 | lua_assert(0); /* invalid var kind to store */ |
424 | luaK_code1(fs, codes[op].opcode, codes[op].arg); | 451 | break; |
425 | } | 452 | } |
426 | } | 453 | } |
427 | } | 454 | } |
428 | 455 | ||
429 | 456 | ||
430 | static void codelineinfo (FuncState *fs) { | 457 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { |
431 | Proto *f = fs->f; | 458 | luaK_exp2anyreg(fs, e); |
432 | LexState *ls = fs->ls; | 459 | freeexp(fs, e); |
433 | if (ls->lastline > fs->lastline) { | 460 | luaK_reserveregs(fs, 2); |
434 | if (ls->lastline > fs->lastline+1) { | 461 | luaK_codeABC(fs, OP_SELF, fs->freereg-2, e->u.i.info, luaK_exp2RK(fs, key)); |
435 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | 462 | e->u.i.info = fs->freereg-2; |
436 | MAX_INT, l_s("line info overflow")); | 463 | e->k = VNONRELOC; |
437 | f->lineinfo[fs->nlineinfo++] = -(ls->lastline - (fs->lastline+1)); | 464 | } |
438 | } | 465 | |
439 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | 466 | |
440 | MAX_INT, l_s("line info overflow")); | 467 | static OpCode invertoperator (OpCode op) { |
441 | f->lineinfo[fs->nlineinfo++] = fs->pc; | 468 | switch (op) { |
442 | fs->lastline = ls->lastline; | 469 | case OP_TESTNE: return OP_TESTEQ; |
470 | case OP_TESTEQ: return OP_TESTNE; | ||
471 | case OP_TESTLT: return OP_TESTGE; | ||
472 | case OP_TESTLE: return OP_TESTGT; | ||
473 | case OP_TESTGT: return OP_TESTLE; | ||
474 | case OP_TESTGE: return OP_TESTLT; | ||
475 | case OP_TESTT: return OP_TESTF; | ||
476 | case OP_TESTF: return OP_TESTT; | ||
477 | default: lua_assert(0); return op; /* invalid jump instruction */ | ||
443 | } | 478 | } |
444 | } | 479 | } |
445 | 480 | ||
446 | 481 | ||
447 | int luaK_code0 (FuncState *fs, OpCode o) { | 482 | static void invertjump (FuncState *fs, expdesc *e) { |
448 | return luaK_code2(fs, o, 0, 0); | 483 | Instruction *pc = getjumpcontrol(fs, e->u.i.info); |
484 | *pc = SET_OPCODE(*pc, invertoperator(GET_OPCODE(*pc))); | ||
449 | } | 485 | } |
450 | 486 | ||
451 | 487 | ||
452 | int luaK_code1 (FuncState *fs, OpCode o, int arg1) { | 488 | static int jumponcond (FuncState *fs, expdesc *e, OpCode op) { |
453 | return luaK_code2(fs, o, arg1, 0); | 489 | if (e->k == VRELOCABLE) { |
490 | Instruction ie = getcode(fs, e); | ||
491 | if (GET_OPCODE(ie) == OP_NOT) { | ||
492 | op = invertoperator(op); | ||
493 | fs->pc--; /* remove previous OP_NOT */ | ||
494 | return luaK_condjump(fs, op, GETARG_B(ie), 0); | ||
495 | } | ||
496 | /* else go through */ | ||
497 | } | ||
498 | discharge2anyreg(fs, e); | ||
499 | freeexp(fs, e); | ||
500 | return luaK_condjump(fs, op, e->u.i.info, 0); | ||
454 | } | 501 | } |
455 | 502 | ||
456 | 503 | ||
457 | int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | 504 | void luaK_goiftrue (FuncState *fs, expdesc *e) { |
458 | Proto *f; | 505 | int pc; /* pc of last jump */ |
459 | Instruction i = previous_instruction(fs); | 506 | dischargevars(fs, e); |
460 | int push = (int)luaK_opproperties[o].push; | 507 | switch (e->k) { |
461 | int pop = (int)luaK_opproperties[o].pop; | 508 | case VK: case VNUMBER: { |
462 | int optm = 0; /* 1 when there is an optimization */ | 509 | pc = NO_JUMP; /* always true; do nothing */ |
463 | switch (o) { | ||
464 | case OP_CLOSURE: { | ||
465 | pop = arg2; | ||
466 | break; | 510 | break; |
467 | } | 511 | } |
468 | case OP_SETTABLE: { | 512 | case VNIL: { |
469 | pop = arg2; | 513 | pc = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); /* always jump */ |
470 | break; | 514 | break; |
471 | } | 515 | } |
472 | case OP_SETLIST: { | 516 | case VJMP: { |
473 | pop = fs->stacklevel - 1 - arg2; | 517 | invertjump(fs, e); |
518 | pc = e->u.i.info; | ||
474 | break; | 519 | break; |
475 | } | 520 | } |
476 | case OP_SETMAP: { | 521 | case VRELOCABLE: |
477 | pop = fs->stacklevel - 1 - arg1; | 522 | case VNONRELOC: { |
523 | pc = jumponcond(fs, e, OP_TESTF); | ||
478 | break; | 524 | break; |
479 | } | 525 | } |
480 | case OP_PUSHNIL: { | 526 | default: { |
481 | if (arg1 == 0) return NO_JUMP; /* nothing to do */ | 527 | pc = 0; /* to avoid warnings */ |
482 | push = arg1; | 528 | lua_assert(0); /* cannot happen */ |
483 | switch(GET_OPCODE(i)) { | ||
484 | case OP_PUSHNIL: SETARG_U(i, GETARG_U(i)+arg1); optm = 1; break; | ||
485 | default: break; | ||
486 | } | ||
487 | break; | 529 | break; |
488 | } | 530 | } |
489 | case OP_POP: { | 531 | } |
490 | if (arg1 == 0) return NO_JUMP; /* nothing to do */ | 532 | luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ |
491 | pop = arg1; | 533 | luaK_patchlist(fs, e->t, luaK_getlabel(fs)); |
492 | switch(GET_OPCODE(i)) { | 534 | e->t = NO_JUMP; |
493 | case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); optm = 1; break; | 535 | } |
494 | default: break; | 536 | |
495 | } | 537 | |
538 | static void luaK_goiffalse (FuncState *fs, expdesc *e) { | ||
539 | int pc; /* pc of last jump */ | ||
540 | dischargevars(fs, e); | ||
541 | switch (e->k) { | ||
542 | case VNIL: { | ||
543 | pc = NO_JUMP; /* always false; do nothing */ | ||
496 | break; | 544 | break; |
497 | } | 545 | } |
498 | case OP_GETTABLE: { | 546 | case VJMP: { |
499 | switch(GET_OPCODE(i)) { | 547 | pc = e->u.i.info; |
500 | case OP_PUSHSTRING: /* `t.x' */ | ||
501 | SET_OPCODE(i, OP_GETDOTTED); | ||
502 | optm = 1; | ||
503 | break; | ||
504 | case OP_GETLOCAL: /* `t[i]' */ | ||
505 | SET_OPCODE(i, OP_GETINDEXED); | ||
506 | optm = 1; | ||
507 | break; | ||
508 | default: break; | ||
509 | } | ||
510 | break; | 548 | break; |
511 | } | 549 | } |
512 | case OP_ADD: { | 550 | case VK: case VNUMBER: /* cannot optimize it (`or' must keep value) */ |
513 | switch(GET_OPCODE(i)) { | 551 | case VRELOCABLE: |
514 | case OP_PUSHINT: SET_OPCODE(i, OP_ADDI); optm = 1; break; /* `a+k' */ | 552 | case VNONRELOC: { |
515 | default: break; | 553 | pc = jumponcond(fs, e, OP_TESTT); |
516 | } | ||
517 | break; | 554 | break; |
518 | } | 555 | } |
519 | case OP_SUB: { | 556 | default: { |
520 | switch(GET_OPCODE(i)) { | 557 | pc = 0; /* to avoid warnings */ |
521 | case OP_PUSHINT: /* `a-k' */ | 558 | lua_assert(0); /* cannot happen */ |
522 | i = CREATE_S(OP_ADDI, -GETARG_S(i)); | ||
523 | optm = 1; | ||
524 | break; | ||
525 | default: break; | ||
526 | } | ||
527 | break; | 559 | break; |
528 | } | 560 | } |
529 | case OP_CONCAT: { | 561 | } |
530 | pop = arg1; | 562 | luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ |
531 | switch(GET_OPCODE(i)) { | 563 | luaK_patchlist(fs, e->f, luaK_getlabel(fs)); |
532 | case OP_CONCAT: /* `a..b..c' */ | 564 | e->f = NO_JUMP; |
533 | SETARG_U(i, GETARG_U(i)+1); | 565 | } |
534 | optm = 1; | 566 | |
535 | break; | 567 | |
536 | default: break; | 568 | static void codenot (FuncState *fs, expdesc *e) { |
537 | } | 569 | dischargevars(fs, e); |
570 | switch (e->k) { | ||
571 | case VNIL: { | ||
572 | e->u.n = 1; | ||
573 | e->k = VNUMBER; | ||
538 | break; | 574 | break; |
539 | } | 575 | } |
540 | case OP_MINUS: { | 576 | case VK: case VNUMBER: { |
541 | switch(GET_OPCODE(i)) { | 577 | e->k = VNIL; |
542 | case OP_PUSHINT: /* `-k' */ | ||
543 | SETARG_S(i, -GETARG_S(i)); | ||
544 | optm = 1; | ||
545 | break; | ||
546 | case OP_PUSHNUM: /* `-k' */ | ||
547 | SET_OPCODE(i, OP_PUSHNEGNUM); | ||
548 | optm = 1; | ||
549 | break; | ||
550 | default: break; | ||
551 | } | ||
552 | break; | 578 | break; |
553 | } | 579 | } |
554 | case OP_JMPNE: { | 580 | case VJMP: { |
555 | if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a~=nil' */ | 581 | invertjump(fs, e); |
556 | i = CREATE_S(OP_JMPT, NO_JUMP); | ||
557 | optm = 1; | ||
558 | } | ||
559 | break; | 582 | break; |
560 | } | 583 | } |
561 | case OP_JMPEQ: { | 584 | case VRELOCABLE: |
562 | if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a==nil' */ | 585 | case VNONRELOC: { |
563 | i = CREATE_0(OP_NOT); | 586 | discharge2anyreg(fs, e); |
564 | pop = 1; /* just undo effect of previous PUSHNIL */ | 587 | freeexp(fs, e); |
565 | optm = 1; | 588 | e->u.i.info = luaK_codeABC(fs, OP_NOT, 0, e->u.i.info, 0); |
566 | } | 589 | e->k = VRELOCABLE; |
567 | break; | 590 | break; |
568 | } | 591 | } |
569 | case OP_JMPT: | 592 | default: { |
570 | case OP_JMPONT: { | 593 | lua_assert(0); /* cannot happen */ |
571 | switch (GET_OPCODE(i)) { | ||
572 | case OP_NOT: { | ||
573 | i = CREATE_S(OP_JMPF, NO_JUMP); | ||
574 | optm = 1; | ||
575 | break; | ||
576 | } | ||
577 | case OP_PUSHINT: { | ||
578 | if (o == OP_JMPT) { /* JMPONT must keep original integer value */ | ||
579 | i = CREATE_S(OP_JMP, NO_JUMP); | ||
580 | optm = 1; | ||
581 | } | ||
582 | break; | ||
583 | } | ||
584 | case OP_PUSHNIL: { | ||
585 | if (GETARG_U(i) == 1) { | ||
586 | fs->pc--; /* erase previous instruction */ | ||
587 | luaK_deltastack(fs, -1); /* correct stack */ | ||
588 | return NO_JUMP; | ||
589 | } | ||
590 | break; | ||
591 | } | ||
592 | default: break; | ||
593 | } | ||
594 | break; | 594 | break; |
595 | } | 595 | } |
596 | case OP_JMPF: | 596 | } |
597 | case OP_JMPONF: { | 597 | /* interchange true and false lists */ |
598 | switch (GET_OPCODE(i)) { | 598 | { int temp = e->f; e->f = e->t; e->t = temp; } |
599 | case OP_NOT: { | 599 | } |
600 | i = CREATE_S(OP_JMPT, NO_JUMP); | 600 | |
601 | optm = 1; | 601 | |
602 | break; | 602 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { |
603 | } | 603 | t->u.i.aux = luaK_exp2RK(fs, k); |
604 | case OP_PUSHINT: { /* `while 1 do ...' */ | 604 | t->k = VINDEXED; |
605 | fs->pc--; /* erase previous instruction */ | 605 | } |
606 | luaK_deltastack(fs, -1); /* correct stack */ | 606 | |
607 | return NO_JUMP; | 607 | |
608 | } | 608 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { |
609 | case OP_PUSHNIL: { /* `repeat ... until nil' */ | 609 | if (op == OPR_MINUS) { |
610 | if (GETARG_U(i) == 1) { | 610 | luaK_exp2val(fs, e); |
611 | i = CREATE_S(OP_JMP, NO_JUMP); | 611 | if (e->k == VNUMBER) |
612 | optm = 1; | 612 | e->u.n = -e->u.n; |
613 | } | 613 | else { |
614 | break; | 614 | luaK_exp2anyreg(fs, e); |
615 | } | 615 | freeexp(fs, e); |
616 | default: break; | 616 | e->u.i.info = luaK_codeABC(fs, OP_UNM, 0, e->u.i.info, 0); |
617 | } | 617 | e->k = VRELOCABLE; |
618 | } | ||
619 | } | ||
620 | else /* op == NOT */ | ||
621 | codenot(fs, e); | ||
622 | } | ||
623 | |||
624 | |||
625 | void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | ||
626 | switch (op) { | ||
627 | case OPR_AND: { | ||
628 | luaK_goiftrue(fs, v); | ||
629 | break; | ||
630 | } | ||
631 | case OPR_OR: { | ||
632 | luaK_goiffalse(fs, v); | ||
633 | break; | ||
634 | } | ||
635 | case OPR_CONCAT: { | ||
636 | luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ | ||
618 | break; | 637 | break; |
619 | } | 638 | } |
620 | case OP_GETDOTTED: | 639 | case OPR_SUB: case OPR_DIV: case OPR_POW: { |
621 | case OP_GETINDEXED: | 640 | /* non-comutative operators */ |
622 | case OP_ADDI: { | 641 | luaK_exp2anyreg(fs, v); /* first operand must be a register */ |
623 | lua_assert(0); /* instruction used only for optimizations */ | ||
624 | break; | 642 | break; |
625 | } | 643 | } |
626 | default: { | 644 | default: { |
645 | luaK_exp2RK(fs, v); | ||
627 | break; | 646 | break; |
628 | } | 647 | } |
629 | } | 648 | } |
630 | f = fs->f; | 649 | } |
631 | lua_assert(push != VD); | 650 | |
632 | lua_assert(pop != VD); | 651 | |
633 | luaK_deltastack(fs, push); | 652 | |
634 | luaK_deltastack(fs, -pop); | 653 | /* opcode for each binary operator */ |
635 | if (optm) { /* optimize: put instruction in place of last one */ | 654 | static const OpCode codes[] = { /* ORDER OPR */ |
636 | f->code[fs->pc-1] = i; /* change previous instruction */ | 655 | OP_ADD, OP_SUB, OP_MUL, OP_DIV, |
637 | return fs->pc-1; /* do not generate new instruction */ | 656 | OP_POW, OP_CONCAT, |
657 | OP_TESTNE, OP_TESTEQ, | ||
658 | OP_TESTLT, OP_TESTLE, OP_TESTGT, OP_TESTGE | ||
659 | }; | ||
660 | |||
661 | |||
662 | /* `inverted' opcode for each binary operator */ | ||
663 | /* ( -1 means operator has no inverse) */ | ||
664 | static const OpCode invcodes[] = { /* ORDER OPR */ | ||
665 | OP_ADD, (OpCode)-1, OP_MUL, (OpCode)-1, | ||
666 | (OpCode)-1, (OpCode)-1, | ||
667 | OP_TESTNE, OP_TESTEQ, | ||
668 | OP_TESTGT, OP_TESTGE, OP_TESTLT, OP_TESTLE | ||
669 | }; | ||
670 | |||
671 | |||
672 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | ||
673 | switch (op) { | ||
674 | case OPR_AND: { | ||
675 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ | ||
676 | dischargevars(fs, e2); | ||
677 | luaK_concat(fs, &e1->f, e2->f); | ||
678 | e1->k = e2->k; e1->u = e2->u; e1->t = e2->t; | ||
679 | break; | ||
680 | } | ||
681 | case OPR_OR: { | ||
682 | lua_assert(e1->f == NO_JUMP); /* list must be closed */ | ||
683 | dischargevars(fs, e2); | ||
684 | luaK_concat(fs, &e1->t, e2->t); | ||
685 | e1->k = e2->k; e1->u = e2->u; e1->f = e2->f; | ||
686 | break; | ||
687 | } | ||
688 | case OPR_CONCAT: { | ||
689 | luaK_exp2val(fs, e2); | ||
690 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { | ||
691 | lua_assert(e1->u.i.info == GETARG_B(getcode(fs, e2))-1); | ||
692 | freeexp(fs, e1); | ||
693 | SETARG_B(getcode(fs, e2), e1->u.i.info); | ||
694 | e1->k = e2->k; e1->u.i.info = e2->u.i.info; | ||
695 | } | ||
696 | else { | ||
697 | luaK_exp2nextreg(fs, e2); | ||
698 | freeexp(fs, e2); | ||
699 | freeexp(fs, e1); | ||
700 | e1->u.i.info = luaK_codeABC(fs, codes[op], 0, e1->u.i.info, | ||
701 | e2->u.i.info); | ||
702 | e1->k = VRELOCABLE; | ||
703 | } | ||
704 | break; | ||
705 | } | ||
706 | case OPR_EQ: case OPR_NE: { | ||
707 | luaK_exp2val(fs, e2); | ||
708 | if (e2->k == VNIL) { /* exp x= nil ? */ | ||
709 | if (e1->k == VK) { /* constant x= nil ? */ | ||
710 | if (op == OPR_EQ) /* constant == nil ? */ | ||
711 | e1->k = VNIL; /* always false */ | ||
712 | /* else always true (leave the constant itself) */ | ||
713 | } | ||
714 | else { | ||
715 | OpCode opc = (op == OPR_EQ) ? OP_TESTF : OP_TESTT; | ||
716 | e1->u.i.info = jumponcond(fs, e1, opc); | ||
717 | e1->k = VJMP; | ||
718 | } | ||
719 | break; | ||
720 | } | ||
721 | /* else go through */ | ||
722 | } | ||
723 | default: { | ||
724 | int o1, o2; | ||
725 | OpCode opc; | ||
726 | if (e1->k != VK) { /* not a constant operator? */ | ||
727 | o1 = e1->u.i.info; | ||
728 | o2 = luaK_exp2RK(fs, e2); /* maybe other operator is constant... */ | ||
729 | opc = codes[op]; | ||
730 | } | ||
731 | else { /* invert operands */ | ||
732 | o2 = luaK_exp2RK(fs, e1); /* constant must be 2nd operand */ | ||
733 | o1 = luaK_exp2anyreg(fs, e2); /* other operator must be in register */ | ||
734 | opc = invcodes[op]; /* use inverted operator */ | ||
735 | } | ||
736 | freeexp(fs, e2); | ||
737 | freeexp(fs, e1); | ||
738 | if (op < OPR_NE) { /* ORDER OPR */ | ||
739 | e1->u.i.info = luaK_codeABC(fs, opc, 0, o1, o2); | ||
740 | e1->k = VRELOCABLE; | ||
741 | } | ||
742 | else { /* jump */ | ||
743 | e1->u.i.info = luaK_condjump(fs, opc, o1, o2); | ||
744 | e1->k = VJMP; | ||
745 | } | ||
746 | } | ||
638 | } | 747 | } |
639 | /* else build new instruction */ | 748 | } |
640 | switch ((enum Mode)luaK_opproperties[o].mode) { | 749 | |
641 | case iO: i = CREATE_0(o); break; | 750 | |
642 | case iU: i = CREATE_U(o, arg1); break; | 751 | static void codelineinfo (FuncState *fs) { |
643 | case iS: i = CREATE_S(o, arg1); break; | 752 | Proto *f = fs->f; |
644 | case iAB: i = CREATE_AB(o, arg1, arg2); break; | 753 | LexState *ls = fs->ls; |
754 | if (ls->lastline > fs->lastline) { | ||
755 | if (ls->lastline > fs->lastline+1) { | ||
756 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | ||
757 | MAX_INT, l_s("line info overflow")); | ||
758 | f->lineinfo[fs->nlineinfo++] = -(ls->lastline - (fs->lastline+1)); | ||
759 | } | ||
760 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | ||
761 | MAX_INT, l_s("line info overflow")); | ||
762 | f->lineinfo[fs->nlineinfo++] = fs->pc; | ||
763 | fs->lastline = ls->lastline; | ||
645 | } | 764 | } |
765 | } | ||
766 | |||
767 | |||
768 | static int luaK_code (FuncState *fs, Instruction i) { | ||
769 | Proto *f; | ||
646 | codelineinfo(fs); | 770 | codelineinfo(fs); |
771 | f = fs->f; | ||
647 | /* put new instruction in code array */ | 772 | /* put new instruction in code array */ |
648 | luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, | 773 | luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, |
649 | MAX_INT, l_s("code size overflow")); | 774 | MAX_INT, l_s("code size overflow")); |
650 | f->code[fs->pc] = i; | 775 | f->code[fs->pc] = i; |
776 | /*printf("free: %d ", fs->freereg); printopcode(f, fs->pc);*/ | ||
651 | return fs->pc++; | 777 | return fs->pc++; |
652 | } | 778 | } |
653 | 779 | ||
654 | 780 | ||
655 | const OpProperties luaK_opproperties[] = { | 781 | int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { |
656 | {iU, 0, 0}, /* OP_RETURN */ | 782 | lua_assert(getOpMode(o) == iABC); |
657 | {iAB, 0, 0}, /* OP_CALL */ | 783 | return luaK_code(fs, CREATE_ABC(o, a, b, c)); |
658 | {iU, VD, 0}, /* OP_PUSHNIL */ | 784 | } |
659 | {iU, 0, VD}, /* OP_POP */ | 785 | |
660 | {iS, 1, 0}, /* OP_PUSHINT */ | 786 | |
661 | {iU, 1, 0}, /* OP_PUSHSTRING */ | 787 | int luaK_codeABc (FuncState *fs, OpCode o, int a, int bc) { |
662 | {iU, 1, 0}, /* OP_PUSHNUM */ | 788 | lua_assert(getOpMode(o) == iABc || getOpMode(o) == iAsBc); |
663 | {iU, 1, 0}, /* OP_PUSHNEGNUM */ | 789 | return luaK_code(fs, CREATE_ABc(o, a, bc)); |
664 | {iU, 1, 0}, /* OP_PUSHUPVALUE */ | 790 | } |
665 | {iU, 1, 0}, /* OP_GETLOCAL */ | ||
666 | {iU, 1, 0}, /* OP_GETGLOBAL */ | ||
667 | {iO, 1, 2}, /* OP_GETTABLE */ | ||
668 | {iU, 1, 1}, /* OP_GETDOTTED */ | ||
669 | {iU, 1, 1}, /* OP_GETINDEXED */ | ||
670 | {iU, 2, 1}, /* OP_PUSHSELF */ | ||
671 | {iU, 1, 0}, /* OP_CREATETABLE */ | ||
672 | {iU, 0, 1}, /* OP_SETLOCAL */ | ||
673 | {iU, 0, 1}, /* OP_SETGLOBAL */ | ||
674 | {iAB, 0, VD}, /* OP_SETTABLE */ | ||
675 | {iAB, 0, VD}, /* OP_SETLIST */ | ||
676 | {iU, 0, VD}, /* OP_SETMAP */ | ||
677 | {iO, 1, 2}, /* OP_ADD */ | ||
678 | {iS, 1, 1}, /* OP_ADDI */ | ||
679 | {iO, 1, 2}, /* OP_SUB */ | ||
680 | {iO, 1, 2}, /* OP_MULT */ | ||
681 | {iO, 1, 2}, /* OP_DIV */ | ||
682 | {iO, 1, 2}, /* OP_POW */ | ||
683 | {iU, 1, VD}, /* OP_CONCAT */ | ||
684 | {iO, 1, 1}, /* OP_MINUS */ | ||
685 | {iO, 1, 1}, /* OP_NOT */ | ||
686 | {iS, 0, 2}, /* OP_JMPNE */ | ||
687 | {iS, 0, 2}, /* OP_JMPEQ */ | ||
688 | {iS, 0, 2}, /* OP_JMPLT */ | ||
689 | {iS, 0, 2}, /* OP_JMPLE */ | ||
690 | {iS, 0, 2}, /* OP_JMPGT */ | ||
691 | {iS, 0, 2}, /* OP_JMPGE */ | ||
692 | {iS, 0, 1}, /* OP_JMPT */ | ||
693 | {iS, 0, 1}, /* OP_JMPF */ | ||
694 | {iS, 0, 1}, /* OP_JMPONT */ | ||
695 | {iS, 0, 1}, /* OP_JMPONF */ | ||
696 | {iS, 0, 0}, /* OP_JMP */ | ||
697 | {iO, 0, 0}, /* OP_PUSHNILJMP */ | ||
698 | {iS, 0, 0}, /* OP_FORPREP */ | ||
699 | {iS, 0, 3}, /* OP_FORLOOP */ | ||
700 | {iS, 3, 0}, /* OP_LFORPREP */ | ||
701 | {iS, 0, 4}, /* OP_LFORLOOP */ | ||
702 | {iAB, 1, VD} /* OP_CLOSURE */ | ||
703 | }; | ||
704 | 791 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.h,v 1.20 2001/02/20 18:15:33 roberto Exp roberto $ | 2 | ** $Id: lcode.h,v 1.21 2001/02/23 17:17:25 roberto Exp roberto $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -31,43 +31,36 @@ typedef enum BinOpr { | |||
31 | OPR_NOBINOPR | 31 | OPR_NOBINOPR |
32 | } BinOpr; | 32 | } BinOpr; |
33 | 33 | ||
34 | typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; | 34 | #define binopistest(op) ((op) >= OPR_NE) |
35 | |||
36 | |||
37 | enum Mode {iO, iU, iS, iAB}; /* instruction format */ | ||
38 | 35 | ||
39 | #define VD 100 /* flag for variable delta */ | 36 | typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; |
40 | |||
41 | typedef struct OpProperties { | ||
42 | lu_byte mode; | ||
43 | lu_byte push; | ||
44 | lu_byte pop; | ||
45 | } OpProperties; | ||
46 | 37 | ||
47 | extern const OpProperties luaK_opproperties[]; | ||
48 | 38 | ||
39 | #define luaK_codeAsBc(fs,o,A,sBc) luaK_codeABc(fs,o,A,(sBc)+MAXARG_sBc) | ||
49 | 40 | ||
50 | void luaK_error (LexState *ls, const l_char *msg); | 41 | void luaK_error (LexState *ls, const l_char *msg); |
51 | int luaK_code0 (FuncState *fs, OpCode o); | 42 | int luaK_codeABc (FuncState *fs, OpCode o, int A, int Bc); |
52 | int luaK_code1 (FuncState *fs, OpCode o, int arg1); | 43 | int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); |
53 | int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2); | 44 | void luaK_nil (FuncState *fs, int from, int n); |
45 | void luaK_reserveregs (FuncState *fs, int n); | ||
46 | int luaK_stringk (FuncState *fs, TString *s); | ||
47 | int luaK_exp2anyreg (FuncState *fs, expdesc *e); | ||
48 | void luaK_exp2nextreg (FuncState *fs, expdesc *e); | ||
49 | void luaK_exp2val (FuncState *fs, expdesc *e); | ||
50 | int luaK_exp2RK (FuncState *fs, expdesc *e); | ||
51 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key); | ||
52 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); | ||
53 | void luaK_goiftrue (FuncState *fs, expdesc *e); | ||
54 | void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); | ||
55 | void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); | ||
54 | int luaK_jump (FuncState *fs); | 56 | int luaK_jump (FuncState *fs); |
55 | void luaK_patchlist (FuncState *fs, int list, int target); | 57 | void luaK_patchlist (FuncState *fs, int list, int target); |
56 | void luaK_fixfor (FuncState *fs, int pc, int dest); | 58 | void luaK_fixfor (FuncState *fs, int pc, int dest); |
57 | void luaK_concat (FuncState *fs, int *l1, int l2); | 59 | void luaK_concat (FuncState *fs, int *l1, int l2); |
58 | void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue); | ||
59 | int luaK_getlabel (FuncState *fs); | 60 | int luaK_getlabel (FuncState *fs); |
60 | void luaK_deltastack (FuncState *fs, int delta); | 61 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); |
61 | void luaK_kstr (LexState *ls, int c); | 62 | void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); |
62 | void luaK_number (FuncState *fs, lua_Number f); | 63 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); |
63 | void luaK_adjuststack (FuncState *fs, int n); | ||
64 | int luaK_lastisopen (FuncState *fs); | ||
65 | void luaK_setcallreturns (FuncState *fs, int nresults); | ||
66 | void luaK_tostack (LexState *ls, expdesc *v, int onlyone); | ||
67 | void luaK_storevar (LexState *ls, const expdesc *var); | ||
68 | void luaK_prefix (LexState *ls, UnOpr op, expdesc *v); | ||
69 | void luaK_infix (LexState *ls, BinOpr op, expdesc *v); | ||
70 | void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2); | ||
71 | 64 | ||
72 | 65 | ||
73 | #endif | 66 | #endif |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 1.75 2001/03/26 14:31:49 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 1.76 2001/04/06 18:25:00 roberto Exp roberto $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -22,6 +22,7 @@ | |||
22 | #include "ltable.h" | 22 | #include "ltable.h" |
23 | #include "ltm.h" | 23 | #include "ltm.h" |
24 | #include "luadebug.h" | 24 | #include "luadebug.h" |
25 | #include "lvm.h" | ||
25 | 26 | ||
26 | 27 | ||
27 | 28 | ||
@@ -298,6 +299,10 @@ LUA_API int lua_getinfo (lua_State *L, const l_char *what, lua_Debug *ar) { | |||
298 | 299 | ||
299 | #define check(x) if (!(x)) return 0; | 300 | #define check(x) if (!(x)) return 0; |
300 | 301 | ||
302 | #define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) | ||
303 | |||
304 | #define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) | ||
305 | |||
301 | 306 | ||
302 | static int checklineinfo (const Proto *pt) { | 307 | static int checklineinfo (const Proto *pt) { |
303 | int *lineinfo = pt->lineinfo; | 308 | int *lineinfo = pt->lineinfo; |
@@ -318,231 +323,199 @@ static int precheck (const Proto *pt) { | |||
318 | } | 323 | } |
319 | 324 | ||
320 | 325 | ||
321 | /* value for non-initialized entries in array stacklevel */ | 326 | static int checkopenop (Instruction i) { |
322 | #define SL_EMPTY 255 | 327 | OpCode op = GET_OPCODE(i); |
323 | 328 | switch (op) { | |
324 | #define checkjump(pt,sl,top,pc) if (!checkjump_aux(pt,sl,top,pc)) return 0; | 329 | case OP_CALL: |
325 | 330 | case OP_RETURN: { | |
326 | static int checkjump_aux (const Proto *pt, lu_byte *sl, int top, int pc) { | 331 | check(GETARG_B(i) == NO_REG); |
327 | check(0 <= pc && pc < pt->sizecode); | 332 | return 1; |
328 | if (sl == NULL) return 1; /* not full checking */ | 333 | } |
329 | if (sl[pc] == SL_EMPTY) | 334 | case OP_SETLISTO: return 1; |
330 | sl[pc] = (lu_byte)top; | 335 | default: return 0; /* invalid instruction after an open call */ |
331 | else | 336 | } |
332 | check(sl[pc] == top); | ||
333 | return 1; | ||
334 | } | 337 | } |
335 | 338 | ||
336 | 339 | ||
337 | static Instruction luaG_symbexec (lua_State *L, const Proto *pt, | 340 | static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { |
338 | int lastpc, int stackpos) { | ||
339 | int stack[MAXSTACK]; /* stores last instruction that changed a stack entry */ | ||
340 | lu_byte *sl = NULL; | ||
341 | int top; | ||
342 | int pc; | 341 | int pc; |
343 | if (stackpos < 0) { /* full check? */ | 342 | int last; /* stores position of last instruction that changed `reg' */ |
344 | int i; | 343 | last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ |
345 | sl = luaO_openspace(L, pt->sizecode, lu_byte); | 344 | if (reg == NO_REG) /* full check? */ |
346 | for (i=0; i<pt->sizecode; i++) /* initialize stack-level array */ | ||
347 | sl[i] = SL_EMPTY; | ||
348 | check(precheck(pt)); | 345 | check(precheck(pt)); |
349 | } | 346 | for (pc = 0; pc < lastpc; pc++) { |
350 | top = pt->numparams; | 347 | const Instruction i = pt->code[pc]; |
351 | pc = 0; | ||
352 | if (pt->is_vararg) /* varargs? */ | ||
353 | top++; /* `arg' */ | ||
354 | if (sl) sl[0] = (lu_byte)top; | ||
355 | while (pc < lastpc) { | ||
356 | const Instruction i = pt->code[pc++]; | ||
357 | OpCode op = GET_OPCODE(i); | 348 | OpCode op = GET_OPCODE(i); |
358 | int arg1 = 0; | 349 | int a = GETARG_A(i); |
359 | int arg2 = 0; | 350 | int b = 0; |
360 | int push, pop; | 351 | int c = 0; |
361 | check(op < NUM_OPCODES); | 352 | #undef check |
362 | push = (int)luaK_opproperties[op].push; | 353 | #define check(x) if (!(x)) { \ |
363 | pop = (int)luaK_opproperties[op].pop; | 354 | printf(">>>%d %d %d %d %d %d\n", op, a, b, c, pt->maxstacksize, pt->sizek); \ |
364 | switch ((enum Mode)luaK_opproperties[op].mode) { | 355 | return 0; } |
365 | case iO: break; | 356 | switch (getOpMode(op)) { |
366 | case iU: arg1 = GETARG_U(i); check(arg1 >= 0); break; | 357 | case iABC: { |
367 | case iS: arg1 = GETARG_S(i); break; | 358 | b = GETARG_B(i); |
368 | case iAB: | 359 | c = GETARG_C(i); |
369 | arg1 = GETARG_A(i); arg2 = GETARG_B(i); check(arg1 >= 0); break; | 360 | if (testOpMode(op, OpModeBreg)) { |
370 | } | 361 | checkreg(pt, b); |
371 | switch (op) { | 362 | check(c < pt->maxstacksize || |
372 | case OP_RETURN: { | 363 | (c >= MAXSTACK && c-MAXSTACK < pt->sizek)); |
373 | check(arg1 <= top); | 364 | } |
374 | pop = top-arg1; | ||
375 | break; | 365 | break; |
376 | } | 366 | } |
377 | case OP_CALL: { | 367 | case iABc: { |
378 | if (arg2 == MULT_RET) arg2 = 1; | 368 | b = GETARG_Bc(i); |
379 | check(arg1 < top); | 369 | if (testOpMode(op, OpModeK)) check(b < pt->sizek); |
380 | pop = top-arg1; | ||
381 | push = arg2; | ||
382 | break; | 370 | break; |
383 | } | 371 | } |
384 | case OP_PUSHNIL: { | 372 | case iAsBc: { |
385 | check(arg1 > 0); | 373 | b = GETARG_sBc(i); |
386 | push = arg1; | ||
387 | break; | 374 | break; |
388 | } | 375 | } |
389 | case OP_POP: { | 376 | } |
390 | pop = arg1; | 377 | if (testOpMode(op, OpModeAreg)) checkreg(pt, a); |
378 | if (testOpMode(op, OpModesetA)) { | ||
379 | if (a == reg) last = pc; /* change register `a' */ | ||
380 | } | ||
381 | if (testOpMode(op, OpModeT)) | ||
382 | check(GET_OPCODE(pt->code[pc+1]) == OP_CJMP); | ||
383 | switch (op) { | ||
384 | case OP_LOADNIL: { | ||
385 | if (a <= reg && reg <= b) | ||
386 | last = pc; /* set registers from `a' to `b' */ | ||
391 | break; | 387 | break; |
392 | } | 388 | } |
393 | case OP_PUSHSTRING: | 389 | case OP_LOADUPVAL: { |
394 | case OP_GETGLOBAL: | 390 | check(b < pt->nupvalues); |
395 | case OP_GETDOTTED: | ||
396 | case OP_PUSHSELF: | ||
397 | case OP_SETGLOBAL: { | ||
398 | check(arg1 < pt->sizekstr); | ||
399 | break; | 391 | break; |
400 | } | 392 | } |
401 | case OP_PUSHNUM: | 393 | case OP_GETGLOBAL: |
402 | case OP_PUSHNEGNUM: { | 394 | case OP_SETGLOBAL: { |
403 | check(arg1 < pt->sizeknum); | 395 | check(ttype(&pt->k[b]) == LUA_TSTRING); |
404 | break; | 396 | break; |
405 | } | 397 | } |
406 | case OP_PUSHUPVALUE: { | 398 | case OP_SELF: { |
407 | check(arg1 < pt->nupvalues); | 399 | checkreg(pt, a+1); |
400 | if (reg == a+1) last = pc; | ||
408 | break; | 401 | break; |
409 | } | 402 | } |
410 | case OP_GETLOCAL: | 403 | case OP_CONCAT: { |
411 | case OP_GETINDEXED: | 404 | check(b < c); /* at least two operands */ |
412 | case OP_SETLOCAL: { | ||
413 | check(arg1 < top); | ||
414 | break; | 405 | break; |
415 | } | 406 | } |
416 | case OP_SETTABLE: { | 407 | case OP_JMP: |
417 | check(3 <= arg1 && arg1 <= top); | 408 | case OP_CJMP: { |
418 | pop = arg2; | 409 | int dest = pc+1+b; |
410 | check(0 <= dest && dest < pt->sizecode); | ||
411 | /* not full check and jump is forward and do not skip `lastpc'? */ | ||
412 | if (reg != NO_REG && pc < dest && dest <= lastpc) | ||
413 | pc += b; /* do the jump */ | ||
419 | break; | 414 | break; |
420 | } | 415 | } |
421 | case OP_SETLIST: { | 416 | case OP_TESTT: |
422 | check(arg2 >= 0); | 417 | case OP_TESTF: { |
423 | pop = top-arg2-1; | 418 | if (a != NO_REG) |
419 | checkreg(pt, a); | ||
424 | break; | 420 | break; |
425 | } | 421 | } |
426 | case OP_SETMAP: { | 422 | case OP_NILJMP: { |
427 | check(arg1 >= 0); | 423 | check(pc+2 < pt->sizecode); /* check its jump */ |
428 | pop = top-arg1-1; | ||
429 | break; | 424 | break; |
430 | } | 425 | } |
431 | case OP_CONCAT: { | 426 | case OP_CALL: { |
432 | pop = arg1; | 427 | if (b == NO_REG) b = pt->maxstacksize; |
428 | if (c == NO_REG) { | ||
429 | check(checkopenop(pt->code[pc+1])); | ||
430 | c = 1; | ||
431 | } | ||
432 | check(b > a); | ||
433 | checkreg(pt, b-1); | ||
434 | checkreg(pt, a+c-1); | ||
435 | if (reg >= a) last = pc; /* affect all registers above base */ | ||
433 | break; | 436 | break; |
434 | } | 437 | } |
435 | case OP_CLOSURE: { | 438 | case OP_RETURN: { |
436 | check(arg1 < pt->sizekproto); | 439 | if (b == NO_REG) b = pt->maxstacksize; |
437 | check(arg2 == pt->kproto[arg1]->nupvalues); | 440 | checkreg(pt, b-1); |
438 | pop = arg2; | ||
439 | break; | 441 | break; |
440 | } | 442 | } |
441 | case OP_JMPNE: | 443 | case OP_FORPREP: |
442 | case OP_JMPEQ: | 444 | case OP_TFORPREP: { |
443 | case OP_JMPLT: | 445 | int dest = pc-b; /* jump is negated here */ |
444 | case OP_JMPLE: | 446 | check(0 <= dest && dest < pt->sizecode && |
445 | case OP_JMPGT: | 447 | GET_OPCODE(pt->code[dest]) == op+1); |
446 | case OP_JMPGE: | ||
447 | case OP_JMPT: | ||
448 | case OP_JMPF: | ||
449 | case OP_JMP: { | ||
450 | checkjump(pt, sl, top-pop, pc+arg1); | ||
451 | break; | 448 | break; |
452 | } | 449 | } |
453 | case OP_FORLOOP: | 450 | case OP_FORLOOP: |
454 | case OP_LFORLOOP: | 451 | case OP_TFORLOOP: { |
455 | case OP_JMPONT: | 452 | int dest = pc+b; |
456 | case OP_JMPONF: { | 453 | check(0 <= dest && dest < pt->sizecode && |
457 | int newpc = pc+arg1; | 454 | pt->code[dest] == SET_OPCODE(i, op-1)); |
458 | checkjump(pt, sl, top, newpc); | 455 | checkreg(pt, a + ((op == OP_FORLOOP) ? 2 : 3)); |
459 | /* jump is forward and do not skip `lastpc' and not full check? */ | ||
460 | if (pc < newpc && newpc <= lastpc && stackpos >= 0) { | ||
461 | stack[top-1] = pc-1; /* value comes from `and'/`or' */ | ||
462 | pc = newpc; /* do the jump */ | ||
463 | pop = 0; /* do not pop */ | ||
464 | } | ||
465 | break; | ||
466 | } | ||
467 | case OP_PUSHNILJMP: { | ||
468 | check(GET_OPCODE(pt->code[pc]) == OP_PUSHINT); /* only valid sequence */ | ||
469 | break; | 456 | break; |
470 | } | 457 | } |
471 | case OP_FORPREP: { | 458 | case OP_SETLIST: { |
472 | int endfor = pc-arg1-1; /* jump is `negative' here */ | 459 | checkreg(pt, a + (b&(LFIELDS_PER_FLUSH-1)) + 1); |
473 | check(top >= 3); | ||
474 | checkjump(pt, sl, top+push, endfor); | ||
475 | check(GET_OPCODE(pt->code[endfor]) == OP_FORLOOP); | ||
476 | check(GETARG_S(pt->code[endfor]) == arg1); | ||
477 | break; | ||
478 | } | ||
479 | case OP_LFORPREP: { | ||
480 | int endfor = pc-arg1-1; /* jump is `negative' here */ | ||
481 | check(top >= 1); | ||
482 | checkjump(pt, sl, top+push, endfor); | ||
483 | check(GET_OPCODE(pt->code[endfor]) == OP_LFORLOOP); | ||
484 | check(GETARG_S(pt->code[endfor]) == arg1); | ||
485 | break; | 460 | break; |
486 | } | 461 | } |
487 | case OP_PUSHINT: | 462 | case OP_CLOSURE: { |
488 | case OP_GETTABLE: | 463 | check(b < pt->sizekproto); |
489 | case OP_CREATETABLE: | 464 | checkreg(pt, a + pt->kproto[b]->nupvalues - 1); |
490 | case OP_ADD: | ||
491 | case OP_ADDI: | ||
492 | case OP_SUB: | ||
493 | case OP_MULT: | ||
494 | case OP_DIV: | ||
495 | case OP_POW: | ||
496 | case OP_MINUS: | ||
497 | case OP_NOT: { | ||
498 | break; | 465 | break; |
499 | } | 466 | } |
467 | default: break; | ||
500 | } | 468 | } |
501 | top -= pop; | ||
502 | check(0 <= top && top+push <= pt->maxstacksize); | ||
503 | while (push--) stack[top++] = pc-1; | ||
504 | checkjump(pt, sl, top, pc); | ||
505 | } | 469 | } |
506 | return (stackpos >= 0) ? pt->code[stack[stackpos]] : 1; | 470 | return pt->code[last]; |
507 | } | 471 | } |
508 | 472 | ||
509 | /* }====================================================== */ | 473 | /* }====================================================== */ |
510 | 474 | ||
511 | 475 | ||
512 | int luaG_checkcode (lua_State *L, const Proto *pt) { | 476 | int luaG_checkcode (const Proto *pt) { |
513 | return luaG_symbexec(L, pt, pt->sizecode-1, -1); | 477 | return luaG_symbexec(pt, pt->sizecode, NO_REG); |
514 | } | 478 | } |
515 | 479 | ||
516 | 480 | ||
517 | static const l_char *getobjname (lua_State *L, StkId obj, const l_char **name) { | 481 | static const l_char *getobjname (lua_State *L, StkId obj, const l_char **name) { |
518 | CallInfo *ci = ci_stack(L, obj); | 482 | CallInfo *ci = ci_stack(L, obj); |
519 | if (!isLmark(ci)) | 483 | if (isLmark(ci)) { /* an active Lua function? */ |
520 | return NULL; /* not an active Lua function */ | ||
521 | else { | ||
522 | Proto *p = ci_func(ci)->f.l; | 484 | Proto *p = ci_func(ci)->f.l; |
523 | int pc = currentpc(ci); | 485 | int pc = currentpc(ci); |
524 | int stackpos = obj - ci->base; | 486 | int stackpos = obj - ci->base; |
525 | Instruction i = luaG_symbexec(L, p, pc, stackpos); | 487 | Instruction i; |
488 | *name = luaF_getlocalname(p, stackpos+1, pc); | ||
489 | if (*name) /* is a local? */ | ||
490 | return l_s("local"); | ||
491 | i = luaG_symbexec(p, pc, stackpos); /* try symbolic execution */ | ||
526 | lua_assert(pc != -1); | 492 | lua_assert(pc != -1); |
527 | switch (GET_OPCODE(i)) { | 493 | switch (GET_OPCODE(i)) { |
528 | case OP_GETGLOBAL: { | 494 | case OP_GETGLOBAL: { |
529 | *name = getstr(p->kstr[GETARG_U(i)]); | 495 | lua_assert(ttype(&p->k[GETARG_Bc(i)]) == LUA_TSTRING); |
496 | *name = getstr(tsvalue(&p->k[GETARG_Bc(i)])); | ||
530 | return l_s("global"); | 497 | return l_s("global"); |
531 | } | 498 | } |
532 | case OP_GETLOCAL: { | 499 | case OP_MOVE: { |
533 | *name = luaF_getlocalname(p, GETARG_U(i)+1, pc); | 500 | int a = GETARG_A(i); |
534 | lua_assert(*name); | 501 | int b = GETARG_B(i); /* move from `b' to `a' */ |
535 | return l_s("local"); | 502 | if (b < a) |
503 | return getobjname(L, ci->base+b, name); /* get name for `b' */ | ||
504 | break; | ||
536 | } | 505 | } |
537 | case OP_PUSHSELF: | 506 | case OP_GETTABLE: |
538 | case OP_GETDOTTED: { | 507 | case OP_SELF: { |
539 | *name = getstr(p->kstr[GETARG_U(i)]); | 508 | int c = GETARG_C(i) - MAXSTACK; |
540 | return l_s("field"); | 509 | if (c >= 0 && ttype(&p->k[c]) == LUA_TSTRING) { |
510 | *name = getstr(tsvalue(&p->k[c])); | ||
511 | return l_s("field"); | ||
512 | } | ||
513 | break; | ||
541 | } | 514 | } |
542 | default: | 515 | default: break; |
543 | return NULL; /* no useful name found */ | ||
544 | } | 516 | } |
545 | } | 517 | } |
518 | return NULL; /* no useful name found */ | ||
546 | } | 519 | } |
547 | 520 | ||
548 | 521 | ||
@@ -576,10 +549,18 @@ void luaG_typeerror (lua_State *L, StkId o, const l_char *op) { | |||
576 | } | 549 | } |
577 | 550 | ||
578 | 551 | ||
579 | void luaG_binerror (lua_State *L, StkId p1, int t, const l_char *op) { | 552 | void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { |
580 | if (ttype(p1) == t) p1++; | 553 | if (ttype(p1) == LUA_TSTRING) p1 = p2; |
581 | lua_assert(ttype(p1) != t); | 554 | lua_assert(ttype(p1) != LUA_TSTRING); |
582 | luaG_typeerror(L, p1, op); | 555 | luaG_typeerror(L, p1, l_s("concat")); |
556 | } | ||
557 | |||
558 | |||
559 | void luaG_aritherror (lua_State *L, StkId p1, TObject *p2) { | ||
560 | TObject temp; | ||
561 | if (luaV_tonumber(p1, &temp) != NULL) | ||
562 | p1 = p2; /* first operand is OK; error is in the second */ | ||
563 | luaG_typeerror(L, p1, l_s("perform arithmetic on")); | ||
583 | } | 564 | } |
584 | 565 | ||
585 | 566 | ||
@@ -592,3 +573,52 @@ void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) { | |||
592 | luaO_verror(L, l_s("attempt to compare %.10s with %.10s"), t1, t2); | 573 | luaO_verror(L, l_s("attempt to compare %.10s with %.10s"), t1, t2); |
593 | } | 574 | } |
594 | 575 | ||
576 | |||
577 | |||
578 | #define opmode(t,a,b,c,sa,k,m) (((t)<<OpModeT) | \ | ||
579 | ((a)<<OpModeAreg) | ((b)<<OpModeBreg) | ((c)<<OpModeCreg) | \ | ||
580 | ((sa)<<OpModesetA) | ((k)<<OpModeK) | (m)) | ||
581 | |||
582 | |||
583 | const unsigned char luaG_opmodes[] = { | ||
584 | /* T A B C sA K mode opcode */ | ||
585 | opmode(0,1,1,0, 1,0,iABC), /* OP_MOVE */ | ||
586 | opmode(0,1,0,0, 1,1,iABc), /* OP_LOADK */ | ||
587 | opmode(0,1,0,0, 1,0,iAsBc), /* OP_LOADINT */ | ||
588 | opmode(0,1,1,0, 1,0,iABC), /* OP_LOADNIL */ | ||
589 | opmode(0,1,0,0, 1,0,iABc), /* OP_LOADUPVAL */ | ||
590 | opmode(0,1,0,0, 1,1,iABc), /* OP_GETGLOBAL */ | ||
591 | opmode(0,1,1,1, 1,0,iABC), /* OP_GETTABLE */ | ||
592 | opmode(0,1,0,0, 0,1,iABc), /* OP_SETGLOBAL */ | ||
593 | opmode(0,1,1,1, 0,0,iABC), /* OP_SETTABLE */ | ||
594 | opmode(0,1,0,0, 1,0,iABc), /* OP_NEWTABLE */ | ||
595 | opmode(0,1,1,1, 1,0,iABC), /* OP_SELF */ | ||
596 | opmode(0,1,1,1, 1,0,iABC), /* OP_ADD */ | ||
597 | opmode(0,1,1,1, 1,0,iABC), /* OP_SUB */ | ||
598 | opmode(0,1,1,1, 1,0,iABC), /* OP_MUL */ | ||
599 | opmode(0,1,1,1, 1,0,iABC), /* OP_DIV */ | ||
600 | opmode(0,1,1,1, 1,0,iABC), /* OP_POW */ | ||
601 | opmode(0,1,1,0, 1,0,iABC), /* OP_UNM */ | ||
602 | opmode(0,1,1,0, 1,0,iABC), /* OP_NOT */ | ||
603 | opmode(0,1,1,1, 1,0,iABC), /* OP_CONCAT */ | ||
604 | opmode(0,0,0,0, 0,0,iAsBc), /* OP_JMP */ | ||
605 | opmode(0,0,0,0, 0,0,iAsBc), /* OP_CJMP */ | ||
606 | opmode(1,0,1,1, 0,0,iABC), /* OP_TESTEQ */ | ||
607 | opmode(1,0,1,1, 0,0,iABC), /* OP_TESTNE */ | ||
608 | opmode(1,0,1,1, 0,0,iABC), /* OP_TESTLT */ | ||
609 | opmode(1,0,1,1, 0,0,iABC), /* OP_TESTLE */ | ||
610 | opmode(1,0,1,1, 0,0,iABC), /* OP_TESTGT */ | ||
611 | opmode(1,0,1,1, 0,0,iABC), /* OP_TESTGE */ | ||
612 | opmode(1,0,1,0, 1,0,iABC), /* OP_TESTT */ | ||
613 | opmode(1,0,1,0, 1,0,iABC), /* OP_TESTF */ | ||
614 | opmode(0,1,0,0, 1,0,iAsBc), /* OP_NILJMP */ | ||
615 | opmode(0,1,0,0, 0,0,iABC), /* OP_CALL */ | ||
616 | opmode(0,1,0,0, 0,0,iABC), /* OP_RETURN */ | ||
617 | opmode(0,1,0,0, 0,0,iAsBc), /* OP_FORPREP */ | ||
618 | opmode(0,1,0,0, 0,0,iAsBc), /* OP_FORLOOP */ | ||
619 | opmode(0,1,0,0, 0,0,iAsBc), /* OP_TFORPREP */ | ||
620 | opmode(0,1,0,0, 0,0,iAsBc), /* OP_TFORLOOP */ | ||
621 | opmode(0,1,0,0, 0,0,iABc), /* OP_SETLIST */ | ||
622 | opmode(0,1,0,0, 0,0,iABc), /* OP_SETLIST0 */ | ||
623 | opmode(0,1,0,0, 0,0,iABc) /* OP_CLOSURE */ | ||
624 | }; | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.h,v 1.10 2001/02/12 19:54:50 roberto Exp roberto $ | 2 | ** $Id: ldebug.h,v 1.11 2001/02/23 17:17:25 roberto Exp roberto $ |
3 | ** Auxiliary functions from Debug Interface module | 3 | ** Auxiliary functions from Debug Interface module |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -12,11 +12,32 @@ | |||
12 | #include "luadebug.h" | 12 | #include "luadebug.h" |
13 | 13 | ||
14 | 14 | ||
15 | enum OpMode {iABC, iABc, iAsBc}; /* basic instruction format */ | ||
16 | |||
17 | /* | ||
18 | ** masks for instruction properties | ||
19 | */ | ||
20 | enum OpModeMask { | ||
21 | OpModeAreg = 2, /* A is a register */ | ||
22 | OpModeBreg, /* B is a register */ | ||
23 | OpModeCreg, /* C is a register/constant */ | ||
24 | OpModesetA, /* instruction set register A */ | ||
25 | OpModeK, /* Bc is a constant */ | ||
26 | OpModeT /* operator is a test */ | ||
27 | }; | ||
28 | |||
29 | extern const unsigned char luaG_opmodes[]; | ||
30 | |||
31 | #define getOpMode(m) ((enum OpMode)(luaG_opmodes[m] & 3)) | ||
32 | #define testOpMode(m, b) (luaG_opmodes[m] & (1 << (b))) | ||
33 | |||
34 | |||
15 | void luaG_typeerror (lua_State *L, StkId o, const l_char *op); | 35 | void luaG_typeerror (lua_State *L, StkId o, const l_char *op); |
16 | void luaG_binerror (lua_State *L, StkId p1, int t, const l_char *op); | 36 | void luaG_concaterror (lua_State *L, StkId p1, StkId p2); |
37 | void luaG_aritherror (lua_State *L, StkId p1, TObject *p2); | ||
17 | int luaG_getline (int *lineinfo, int pc, int refline, int *refi); | 38 | int luaG_getline (int *lineinfo, int pc, int refline, int *refi); |
18 | void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2); | 39 | void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2); |
19 | int luaG_checkcode (lua_State *L, const Proto *pt); | 40 | int luaG_checkcode (const Proto *pt); |
20 | 41 | ||
21 | 42 | ||
22 | #endif | 43 | #endif |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.c,v 1.42 2001/02/23 17:17:25 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 1.43 2001/03/26 14:31:49 roberto Exp roberto $ |
3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -30,10 +30,8 @@ Closure *luaF_newclosure (lua_State *L, int nelems) { | |||
30 | 30 | ||
31 | Proto *luaF_newproto (lua_State *L) { | 31 | Proto *luaF_newproto (lua_State *L) { |
32 | Proto *f = luaM_new(L, Proto); | 32 | Proto *f = luaM_new(L, Proto); |
33 | f->knum = NULL; | 33 | f->k = NULL; |
34 | f->sizeknum = 0; | 34 | f->sizek = 0; |
35 | f->kstr = NULL; | ||
36 | f->sizekstr = 0; | ||
37 | f->kproto = NULL; | 35 | f->kproto = NULL; |
38 | f->sizekproto = 0; | 36 | f->sizekproto = 0; |
39 | f->code = NULL; | 37 | f->code = NULL; |
@@ -58,8 +56,7 @@ Proto *luaF_newproto (lua_State *L) { | |||
58 | void luaF_freeproto (lua_State *L, Proto *f) { | 56 | void luaF_freeproto (lua_State *L, Proto *f) { |
59 | luaM_freearray(L, f->code, f->sizecode, Instruction); | 57 | luaM_freearray(L, f->code, f->sizecode, Instruction); |
60 | luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); | 58 | luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); |
61 | luaM_freearray(L, f->kstr, f->sizekstr, TString *); | 59 | luaM_freearray(L, f->k, f->sizek, TObject); |
62 | luaM_freearray(L, f->knum, f->sizeknum, lua_Number); | ||
63 | luaM_freearray(L, f->kproto, f->sizekproto, Proto *); | 60 | luaM_freearray(L, f->kproto, f->sizekproto, Proto *); |
64 | luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); | 61 | luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); |
65 | luaM_freelem(L, f, Proto); | 62 | luaM_freelem(L, f, Proto); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.96 2001/04/11 14:42:41 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.97 2001/04/17 17:35:54 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -48,8 +48,10 @@ static void protomark (Proto *f) { | |||
48 | int i; | 48 | int i; |
49 | f->marked = 1; | 49 | f->marked = 1; |
50 | strmark(f->source); | 50 | strmark(f->source); |
51 | for (i=0; i<f->sizekstr; i++) | 51 | for (i=0; i<f->sizek; i++) { |
52 | strmark(f->kstr[i]); | 52 | if (ttype(f->k+i) == LUA_TSTRING) |
53 | strmark(tsvalue(f->k+i)); | ||
54 | } | ||
53 | for (i=0; i<f->sizekproto; i++) | 55 | for (i=0; i<f->sizekproto; i++) |
54 | protomark(f->kproto[i]); | 56 | protomark(f->kproto[i]); |
55 | for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */ | 57 | for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llimits.h,v 1.27 2001/02/23 20:28:56 roberto Exp roberto $ | 2 | ** $Id: llimits.h,v 1.28 2001/03/26 14:31:49 roberto Exp roberto $ |
3 | ** Limits, basic types, and some other `installation-dependent' definitions | 3 | ** Limits, basic types, and some other `installation-dependent' definitions |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -89,92 +89,23 @@ union L_Umaxalign { double d; void *s; long l; }; | |||
89 | /* | 89 | /* |
90 | ** type for virtual-machine instructions | 90 | ** type for virtual-machine instructions |
91 | ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) | 91 | ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) |
92 | ** For a very small machine, you may change that to 2 bytes (and adjust | ||
93 | ** the following limits accordingly) | ||
94 | */ | 92 | */ |
95 | typedef unsigned long Instruction; | 93 | typedef unsigned long Instruction; |
96 | 94 | ||
97 | 95 | ||
98 | /* | 96 | /* maximum stack for a Lua function */ |
99 | ** size and position of opcode arguments. | ||
100 | ** For an instruction with 2 bytes, size is 16, and size_b can be 5 | ||
101 | ** (accordingly, size_u will be 10, and size_a will be 5) | ||
102 | */ | ||
103 | #define SIZE_INSTRUCTION 32 | ||
104 | #define SIZE_B 8 | ||
105 | |||
106 | #define SIZE_OP 6 | ||
107 | #define SIZE_U (SIZE_INSTRUCTION-SIZE_OP) | ||
108 | #define POS_U SIZE_OP | ||
109 | #define POS_B SIZE_OP | ||
110 | #define SIZE_A (SIZE_INSTRUCTION-(SIZE_OP+SIZE_B)) | ||
111 | #define POS_A (SIZE_OP+SIZE_B) | ||
112 | |||
113 | |||
114 | /* | ||
115 | ** limits for opcode arguments. | ||
116 | ** we use (signed) int to manipulate most arguments, | ||
117 | ** so they must fit in BITS_INT-1 bits (-1 for sign) | ||
118 | */ | ||
119 | #if SIZE_U < BITS_INT-1 | ||
120 | #define MAXARG_U ((1<<SIZE_U)-1) | ||
121 | #define MAXARG_S (MAXARG_U>>1) /* `S' is signed */ | ||
122 | #else | ||
123 | #define MAXARG_U MAX_INT | ||
124 | #define MAXARG_S MAX_INT | ||
125 | #endif | ||
126 | |||
127 | #if SIZE_A < BITS_INT-1 | ||
128 | #define MAXARG_A ((1<<SIZE_A)-1) | ||
129 | #else | ||
130 | #define MAXARG_A MAX_INT | ||
131 | #endif | ||
132 | |||
133 | #if SIZE_B < BITS_INT-1 | ||
134 | #define MAXARG_B ((1<<SIZE_B)-1) | ||
135 | #else | ||
136 | #define MAXARG_B MAX_INT | ||
137 | #endif | ||
138 | |||
139 | |||
140 | /* maximum stack size in a function */ | ||
141 | #ifndef MAXSTACK | ||
142 | #define MAXSTACK 250 | 97 | #define MAXSTACK 250 |
143 | #endif | ||
144 | |||
145 | #if MAXSTACK > MAXARG_B | ||
146 | #undef MAXSTACK | ||
147 | #define MAXSTACK MAXARG_B | ||
148 | #endif | ||
149 | 98 | ||
150 | 99 | ||
151 | /* maximum number of local variables */ | 100 | /* maximum number of local variables */ |
152 | #ifndef MAXLOCALS | 101 | #ifndef MAXLOCALS |
153 | #define MAXLOCALS 200 /* arbitrary limit (<MAXSTACK) */ | 102 | #define MAXLOCALS 200 /* arbitrary limit (<MAXSTACK) */ |
154 | #endif | 103 | #endif |
155 | #if MAXLOCALS>=MAXSTACK | ||
156 | #undef MAXLOCALS | ||
157 | #define MAXLOCALS (MAXSTACK-1) | ||
158 | #endif | ||
159 | 104 | ||
160 | 105 | ||
161 | /* maximum number of upvalues */ | 106 | /* maximum number of upvalues */ |
162 | #ifndef MAXUPVALUES | 107 | #ifndef MAXUPVALUES |
163 | #define MAXUPVALUES 32 /* arbitrary limit (<=MAXARG_B) */ | 108 | #define MAXUPVALUES 32 /* arbitrary limit (<MAXSTACK) */ |
164 | #endif | ||
165 | #if MAXUPVALUES>MAXARG_B | ||
166 | #undef MAXUPVALUES | ||
167 | #define MAXUPVALUES MAXARG_B | ||
168 | #endif | ||
169 | |||
170 | |||
171 | /* maximum number of variables in the left side of an assignment */ | ||
172 | #ifndef MAXVARSLH | ||
173 | #define MAXVARSLH 100 /* arbitrary limit (<MULT_RET) */ | ||
174 | #endif | ||
175 | #if MAXVARSLH>=MULT_RET | ||
176 | #undef MAXVARSLH | ||
177 | #define MAXVARSLH (MULT_RET-1) | ||
178 | #endif | 109 | #endif |
179 | 110 | ||
180 | 111 | ||
@@ -182,27 +113,17 @@ typedef unsigned long Instruction; | |||
182 | #ifndef MAXPARAMS | 113 | #ifndef MAXPARAMS |
183 | #define MAXPARAMS 100 /* arbitrary limit (<MAXLOCALS) */ | 114 | #define MAXPARAMS 100 /* arbitrary limit (<MAXLOCALS) */ |
184 | #endif | 115 | #endif |
185 | #if MAXPARAMS>=MAXLOCALS | ||
186 | #undef MAXPARAMS | ||
187 | #define MAXPARAMS (MAXLOCALS-1) | ||
188 | #endif | ||
189 | 116 | ||
190 | 117 | ||
191 | /* number of list items to accumulate before a SETLIST instruction */ | 118 | /* number of list items to accumulate before a SETLIST instruction */ |
119 | /* (must be a power of 2) */ | ||
192 | #define LFIELDS_PER_FLUSH 64 | 120 | #define LFIELDS_PER_FLUSH 64 |
193 | #if LFIELDS_PER_FLUSH>(MAXSTACK/4) | ||
194 | #undef LFIELDS_PER_FLUSH | ||
195 | #define LFIELDS_PER_FLUSH (MAXSTACK/4) | ||
196 | #endif | ||
197 | 121 | ||
198 | /* number of record items to accumulate before a SETMAP instruction */ | ||
199 | /* (each item counts 2 elements on the stack: an index and a value) */ | ||
200 | #define RFIELDS_PER_FLUSH (LFIELDS_PER_FLUSH/2) | ||
201 | 122 | ||
202 | 123 | ||
203 | /* maximum lookback to find a real constant (for code generation) */ | 124 | /* maximum lookback to find a real constant (for code generation) */ |
204 | #ifndef LOOKBACKNUMS | 125 | #ifndef LOOKBACKNUMS |
205 | #define LOOKBACKNUMS 20 /* arbitrary constant */ | 126 | #define LOOKBACKNUMS 40 /* arbitrary constant */ |
206 | #endif | 127 | #endif |
207 | 128 | ||
208 | 129 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.h,v 1.101 2001/03/07 18:09:25 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 1.102 2001/04/11 14:42:41 roberto Exp roberto $ |
3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -114,10 +114,8 @@ union L_UTString { | |||
114 | ** Function Prototypes | 114 | ** Function Prototypes |
115 | */ | 115 | */ |
116 | typedef struct Proto { | 116 | typedef struct Proto { |
117 | lua_Number *knum; /* numbers used by the function */ | 117 | TObject *k; /* constants used by the function */ |
118 | int sizeknum; /* size of `knum' */ | 118 | int sizek; /* size of `k' */ |
119 | struct TString **kstr; /* strings used by the function */ | ||
120 | int sizekstr; /* size of `kstr' */ | ||
121 | struct Proto **kproto; /* functions defined inside the function */ | 119 | struct Proto **kproto; /* functions defined inside the function */ |
122 | int sizekproto; /* size of `kproto' */ | 120 | int sizekproto; /* size of `kproto' */ |
123 | Instruction *code; | 121 | Instruction *code; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.71 2001/03/07 13:22:55 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.72 2001/04/06 18:25:00 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -12,29 +12,55 @@ | |||
12 | 12 | ||
13 | /*=========================================================================== | 13 | /*=========================================================================== |
14 | We assume that instructions are unsigned numbers. | 14 | We assume that instructions are unsigned numbers. |
15 | All instructions have an opcode in the first 6 bits. Moreover, | 15 | All instructions have an opcode in the first 6 bits. |
16 | an instruction can have 0, 1, or 2 arguments. Instructions can | 16 | Instructions can have the following fields: |
17 | have the following types: | 17 | `A' : 8 bits (25-32) |
18 | type 0: no arguments | 18 | `B' : 8 bits (17-24) |
19 | type 1: 1 unsigned argument in the higher bits (called `U') | 19 | `C' : 10 bits (7-16) |
20 | type 2: 1 signed argument in the higher bits (`S') | 20 | `Bc' : 18 bits (`B' and `C' together) |
21 | type 3: 1st unsigned argument in the higher bits (`A') | 21 | `sBc' : signed Bc |
22 | 2nd unsigned argument in the middle bits (`B') | ||
23 | 22 | ||
24 | A signed argument is represented in excess K; that is, the number | 23 | A signed argument is represented in excess K; that is, the number |
25 | value is the unsigned value minus K. K is exactly the maximum value | 24 | value is the unsigned value minus K. K is exactly the maximum value |
26 | for that argument (so that -max is represented by 0, and +max is | 25 | for that argument (so that -max is represented by 0, and +max is |
27 | represented by 2*max), which is half the maximum for the corresponding | 26 | represented by 2*max), which is half the maximum for the corresponding |
28 | unsigned argument. | 27 | unsigned argument. |
29 | |||
30 | The size of each argument is defined in `llimits.h'. The usual is an | ||
31 | instruction with 32 bits, U arguments with 26 bits (32-6), B arguments | ||
32 | with 9 bits, and A arguments with 17 bits (32-6-9). For small | ||
33 | installations, the instruction size can be 16, so U has 10 bits, | ||
34 | and A and B have 5 bits each. | ||
35 | ===========================================================================*/ | 28 | ===========================================================================*/ |
36 | 29 | ||
37 | 30 | ||
31 | /* | ||
32 | ** size and position of opcode arguments. | ||
33 | */ | ||
34 | #define SIZE_C 10 | ||
35 | #define SIZE_B 8 | ||
36 | #define SIZE_Bc (SIZE_C + SIZE_B) | ||
37 | #define SIZE_A 8 | ||
38 | |||
39 | #define SIZE_OP 6 | ||
40 | |||
41 | #define POS_C SIZE_OP | ||
42 | #define POS_B (POS_C + SIZE_C) | ||
43 | #define POS_Bc POS_C | ||
44 | #define POS_A (POS_B + SIZE_B) | ||
45 | |||
46 | |||
47 | /* | ||
48 | ** limits for opcode arguments. | ||
49 | ** we use (signed) int to manipulate most arguments, | ||
50 | ** so they must fit in BITS_INT-1 bits (-1 for sign) | ||
51 | */ | ||
52 | #if SIZE_Bc < BITS_INT-1 | ||
53 | #define MAXARG_Bc ((1<<SIZE_Bc)-1) | ||
54 | #define MAXARG_sBc (MAXARG_Bc>>1) /* `sBc' is signed */ | ||
55 | #else | ||
56 | #define MAXARG_Bc MAX_INT | ||
57 | #define MAXARG_sBc MAX_INT | ||
58 | #endif | ||
59 | |||
60 | |||
61 | #define MAXARG_A ((1<<SIZE_A)-1) | ||
62 | #define MAXARG_B ((1<<SIZE_B)-1) | ||
63 | #define MAXARG_C ((1<<SIZE_C)-1) | ||
38 | 64 | ||
39 | 65 | ||
40 | /* creates a mask with `n' 1 bits at position `p' */ | 66 | /* creates a mask with `n' 1 bits at position `p' */ |
@@ -47,120 +73,129 @@ | |||
47 | ** the following macros help to manipulate instructions | 73 | ** the following macros help to manipulate instructions |
48 | */ | 74 | */ |
49 | 75 | ||
50 | #define CREATE_0(o) ((Instruction)(o)) | ||
51 | #define GET_OPCODE(i) ((OpCode)((i)&MASK1(SIZE_OP,0))) | 76 | #define GET_OPCODE(i) ((OpCode)((i)&MASK1(SIZE_OP,0))) |
52 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,0)) | (Instruction)(o))) | 77 | #define SET_OPCODE(i,o) (((i)&MASK0(SIZE_OP,0)) | (Instruction)(o)) |
53 | |||
54 | #define CREATE_U(o,u) ((Instruction)(o) | ((Instruction)(u)<<POS_U)) | ||
55 | #define GETARG_U(i) ((int)((i)>>POS_U)) | ||
56 | #define SETARG_U(i,u) ((i) = (((i)&MASK0(SIZE_U,POS_U)) | \ | ||
57 | ((Instruction)(u)<<POS_U))) | ||
58 | 78 | ||
59 | #define CREATE_S(o,s) CREATE_U((o),(s)+MAXARG_S) | ||
60 | #define GETARG_S(i) (GETARG_U(i)-MAXARG_S) | ||
61 | #define SETARG_S(i,s) SETARG_U((i),(s)+MAXARG_S) | ||
62 | |||
63 | |||
64 | #define CREATE_AB(o,a,b) ((Instruction)(o) | ((Instruction)(a)<<POS_A) \ | ||
65 | | ((Instruction)(b)<<POS_B)) | ||
66 | #define GETARG_A(i) ((int)((i)>>POS_A)) | 79 | #define GETARG_A(i) ((int)((i)>>POS_A)) |
67 | #define SETARG_A(i,a) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ | 80 | #define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ |
68 | ((Instruction)(a)<<POS_A))) | 81 | ((Instruction)(u)<<POS_A))) |
82 | |||
69 | #define GETARG_B(i) ((int)(((i)>>POS_B) & MASK1(SIZE_B,0))) | 83 | #define GETARG_B(i) ((int)(((i)>>POS_B) & MASK1(SIZE_B,0))) |
70 | #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ | 84 | #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ |
71 | ((Instruction)(b)<<POS_B))) | 85 | ((Instruction)(b)<<POS_B))) |
72 | 86 | ||
87 | #define GETARG_C(i) ((int)(((i)>>POS_C) & MASK1(SIZE_C,0))) | ||
88 | #define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ | ||
89 | ((Instruction)(b)<<POS_C))) | ||
90 | |||
91 | #define GETARG_Bc(i) ((int)(((i)>>POS_Bc) & MASK1(SIZE_Bc,0))) | ||
92 | #define SETARG_Bc(i,b) ((i) = (((i)&MASK0(SIZE_Bc,POS_Bc)) | \ | ||
93 | ((Instruction)(b)<<POS_Bc))) | ||
94 | |||
95 | #define GETARG_sBc(i) (GETARG_Bc(i)-MAXARG_sBc) | ||
96 | #define SETARG_sBc(i,b) SETARG_Bc((i),(b)+MAXARG_sBc) | ||
97 | |||
98 | |||
99 | #define CREATE_ABC(o,a,b,c) ((Instruction)(o) \ | ||
100 | | ((Instruction)(a)<<POS_A) \ | ||
101 | | ((Instruction)(b)<<POS_B) \ | ||
102 | | ((Instruction)(c)<<POS_C)) | ||
103 | |||
104 | #define CREATE_ABc(o,a,bc) ((Instruction)(o) \ | ||
105 | | ((Instruction)(a)<<POS_A) \ | ||
106 | | ((Instruction)(bc)<<POS_Bc)) | ||
107 | |||
108 | |||
109 | |||
73 | 110 | ||
74 | /* | 111 | /* |
75 | ** K = U argument used as index to `kstr' | 112 | ** an invalid register that fits in 8 bits |
76 | ** J = S argument used as jump offset (relative to pc of next instruction) | 113 | */ |
77 | ** L = unsigned argument used as index of local variable | 114 | #define NO_REG MAXARG_A |
78 | ** N = U argument used as index to `knum' | 115 | |
116 | |||
117 | /* | ||
118 | ** R(x) - register | ||
119 | ** Kst(x) - constant (in constant table) | ||
120 | ** R/K(x) == if x < MAXSTACK then R(x) else Kst(x-MAXSTACK) | ||
79 | */ | 121 | */ |
80 | 122 | ||
81 | typedef enum { | 123 | typedef enum { |
82 | /*---------------------------------------------------------------------- | 124 | /*---------------------------------------------------------------------- |
83 | name args stack before stack after side effects | 125 | name args description |
84 | ------------------------------------------------------------------------*/ | 126 | ------------------------------------------------------------------------*/ |
85 | OP_RETURN,/* U v_n-v_x(at u) (return) returns v_x-v_n */ | 127 | OP_MOVE,/* A B R(A) := R(B) */ |
86 | 128 | OP_LOADK,/* A Bc R(A) := Kst(Bc) */ | |
87 | OP_CALL,/* A B v_n-v_1 f(at a) r_b-r_1 f(v1,...,v_n) */ | 129 | OP_LOADINT,/* A sBc R(A) := (Number)sBc */ |
88 | 130 | OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ | |
89 | OP_PUSHNIL,/* U - nil_1-nil_u */ | 131 | OP_LOADUPVAL,/* A Bc R(A) := UpValue[Bc] */ |
90 | OP_POP,/* U a_u-a_1 - */ | ||
91 | 132 | ||
92 | OP_PUSHINT,/* S - (lua_Number)s */ | 133 | OP_GETGLOBAL,/* A Bc R(A) := Gbl[Kst(Bc)] */ |
93 | OP_PUSHSTRING,/* K - KSTR[k] */ | 134 | OP_GETTABLE,/* A B C R(A) := R(B)[R/K(C)] */ |
94 | OP_PUSHNUM,/* N - KNUM[n] */ | ||
95 | OP_PUSHNEGNUM,/* N - -KNUM[n] */ | ||
96 | 135 | ||
97 | OP_PUSHUPVALUE,/* U - Closure[u] */ | 136 | OP_SETGLOBAL,/* A Bc Gbl[Kst(Bc)] := R(A) */ |
137 | OP_SETTABLE,/* A B C R(B)[R/K(C)] := R(A) */ | ||
98 | 138 | ||
99 | OP_GETLOCAL,/* L - LOC[l] */ | 139 | OP_NEWTABLE,/* A Bc R(A) := {} (size = Bc) */ |
100 | OP_GETGLOBAL,/* K - VAR[KSTR[k]] */ | ||
101 | 140 | ||
102 | OP_GETTABLE,/* - i t t[i] */ | 141 | OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[R/K(C)] */ |
103 | OP_GETDOTTED,/* K t t[KSTR[k]] */ | ||
104 | OP_GETINDEXED,/* L t t[LOC[l]] */ | ||
105 | OP_PUSHSELF,/* K t t t[KSTR[k]] */ | ||
106 | 142 | ||
107 | OP_CREATETABLE,/* U - newarray(size = u) */ | 143 | OP_ADD,/* A B C R(A) := R(B) + R/K(C) */ |
144 | OP_SUB,/* A B C R(A) := R(B) - R/K(C) */ | ||
145 | OP_MUL,/* A B C R(A) := R(B) * R/K(C) */ | ||
146 | OP_DIV,/* A B C R(A) := R(B) / R/K(C) */ | ||
147 | OP_POW,/* A B C R(A) := R(B) ^ R/K(C) */ | ||
148 | OP_UNM,/* A B R(A) := -R(B) */ | ||
149 | OP_NOT,/* A B R(A) := not R(B) */ | ||
108 | 150 | ||
109 | OP_SETLOCAL,/* L x - LOC[l]=x */ | 151 | OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ |
110 | OP_SETGLOBAL,/* K x - VAR[KSTR[k]]=x */ | ||
111 | OP_SETTABLE,/* A B v a_a-a_1 i t (pops b values) t[i]=v */ | ||
112 | 152 | ||
113 | OP_SETLIST,/* A B v_n-v_1 v_b v_b v_b[i+a*FPF]=v_i */ | 153 | OP_JMP,/* sBc PC += sBc */ |
114 | OP_SETMAP,/* U v_n k_n - v_1 k_1 v_u v_u v_u[k_i]=v_i */ | 154 | OP_CJMP,/* sBc if test then PC += sBc (see (1)) */ |
115 | 155 | ||
116 | OP_ADD,/* - y x x+y */ | 156 | OP_TESTEQ,/* B C test := (R(B) == R/K(C)) */ |
117 | OP_ADDI,/* S x x+s */ | 157 | OP_TESTNE,/* B C test := (R(B) ~= R/K(C)) */ |
118 | OP_SUB,/* - y x x-y */ | 158 | OP_TESTLT,/* B C test := (R(B) < R/K(C)) */ |
119 | OP_MULT,/* - y x x*y */ | 159 | OP_TESTLE,/* B C test := (R(B) <= R/K(C)) */ |
120 | OP_DIV,/* - y x x/y */ | 160 | OP_TESTGT,/* B C test := (R(B) > R/K(C)) */ |
121 | OP_POW,/* - y x x^y */ | 161 | OP_TESTGE,/* B C test := (R(B) >= R/K(C)) */ |
122 | OP_CONCAT,/* U v_u-v_1 v1..-..v_u */ | ||
123 | OP_MINUS,/* - x -x */ | ||
124 | OP_NOT,/* - x (x==nil)? 1 : nil */ | ||
125 | 162 | ||
126 | OP_JMPNE,/* J y x - (x~=y)? PC+=s */ | 163 | OP_TESTT,/* A B test := R(B); if (test) R(A) := R(B) */ |
127 | OP_JMPEQ,/* J y x - (x==y)? PC+=s */ | 164 | OP_TESTF,/* A B test := not R(B); if (test) R(A) := nil */ |
128 | OP_JMPLT,/* J y x - (x<y)? PC+=s */ | ||
129 | OP_JMPLE,/* J y x - (x<y)? PC+=s */ | ||
130 | OP_JMPGT,/* J y x - (x>y)? PC+=s */ | ||
131 | OP_JMPGE,/* J y x - (x>=y)? PC+=s */ | ||
132 | 165 | ||
133 | OP_JMPT,/* J x - (x~=nil)? PC+=s */ | 166 | OP_NILJMP,/* A R(A) := nil; PC++; */ |
134 | OP_JMPF,/* J x - (x==nil)? PC+=s */ | ||
135 | OP_JMPONT,/* J x (x~=nil)? x : - (x~=nil)? PC+=s */ | ||
136 | OP_JMPONF,/* J x (x==nil)? x : - (x==nil)? PC+=s */ | ||
137 | OP_JMP,/* J - - PC+=s */ | ||
138 | 167 | ||
139 | OP_PUSHNILJMP,/* - - nil PC++; */ | 168 | OP_CALL,/* A B C R(A), ... ,R(A+C-1) := R(A)(R(A+1), ... ,R(B-1))*/ |
169 | OP_RETURN,/* A B return R(A), ... ,R(B-1) (see (3)) */ | ||
140 | 170 | ||
141 | OP_FORPREP,/* J */ | 171 | OP_FORPREP,/* A sBc */ |
142 | OP_FORLOOP,/* J */ | 172 | OP_FORLOOP,/* A sBc */ |
143 | 173 | ||
144 | OP_LFORPREP,/* J */ | 174 | OP_TFORPREP,/* A sBc */ |
145 | OP_LFORLOOP,/* J */ | 175 | OP_TFORLOOP,/* A sBc */ |
146 | 176 | ||
147 | OP_CLOSURE/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ | 177 | OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */ |
178 | OP_SETLISTO,/* A Bc */ | ||
148 | 179 | ||
180 | OP_CLOSURE /* A Bc R(A) := closure(KPROTO[Bc], R(A), ... ,R(A+n)) */ | ||
149 | } OpCode; | 181 | } OpCode; |
150 | 182 | ||
183 | |||
151 | #define NUM_OPCODES ((int)OP_CLOSURE+1) | 184 | #define NUM_OPCODES ((int)OP_CLOSURE+1) |
152 | 185 | ||
153 | 186 | ||
154 | #define ISJUMP(o) (OP_JMPNE <= (o) && (o) <= OP_JMP) | ||
155 | 187 | ||
188 | /*=========================================================================== | ||
189 | Notes: | ||
190 | (1) In the current implementation there is no `test' variable; | ||
191 | instructions OP_TEST* and OP_CJMP must always occur together. | ||
156 | 192 | ||
193 | (2) In OP_CALL, if (B == NO_REG) then B = top. C is the number of returns, | ||
194 | and can be NO_REG. OP_CALL always set "top" to last_result+1, so | ||
195 | next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use "top". | ||
157 | 196 | ||
158 | /* special code to fit a LUA_MULTRET inside an argB */ | 197 | (3) In OP_RETURN, if (B == NO_REG) then B = top. |
159 | #define MULT_RET 255 /* (<=MAXARG_B) */ | 198 | ===========================================================================*/ |
160 | #if MULT_RET>MAXARG_B | ||
161 | #undef MULT_RET | ||
162 | #define MULT_RET MAXARG_B | ||
163 | #endif | ||
164 | 199 | ||
165 | 200 | ||
166 | #endif | 201 | #endif |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.141 2001/04/05 16:49:14 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.142 2001/04/06 18:25:00 roberto Exp roberto $ |
3 | ** LL(1) Parser and code generator for Lua | 3 | ** LL(1) Parser and code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -35,10 +35,12 @@ typedef struct Constdesc { | |||
35 | } Constdesc; | 35 | } Constdesc; |
36 | 36 | ||
37 | 37 | ||
38 | /* | ||
39 | ** nodes for break list (list of active breakable loops) | ||
40 | */ | ||
38 | typedef struct Breaklabel { | 41 | typedef struct Breaklabel { |
39 | struct Breaklabel *previous; /* chain */ | 42 | struct Breaklabel *previous; /* chain */ |
40 | int breaklist; | 43 | int breaklist; /* list of jumps out of this loop */ |
41 | int stacklevel; | ||
42 | } Breaklabel; | 44 | } Breaklabel; |
43 | 45 | ||
44 | 46 | ||
@@ -47,11 +49,10 @@ typedef struct Breaklabel { | |||
47 | /* | 49 | /* |
48 | ** prototypes for recursive non-terminal functions | 50 | ** prototypes for recursive non-terminal functions |
49 | */ | 51 | */ |
50 | static void body (LexState *ls, int needself, int line); | 52 | static void body (LexState *ls, expdesc *v, int needself, int line); |
51 | static void chunk (LexState *ls); | 53 | static void chunk (LexState *ls); |
52 | static void constructor (LexState *ls); | 54 | static void constructor (LexState *ls, expdesc *v); |
53 | static void expr (LexState *ls, expdesc *v); | 55 | static void expr (LexState *ls, expdesc *v); |
54 | static void exp1 (LexState *ls); | ||
55 | 56 | ||
56 | 57 | ||
57 | 58 | ||
@@ -119,25 +120,6 @@ static void check_match (LexState *ls, int what, int who, int where) { | |||
119 | } | 120 | } |
120 | 121 | ||
121 | 122 | ||
122 | static int string_constant (FuncState *fs, TString *s) { | ||
123 | Proto *f = fs->f; | ||
124 | int c = s->u.s.constindex; | ||
125 | if (c >= fs->nkstr || f->kstr[c] != s) { | ||
126 | luaM_growvector(fs->L, f->kstr, fs->nkstr, f->sizekstr, TString *, | ||
127 | MAXARG_U, l_s("constant table overflow")); | ||
128 | c = fs->nkstr++; | ||
129 | f->kstr[c] = s; | ||
130 | s->u.s.constindex = c; /* hint for next time */ | ||
131 | } | ||
132 | return c; | ||
133 | } | ||
134 | |||
135 | |||
136 | static void code_string (LexState *ls, TString *s) { | ||
137 | luaK_kstr(ls, string_constant(ls->fs, s)); | ||
138 | } | ||
139 | |||
140 | |||
141 | static TString *str_checkname (LexState *ls) { | 123 | static TString *str_checkname (LexState *ls) { |
142 | TString *ts; | 124 | TString *ts; |
143 | check_condition(ls, (ls->t.token == TK_NAME), l_s("<name> expected")); | 125 | check_condition(ls, (ls->t.token == TK_NAME), l_s("<name> expected")); |
@@ -147,11 +129,21 @@ static TString *str_checkname (LexState *ls) { | |||
147 | } | 129 | } |
148 | 130 | ||
149 | 131 | ||
150 | static int checkname (LexState *ls) { | 132 | static void init_exp (expdesc *e, expkind k, int i) { |
151 | return string_constant(ls->fs, str_checkname(ls)); | 133 | e->f = e->t = NO_JUMP; |
134 | e->k = k; | ||
135 | e->u.i.info = i; | ||
136 | } | ||
137 | |||
138 | |||
139 | static void codestring (LexState *ls, expdesc *e, TString *s) { | ||
140 | init_exp(e, VK, luaK_stringk(ls->fs, s)); | ||
152 | } | 141 | } |
153 | 142 | ||
154 | 143 | ||
144 | #define checkname(ls,e) codestring(ls,e,str_checkname(ls)) | ||
145 | |||
146 | |||
155 | static int luaI_registerlocalvar (LexState *ls, TString *varname) { | 147 | static int luaI_registerlocalvar (LexState *ls, TString *varname) { |
156 | FuncState *fs = ls->fs; | 148 | FuncState *fs = ls->fs; |
157 | Proto *f = fs->f; | 149 | Proto *f = fs->f; |
@@ -195,14 +187,13 @@ static int search_local (LexState *ls, TString *n, expdesc *var) { | |||
195 | int i; | 187 | int i; |
196 | for (i=fs->nactloc-1; i >= 0; i--) { | 188 | for (i=fs->nactloc-1; i >= 0; i--) { |
197 | if (n == fs->f->locvars[fs->actloc[i]].varname) { | 189 | if (n == fs->f->locvars[fs->actloc[i]].varname) { |
198 | var->k = VLOCAL; | 190 | init_exp(var, VLOCAL, i); |
199 | var->u.index = i; | ||
200 | return level; | 191 | return level; |
201 | } | 192 | } |
202 | } | 193 | } |
203 | level++; /* `var' not found; check outer level */ | 194 | level++; /* `var' not found; check outer level */ |
204 | } | 195 | } |
205 | var->k = VGLOBAL; /* not found in any level; must be global */ | 196 | init_exp(var, VGLOBAL, 0); /* not found in any level; must be global */ |
206 | return -1; | 197 | return -1; |
207 | } | 198 | } |
208 | 199 | ||
@@ -213,7 +204,7 @@ static void singlevar (LexState *ls, TString *n, expdesc *var) { | |||
213 | luaX_syntaxerror(ls, l_s("cannot access a variable in outer function"), | 204 | luaX_syntaxerror(ls, l_s("cannot access a variable in outer function"), |
214 | getstr(n)); | 205 | getstr(n)); |
215 | else if (level == -1) /* global? */ | 206 | else if (level == -1) /* global? */ |
216 | var->u.index = string_constant(ls->fs, n); | 207 | var->u.i.info = luaK_stringk(ls->fs, n); |
217 | } | 208 | } |
218 | 209 | ||
219 | 210 | ||
@@ -221,7 +212,7 @@ static int indexupvalue (LexState *ls, expdesc *v) { | |||
221 | FuncState *fs = ls->fs; | 212 | FuncState *fs = ls->fs; |
222 | int i; | 213 | int i; |
223 | for (i=0; i<fs->f->nupvalues; i++) { | 214 | for (i=0; i<fs->f->nupvalues; i++) { |
224 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.index == v->u.index) | 215 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.i.info == v->u.i.info) |
225 | return i; | 216 | return i; |
226 | } | 217 | } |
227 | /* new one */ | 218 | /* new one */ |
@@ -231,37 +222,43 @@ static int indexupvalue (LexState *ls, expdesc *v) { | |||
231 | } | 222 | } |
232 | 223 | ||
233 | 224 | ||
234 | static void pushupvalue (LexState *ls, TString *n) { | 225 | static void codeupvalue (LexState *ls, expdesc *v, TString *n) { |
235 | FuncState *fs = ls->fs; | 226 | FuncState *fs = ls->fs; |
236 | expdesc v; | 227 | int level; |
237 | int level = search_local(ls, n, &v); | 228 | level = search_local(ls, n, v); |
238 | if (level == -1) { /* global? */ | 229 | if (level == -1) { /* global? */ |
239 | if (fs->prev == NULL) | 230 | if (fs->prev == NULL) |
240 | luaX_syntaxerror(ls, l_s("cannot access an upvalue at top level"), getstr(n)); | 231 | luaX_syntaxerror(ls, l_s("cannot access an upvalue at top level"), |
241 | v.u.index = string_constant(fs->prev, n); | 232 | getstr(n)); |
233 | v->u.i.info = luaK_stringk(fs->prev, n); | ||
242 | } | 234 | } |
243 | else if (level != 1) { | 235 | else if (level != 1) { |
244 | luaX_syntaxerror(ls, | 236 | luaX_syntaxerror(ls, |
245 | l_s("upvalue must be global or local to immediately outer function"), getstr(n)); | 237 | l_s("upvalue must be global or local to immediately outer function"), |
238 | getstr(n)); | ||
246 | } | 239 | } |
247 | luaK_code1(fs, OP_PUSHUPVALUE, indexupvalue(ls, &v)); | 240 | init_exp(v, VRELOCABLE, |
241 | luaK_codeABc(fs, OP_LOADUPVAL, 0, indexupvalue(ls, v))); | ||
248 | } | 242 | } |
249 | 243 | ||
250 | 244 | ||
251 | static void adjust_mult_assign (LexState *ls, int nvars, int nexps) { | 245 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { |
252 | FuncState *fs = ls->fs; | 246 | FuncState *fs = ls->fs; |
253 | int diff = nexps - nvars; | 247 | int extra = nvars - nexps; |
254 | if (nexps > 0 && luaK_lastisopen(fs)) { /* list ends in a function call */ | 248 | if (e->k == VCALL) { |
255 | diff--; /* do not count function call itself */ | 249 | extra++; /* includes call itself */ |
256 | if (diff <= 0) { /* more variables than values? */ | 250 | if (extra <= 0) extra = 0; |
257 | luaK_setcallreturns(fs, -diff); /* function call provide extra values */ | 251 | else luaK_reserveregs(fs, extra-1); |
258 | diff = 0; /* no more difference */ | 252 | luaK_setcallreturns(fs, e, extra); /* call provides the difference */ |
253 | } | ||
254 | else { | ||
255 | if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ | ||
256 | if (extra > 0) { | ||
257 | int reg = fs->freereg; | ||
258 | luaK_reserveregs(fs, extra); | ||
259 | luaK_nil(fs, reg, extra); | ||
259 | } | 260 | } |
260 | else /* more values than variables */ | ||
261 | luaK_setcallreturns(fs, 0); /* call should provide no value */ | ||
262 | } | 261 | } |
263 | /* push or pop eventual difference between list lengths */ | ||
264 | luaK_adjuststack(fs, diff); | ||
265 | } | 262 | } |
266 | 263 | ||
267 | 264 | ||
@@ -275,12 +272,11 @@ static void code_params (LexState *ls, int nparams, short dots) { | |||
275 | new_localvarstr(ls, l_s("arg"), 0); | 272 | new_localvarstr(ls, l_s("arg"), 0); |
276 | adjustlocalvars(ls, 1); | 273 | adjustlocalvars(ls, 1); |
277 | } | 274 | } |
278 | luaK_deltastack(fs, fs->nactloc); /* count parameters in the stack */ | 275 | luaK_reserveregs(fs, fs->nactloc); /* reserve register for parameters */ |
279 | } | 276 | } |
280 | 277 | ||
281 | 278 | ||
282 | static void enterbreak (FuncState *fs, Breaklabel *bl) { | 279 | static void enterbreak (FuncState *fs, Breaklabel *bl) { |
283 | bl->stacklevel = fs->stacklevel; | ||
284 | bl->breaklist = NO_JUMP; | 280 | bl->breaklist = NO_JUMP; |
285 | bl->previous = fs->bl; | 281 | bl->previous = fs->bl; |
286 | fs->bl = bl; | 282 | fs->bl = bl; |
@@ -289,21 +285,24 @@ static void enterbreak (FuncState *fs, Breaklabel *bl) { | |||
289 | 285 | ||
290 | static void leavebreak (FuncState *fs, Breaklabel *bl) { | 286 | static void leavebreak (FuncState *fs, Breaklabel *bl) { |
291 | fs->bl = bl->previous; | 287 | fs->bl = bl->previous; |
292 | lua_assert(bl->stacklevel == fs->stacklevel); | ||
293 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); | 288 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); |
294 | } | 289 | } |
295 | 290 | ||
296 | 291 | ||
297 | static void pushclosure (LexState *ls, FuncState *func) { | 292 | static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { |
298 | FuncState *fs = ls->fs; | 293 | FuncState *fs = ls->fs; |
299 | Proto *f = fs->f; | 294 | Proto *f = fs->f; |
300 | int i; | 295 | int i; |
296 | int reg = fs->freereg; | ||
301 | for (i=0; i<func->f->nupvalues; i++) | 297 | for (i=0; i<func->f->nupvalues; i++) |
302 | luaK_tostack(ls, &func->upvalues[i], 1); | 298 | luaK_exp2nextreg(fs, &func->upvalues[i]); |
303 | luaM_growvector(ls->L, f->kproto, fs->nkproto, f->sizekproto, Proto *, | 299 | luaM_growvector(ls->L, f->kproto, fs->nkproto, f->sizekproto, Proto *, |
304 | MAXARG_A, l_s("constant table overflow")); | 300 | MAXARG_Bc, l_s("constant table overflow")); |
305 | f->kproto[fs->nkproto++] = func->f; | 301 | f->kproto[fs->nkproto++] = func->f; |
306 | luaK_code2(fs, OP_CLOSURE, fs->nkproto-1, func->f->nupvalues); | 302 | fs->freereg = reg; /* CLOSURE will consume those values */ |
303 | init_exp(v, VNONRELOC, reg); | ||
304 | luaK_reserveregs(fs, 1); | ||
305 | luaK_codeABc(fs, OP_CLOSURE, v->u.i.info, fs->nkproto-1); | ||
307 | } | 306 | } |
308 | 307 | ||
309 | 308 | ||
@@ -317,10 +316,9 @@ static void open_func (LexState *ls, FuncState *fs) { | |||
317 | fs->pc = 0; | 316 | fs->pc = 0; |
318 | fs->lasttarget = 0; | 317 | fs->lasttarget = 0; |
319 | fs->jlt = NO_JUMP; | 318 | fs->jlt = NO_JUMP; |
320 | fs->stacklevel = 0; | 319 | fs->freereg = 0; |
321 | fs->nkstr = 0; | 320 | fs->nk = 0; |
322 | fs->nkproto = 0; | 321 | fs->nkproto = 0; |
323 | fs->nknum = 0; | ||
324 | fs->nlineinfo = 0; | 322 | fs->nlineinfo = 0; |
325 | fs->nlocvars = 0; | 323 | fs->nlocvars = 0; |
326 | fs->nactloc = 0; | 324 | fs->nactloc = 0; |
@@ -328,7 +326,7 @@ static void open_func (LexState *ls, FuncState *fs) { | |||
328 | fs->bl = NULL; | 326 | fs->bl = NULL; |
329 | f->code = NULL; | 327 | f->code = NULL; |
330 | f->source = ls->source; | 328 | f->source = ls->source; |
331 | f->maxstacksize = 0; | 329 | f->maxstacksize = 1; /* register 0 is always valid */ |
332 | f->numparams = 0; /* default for main chunk */ | 330 | f->numparams = 0; /* default for main chunk */ |
333 | f->is_vararg = 0; /* default for main chunk */ | 331 | f->is_vararg = 0; /* default for main chunk */ |
334 | } | 332 | } |
@@ -338,15 +336,13 @@ static void close_func (LexState *ls) { | |||
338 | lua_State *L = ls->L; | 336 | lua_State *L = ls->L; |
339 | FuncState *fs = ls->fs; | 337 | FuncState *fs = ls->fs; |
340 | Proto *f = fs->f; | 338 | Proto *f = fs->f; |
341 | luaK_code1(fs, OP_RETURN, ls->fs->nactloc); /* final return */ | 339 | luaK_codeABC(fs, OP_RETURN, 0, 0, 0); /* final return */ |
342 | luaK_getlabel(fs); /* close eventual list of pending jumps */ | 340 | luaK_getlabel(fs); /* close eventual list of pending jumps */ |
343 | removelocalvars(ls, fs->nactloc); | 341 | removelocalvars(ls, fs->nactloc); |
344 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); | 342 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); |
345 | f->sizecode = fs->pc; | 343 | f->sizecode = fs->pc; |
346 | luaM_reallocvector(L, f->kstr, f->sizekstr, fs->nkstr, TString *); | 344 | luaM_reallocvector(L, f->k, f->sizek, fs->nk, TObject); |
347 | f->sizekstr = fs->nkstr; | 345 | f->sizek = fs->nk; |
348 | luaM_reallocvector(L, f->knum, f->sizeknum, fs->nknum, lua_Number); | ||
349 | f->sizeknum = fs->nknum; | ||
350 | luaM_reallocvector(L, f->kproto, f->sizekproto, fs->nkproto, Proto *); | 346 | luaM_reallocvector(L, f->kproto, f->sizekproto, fs->nkproto, Proto *); |
351 | f->sizekproto = fs->nkproto; | 347 | f->sizekproto = fs->nkproto; |
352 | luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); | 348 | luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); |
@@ -354,9 +350,9 @@ static void close_func (LexState *ls) { | |||
354 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->nlineinfo+1, int); | 350 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->nlineinfo+1, int); |
355 | f->lineinfo[fs->nlineinfo++] = MAX_INT; /* end flag */ | 351 | f->lineinfo[fs->nlineinfo++] = MAX_INT; /* end flag */ |
356 | f->sizelineinfo = fs->nlineinfo; | 352 | f->sizelineinfo = fs->nlineinfo; |
357 | lua_assert(luaG_checkcode(L, f)); | 353 | lua_assert(luaG_checkcode(f)); |
358 | ls->fs = fs->prev; | ||
359 | lua_assert(fs->bl == NULL); | 354 | lua_assert(fs->bl == NULL); |
355 | ls->fs = fs->prev; | ||
360 | } | 356 | } |
361 | 357 | ||
362 | 358 | ||
@@ -367,7 +363,8 @@ Proto *luaY_parser (lua_State *L, ZIO *z) { | |||
367 | open_func(&lexstate, &funcstate); | 363 | open_func(&lexstate, &funcstate); |
368 | next(&lexstate); /* read first token */ | 364 | next(&lexstate); /* read first token */ |
369 | chunk(&lexstate); | 365 | chunk(&lexstate); |
370 | check_condition(&lexstate, (lexstate.t.token == TK_EOS), l_s("<eof> expected")); | 366 | check_condition(&lexstate, (lexstate.t.token == TK_EOS), |
367 | l_s("<eof> expected")); | ||
371 | close_func(&lexstate); | 368 | close_func(&lexstate); |
372 | lua_assert(funcstate.prev == NULL); | 369 | lua_assert(funcstate.prev == NULL); |
373 | lua_assert(funcstate.f->nupvalues == 0); | 370 | lua_assert(funcstate.f->nupvalues == 0); |
@@ -381,48 +378,64 @@ Proto *luaY_parser (lua_State *L, ZIO *z) { | |||
381 | /*============================================================*/ | 378 | /*============================================================*/ |
382 | 379 | ||
383 | 380 | ||
384 | static int explist1 (LexState *ls) { | 381 | static void luaY_field (LexState *ls, expdesc *v) { |
382 | /* field -> ['.' | ':'] NAME */ | ||
383 | FuncState *fs = ls->fs; | ||
384 | expdesc key; | ||
385 | luaK_exp2anyreg(fs, v); | ||
386 | next(ls); /* skip the dot or colon */ | ||
387 | checkname(ls, &key); | ||
388 | luaK_indexed(fs, v, &key); | ||
389 | } | ||
390 | |||
391 | |||
392 | static void luaY_index (LexState *ls, expdesc *v) { | ||
393 | /* index -> '[' expr ']' */ | ||
394 | next(ls); /* skip the '[' */ | ||
395 | expr(ls, v); | ||
396 | luaK_exp2val(ls->fs, v); | ||
397 | check(ls, l_c(']')); | ||
398 | } | ||
399 | |||
400 | |||
401 | static int explist1 (LexState *ls, expdesc *v) { | ||
385 | /* explist1 -> expr { `,' expr } */ | 402 | /* explist1 -> expr { `,' expr } */ |
386 | int n = 1; /* at least one expression */ | 403 | int n = 1; /* at least one expression */ |
387 | expdesc v; | 404 | expr(ls, v); |
388 | expr(ls, &v); | ||
389 | while (ls->t.token == l_c(',')) { | 405 | while (ls->t.token == l_c(',')) { |
390 | next(ls); /* skip comma */ | 406 | next(ls); /* skip comma */ |
391 | luaK_tostack(ls, &v, 1); /* gets only 1 value from previous expression */ | 407 | luaK_exp2nextreg(ls->fs, v); |
392 | expr(ls, &v); | 408 | expr(ls, v); |
393 | n++; | 409 | n++; |
394 | } | 410 | } |
395 | luaK_tostack(ls, &v, 0); /* keep open number of values of last expression */ | ||
396 | return n; | 411 | return n; |
397 | } | 412 | } |
398 | 413 | ||
399 | 414 | ||
400 | static void funcargs (LexState *ls, int slf) { | 415 | static void funcargs (LexState *ls, expdesc *f) { |
401 | FuncState *fs = ls->fs; | 416 | FuncState *fs = ls->fs; |
402 | int slevel = fs->stacklevel - slf - 1; /* where is func in the stack */ | 417 | expdesc args; |
418 | int base, top; | ||
403 | switch (ls->t.token) { | 419 | switch (ls->t.token) { |
404 | case l_c('('): { /* funcargs -> `(' [ explist1 ] `)' */ | 420 | case l_c('('): { /* funcargs -> `(' [ explist1 ] `)' */ |
405 | int line = ls->linenumber; | 421 | int line = ls->linenumber; |
406 | int nargs = 0; | ||
407 | next(ls); | 422 | next(ls); |
408 | if (ls->t.token != l_c(')')) /* arg list not empty? */ | 423 | if (ls->t.token == l_c(')')) /* arg list is empty? */ |
409 | nargs = explist1(ls); | 424 | args.k = VVOID; |
425 | else { | ||
426 | explist1(ls, &args); | ||
427 | luaK_setcallreturns(fs, &args, NO_REG); | ||
428 | } | ||
410 | check_match(ls, l_c(')'), l_c('('), line); | 429 | check_match(ls, l_c(')'), l_c('('), line); |
411 | #ifdef LUA_COMPAT_ARGRET | ||
412 | if (nargs > 0) /* arg list is not empty? */ | ||
413 | luaK_setcallreturns(fs, 1); /* last call returns only 1 value */ | ||
414 | #else | ||
415 | UNUSED(nargs); /* to avoid warnings */ | ||
416 | #endif | ||
417 | break; | 430 | break; |
418 | } | 431 | } |
419 | case l_c('{'): { /* funcargs -> constructor */ | 432 | case l_c('{'): { /* funcargs -> constructor */ |
420 | constructor(ls); | 433 | constructor(ls, &args); |
421 | break; | 434 | break; |
422 | } | 435 | } |
423 | case TK_STRING: { /* funcargs -> STRING */ | 436 | case TK_STRING: { /* funcargs -> STRING */ |
424 | code_string(ls, ls->t.seminfo.ts); /* must use `seminfo' before `next' */ | 437 | codestring(ls, &args, ls->t.seminfo.ts); |
425 | next(ls); | 438 | next(ls); /* must use `seminfo' before `next' */ |
426 | break; | 439 | break; |
427 | } | 440 | } |
428 | default: { | 441 | default: { |
@@ -430,11 +443,22 @@ static void funcargs (LexState *ls, int slf) { | |||
430 | break; | 443 | break; |
431 | } | 444 | } |
432 | } | 445 | } |
433 | fs->stacklevel = slevel; /* call will remove function and arguments */ | 446 | lua_assert(f->k == VNONRELOC); |
434 | luaK_code2(fs, OP_CALL, slevel, MULT_RET); | 447 | base = f->u.i.info; /* base register for call */ |
448 | if (args.k == VCALL) | ||
449 | top = NO_REG; /* open call */ | ||
450 | else { | ||
451 | if (args.k != VVOID) | ||
452 | luaK_exp2nextreg(fs, &args); /* close last argument */ | ||
453 | top = fs->freereg; | ||
454 | } | ||
455 | init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, top, 1)); | ||
456 | fs->freereg = base+1; /* call remove function and arguments and leaves | ||
457 | (unless changed) one result */ | ||
435 | } | 458 | } |
436 | 459 | ||
437 | 460 | ||
461 | |||
438 | /* | 462 | /* |
439 | ** {====================================================================== | 463 | ** {====================================================================== |
440 | ** Rules for Constructors | 464 | ** Rules for Constructors |
@@ -442,69 +466,82 @@ static void funcargs (LexState *ls, int slf) { | |||
442 | */ | 466 | */ |
443 | 467 | ||
444 | 468 | ||
445 | static void recfield (LexState *ls) { | 469 | static void recfield (LexState *ls, expdesc *t) { |
446 | /* recfield -> (NAME | `['exp1`]') = exp1 */ | 470 | /* recfield -> (NAME | `['exp1`]') = exp1 */ |
471 | FuncState *fs = ls->fs; | ||
472 | int reg = ls->fs->freereg; | ||
473 | expdesc key, val; | ||
447 | switch (ls->t.token) { | 474 | switch (ls->t.token) { |
448 | case TK_NAME: { | 475 | case TK_NAME: { |
449 | luaK_kstr(ls, checkname(ls)); | 476 | checkname(ls, &key); |
450 | break; | 477 | break; |
451 | } | 478 | } |
452 | case l_c('['): { | 479 | case l_c('['): { |
453 | next(ls); | 480 | luaY_index(ls, &key); |
454 | exp1(ls); | ||
455 | check(ls, l_c(']')); | ||
456 | break; | 481 | break; |
457 | } | 482 | } |
458 | default: luaK_error(ls, l_s("<name> or `[' expected")); | 483 | default: luaK_error(ls, l_s("<name> or `[' expected")); |
459 | } | 484 | } |
460 | check(ls, l_c('=')); | 485 | check(ls, l_c('=')); |
461 | exp1(ls); | 486 | luaK_exp2RK(fs, &key); |
487 | expr(ls, &val); | ||
488 | luaK_exp2anyreg(fs, &val); | ||
489 | luaK_codeABC(fs, OP_SETTABLE, val.u.i.info, t->u.i.info, | ||
490 | luaK_exp2RK(fs, &key)); | ||
491 | fs->freereg = reg; /* free registers */ | ||
462 | } | 492 | } |
463 | 493 | ||
464 | 494 | ||
465 | static int recfields (LexState *ls) { | 495 | static int recfields (LexState *ls, expdesc *t) { |
466 | /* recfields -> recfield { `,' recfield } [`,'] */ | 496 | /* recfields -> recfield { `,' recfield } [`,'] */ |
467 | FuncState *fs = ls->fs; | ||
468 | int t = fs->stacklevel-1; /* level of table on the stack */ | ||
469 | int n = 1; /* at least one element */ | 497 | int n = 1; /* at least one element */ |
470 | recfield(ls); | 498 | luaK_exp2nextreg(ls->fs, t); |
471 | while (ls->t.token == l_c(',') && | 499 | recfield(ls, t); |
472 | (next(ls), (ls->t.token != l_c(';') && ls->t.token != l_c('}')))) { | 500 | while (ls->t.token == l_c(',')) { |
473 | if (n%RFIELDS_PER_FLUSH == 0) | 501 | next(ls); |
474 | luaK_code1(fs, OP_SETMAP, t); | 502 | if (ls->t.token == l_c(';') || ls->t.token == l_c('}')) break; |
475 | recfield(ls); | 503 | recfield(ls, t); |
476 | n++; | 504 | n++; |
477 | } | 505 | } |
478 | luaK_code1(fs, OP_SETMAP, t); | ||
479 | return n; | 506 | return n; |
480 | } | 507 | } |
481 | 508 | ||
482 | 509 | ||
483 | static int listfields (LexState *ls) { | 510 | static int listfields (LexState *ls, expdesc *t) { |
484 | /* listfields -> exp1 { `,' exp1 } [`,'] */ | 511 | /* listfields -> exp1 { `,' exp1 } [`,'] */ |
485 | expdesc v; | 512 | expdesc v; |
486 | FuncState *fs = ls->fs; | 513 | FuncState *fs = ls->fs; |
487 | int t = fs->stacklevel-1; /* level of table on the stack */ | ||
488 | int n = 1; /* at least one element */ | 514 | int n = 1; /* at least one element */ |
515 | int reg; | ||
516 | luaK_exp2nextreg(ls->fs, t); | ||
517 | reg = fs->freereg; | ||
489 | expr(ls, &v); | 518 | expr(ls, &v); |
490 | while (ls->t.token == l_c(',') && | 519 | while (ls->t.token == l_c(',') && |
491 | (next(ls), (ls->t.token != l_c(';') && ls->t.token != l_c('}')))) { | 520 | (next(ls), (ls->t.token != l_c(';') && ls->t.token != l_c('}')))) { |
492 | luaK_tostack(ls, &v, 1); /* only one value from intermediate expressions */ | 521 | luaK_exp2nextreg(fs, &v); |
493 | luaX_checklimit(ls, n/LFIELDS_PER_FLUSH, MAXARG_A, | 522 | luaX_checklimit(ls, n, MAXARG_Bc, |
494 | l_s("`item groups' in a list initializer")); | 523 | l_s("`item groups' in a list initializer")); |
495 | if (n%LFIELDS_PER_FLUSH == 0) | 524 | if (n%LFIELDS_PER_FLUSH == 0) { |
496 | luaK_code2(fs, OP_SETLIST, (n-1)/LFIELDS_PER_FLUSH, t); | 525 | luaK_codeABc(fs, OP_SETLIST, t->u.i.info, n-1); |
526 | fs->freereg = reg; /* free registers */ | ||
527 | } | ||
497 | expr(ls, &v); | 528 | expr(ls, &v); |
498 | n++; | 529 | n++; |
499 | } | 530 | } |
500 | luaK_tostack(ls, &v, 0); /* allow multiple values for last expression */ | 531 | if (v.k == VCALL) { |
501 | luaK_code2(fs, OP_SETLIST, (n-1)/LFIELDS_PER_FLUSH, t); | 532 | luaK_setcallreturns(fs, &v, NO_REG); |
533 | luaK_codeABc(fs, OP_SETLISTO, t->u.i.info, n-1); | ||
534 | } | ||
535 | else { | ||
536 | luaK_exp2nextreg(fs, &v); | ||
537 | luaK_codeABc(fs, OP_SETLIST, t->u.i.info, n-1); | ||
538 | } | ||
539 | fs->freereg = reg; /* free registers */ | ||
502 | return n; | 540 | return n; |
503 | } | 541 | } |
504 | 542 | ||
505 | 543 | ||
506 | 544 | static void constructor_part (LexState *ls, expdesc *t, Constdesc *cd) { | |
507 | static void constructor_part (LexState *ls, Constdesc *cd) { | ||
508 | switch (ls->t.token) { | 545 | switch (ls->t.token) { |
509 | case l_c(';'): case l_c('}'): { /* constructor_part -> empty */ | 546 | case l_c(';'): case l_c('}'): { /* constructor_part -> empty */ |
510 | cd->n = 0; | 547 | cd->n = 0; |
@@ -518,13 +555,13 @@ static void constructor_part (LexState *ls, Constdesc *cd) { | |||
518 | /* else go through to recfields */ | 555 | /* else go through to recfields */ |
519 | } | 556 | } |
520 | case l_c('['): { /* constructor_part -> recfields */ | 557 | case l_c('['): { /* constructor_part -> recfields */ |
521 | cd->n = recfields(ls); | 558 | cd->n = recfields(ls, t); |
522 | cd->k = 1; /* record */ | 559 | cd->k = 1; /* record */ |
523 | break; | 560 | break; |
524 | } | 561 | } |
525 | default: { /* constructor_part -> listfields */ | 562 | default: { /* constructor_part -> listfields */ |
526 | case_default: | 563 | case_default: |
527 | cd->n = listfields(ls); | 564 | cd->n = listfields(ls, t); |
528 | cd->k = 0; /* list */ | 565 | cd->k = 0; /* list */ |
529 | break; | 566 | break; |
530 | } | 567 | } |
@@ -532,25 +569,27 @@ static void constructor_part (LexState *ls, Constdesc *cd) { | |||
532 | } | 569 | } |
533 | 570 | ||
534 | 571 | ||
535 | static void constructor (LexState *ls) { | 572 | static void constructor (LexState *ls, expdesc *t) { |
536 | /* constructor -> `{' constructor_part [`;' constructor_part] `}' */ | 573 | /* constructor -> `{' constructor_part [`;' constructor_part] `}' */ |
537 | FuncState *fs = ls->fs; | 574 | FuncState *fs = ls->fs; |
538 | int line = ls->linenumber; | 575 | int line = ls->linenumber; |
539 | int pc = luaK_code1(fs, OP_CREATETABLE, 0); | 576 | int n; |
540 | int nelems; | 577 | int pc; |
541 | Constdesc cd; | 578 | Constdesc cd; |
579 | pc = luaK_codeABc(fs, OP_NEWTABLE, 0, 0); | ||
580 | init_exp(t, VRELOCABLE, pc); | ||
542 | check(ls, l_c('{')); | 581 | check(ls, l_c('{')); |
543 | constructor_part(ls, &cd); | 582 | constructor_part(ls, t, &cd); |
544 | nelems = cd.n; | 583 | n = cd.n; |
545 | if (optional(ls, l_c(';'))) { | 584 | if (optional(ls, l_c(';'))) { |
546 | Constdesc other_cd; | 585 | Constdesc other_cd; |
547 | constructor_part(ls, &other_cd); | 586 | constructor_part(ls, t, &other_cd); |
548 | check_condition(ls, (cd.k != other_cd.k), l_s("invalid constructor syntax")); | 587 | check_condition(ls, (cd.k != other_cd.k), l_s("invalid constructor syntax")); |
549 | nelems += other_cd.n; | 588 | n += other_cd.n; |
550 | } | 589 | } |
551 | check_match(ls, l_c('}'), l_c('{'), line); | 590 | check_match(ls, l_c('}'), l_c('{'), line); |
552 | luaX_checklimit(ls, nelems, MAXARG_U, l_s("elements in a table constructor")); | 591 | luaX_checklimit(ls, n, MAXARG_Bc, l_s("elements in a table constructor")); |
553 | SETARG_U(fs->f->code[pc], nelems); /* set initial table size */ | 592 | SETARG_Bc(fs->f->code[pc], n); /* set initial table size */ |
554 | } | 593 | } |
555 | 594 | ||
556 | /* }====================================================================== */ | 595 | /* }====================================================================== */ |
@@ -565,31 +604,30 @@ static void constructor (LexState *ls) { | |||
565 | */ | 604 | */ |
566 | 605 | ||
567 | static void primaryexp (LexState *ls, expdesc *v) { | 606 | static void primaryexp (LexState *ls, expdesc *v) { |
568 | FuncState *fs = ls->fs; | ||
569 | switch (ls->t.token) { | 607 | switch (ls->t.token) { |
570 | case TK_NUMBER: { | 608 | case TK_NUMBER: { |
571 | lua_Number r = ls->t.seminfo.r; | 609 | init_exp(v, VNUMBER, 0); |
572 | next(ls); | 610 | v->u.n = ls->t.seminfo.r; |
573 | luaK_number(fs, r); | 611 | next(ls); /* must use `seminfo' before `next' */ |
574 | break; | 612 | break; |
575 | } | 613 | } |
576 | case TK_STRING: { | 614 | case TK_STRING: { |
577 | code_string(ls, ls->t.seminfo.ts); /* must use `seminfo' before `next' */ | 615 | codestring(ls, v, ls->t.seminfo.ts); |
578 | next(ls); | 616 | next(ls); /* must use `seminfo' before `next' */ |
579 | break; | 617 | break; |
580 | } | 618 | } |
581 | case TK_NIL: { | 619 | case TK_NIL: { |
582 | luaK_adjuststack(fs, -1); | 620 | init_exp(v, VNIL, 0); |
583 | next(ls); | 621 | next(ls); |
584 | break; | 622 | break; |
585 | } | 623 | } |
586 | case l_c('{'): { /* constructor */ | 624 | case l_c('{'): { /* constructor */ |
587 | constructor(ls); | 625 | constructor(ls, v); |
588 | break; | 626 | break; |
589 | } | 627 | } |
590 | case TK_FUNCTION: { | 628 | case TK_FUNCTION: { |
591 | next(ls); | 629 | next(ls); |
592 | body(ls, 0, ls->linenumber); | 630 | body(ls, v, 0, ls->linenumber); |
593 | break; | 631 | break; |
594 | } | 632 | } |
595 | case l_c('('): { | 633 | case l_c('('): { |
@@ -604,7 +642,7 @@ static void primaryexp (LexState *ls, expdesc *v) { | |||
604 | } | 642 | } |
605 | case l_c('%'): { | 643 | case l_c('%'): { |
606 | next(ls); /* skip `%' */ | 644 | next(ls); /* skip `%' */ |
607 | pushupvalue(ls, str_checkname(ls)); | 645 | codeupvalue(ls, v, str_checkname(ls)); |
608 | break; | 646 | break; |
609 | } | 647 | } |
610 | default: { | 648 | default: { |
@@ -612,46 +650,38 @@ static void primaryexp (LexState *ls, expdesc *v) { | |||
612 | return; | 650 | return; |
613 | } | 651 | } |
614 | } | 652 | } |
615 | v->k = VEXP; | ||
616 | v->u.l.t = v->u.l.f = NO_JUMP; | ||
617 | } | 653 | } |
618 | 654 | ||
619 | 655 | ||
620 | static void simpleexp (LexState *ls, expdesc *v) { | 656 | static void simpleexp (LexState *ls, expdesc *v) { |
621 | /* simpleexp -> | 657 | /* simpleexp -> |
622 | primaryexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ | 658 | primaryexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ |
659 | FuncState *fs = ls->fs; | ||
623 | primaryexp(ls, v); | 660 | primaryexp(ls, v); |
624 | for (;;) { | 661 | for (;;) { |
625 | switch (ls->t.token) { | 662 | switch (ls->t.token) { |
626 | case l_c('.'): { /* `.' NAME */ | 663 | case l_c('.'): { /* field */ |
627 | next(ls); | 664 | luaY_field(ls, v); |
628 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | ||
629 | luaK_kstr(ls, checkname(ls)); | ||
630 | v->k = VINDEXED; | ||
631 | break; | 665 | break; |
632 | } | 666 | } |
633 | case l_c('['): { /* `[' exp1 `]' */ | 667 | case l_c('['): { /* `[' exp1 `]' */ |
634 | next(ls); | 668 | expdesc key; |
635 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | 669 | luaK_exp2anyreg(fs, v); |
636 | v->k = VINDEXED; | 670 | luaY_index(ls, &key); |
637 | exp1(ls); | 671 | luaK_indexed(fs, v, &key); |
638 | check(ls, l_c(']')); | ||
639 | break; | 672 | break; |
640 | } | 673 | } |
641 | case l_c(':'): { /* `:' NAME funcargs */ | 674 | case l_c(':'): { /* `:' NAME funcargs */ |
675 | expdesc key; | ||
642 | next(ls); | 676 | next(ls); |
643 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | 677 | checkname(ls, &key); |
644 | luaK_code1(ls->fs, OP_PUSHSELF, checkname(ls)); | 678 | luaK_self(fs, v, &key); |
645 | funcargs(ls, 1); | 679 | funcargs(ls, v); |
646 | v->k = VEXP; | ||
647 | v->u.l.t = v->u.l.f = NO_JUMP; | ||
648 | break; | 680 | break; |
649 | } | 681 | } |
650 | case l_c('('): case TK_STRING: case l_c('{'): { /* funcargs */ | 682 | case l_c('('): case TK_STRING: case l_c('{'): { /* funcargs */ |
651 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | 683 | luaK_exp2nextreg(fs, v); |
652 | funcargs(ls, 0); | 684 | funcargs(ls, v); |
653 | v->k = VEXP; | ||
654 | v->u.l.t = v->u.l.f = NO_JUMP; | ||
655 | break; | 685 | break; |
656 | } | 686 | } |
657 | default: return; /* should be follow... */ | 687 | default: return; /* should be follow... */ |
@@ -714,7 +744,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { | |||
714 | if (uop != OPR_NOUNOPR) { | 744 | if (uop != OPR_NOUNOPR) { |
715 | next(ls); | 745 | next(ls); |
716 | subexpr(ls, v, UNARY_PRIORITY); | 746 | subexpr(ls, v, UNARY_PRIORITY); |
717 | luaK_prefix(ls, uop, v); | 747 | luaK_prefix(ls->fs, uop, v); |
718 | } | 748 | } |
719 | else simpleexp(ls, v); | 749 | else simpleexp(ls, v); |
720 | /* expand while operators have priorities higher than `limit' */ | 750 | /* expand while operators have priorities higher than `limit' */ |
@@ -723,10 +753,10 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { | |||
723 | expdesc v2; | 753 | expdesc v2; |
724 | BinOpr nextop; | 754 | BinOpr nextop; |
725 | next(ls); | 755 | next(ls); |
726 | luaK_infix(ls, op, v); | 756 | luaK_infix(ls->fs, op, v); |
727 | /* read sub-expression with higher priority */ | 757 | /* read sub-expression with higher priority */ |
728 | nextop = subexpr(ls, &v2, (int)priority[op].right); | 758 | nextop = subexpr(ls, &v2, (int)priority[op].right); |
729 | luaK_posfix(ls, op, v, &v2); | 759 | luaK_posfix(ls->fs, op, v, &v2); |
730 | op = nextop; | 760 | op = nextop; |
731 | } | 761 | } |
732 | return op; /* return first untreated operator */ | 762 | return op; /* return first untreated operator */ |
@@ -737,13 +767,6 @@ static void expr (LexState *ls, expdesc *v) { | |||
737 | subexpr(ls, v, -1); | 767 | subexpr(ls, v, -1); |
738 | } | 768 | } |
739 | 769 | ||
740 | |||
741 | static void exp1 (LexState *ls) { | ||
742 | expdesc v; | ||
743 | expr(ls, &v); | ||
744 | luaK_tostack(ls, &v, 1); | ||
745 | } | ||
746 | |||
747 | /* }==================================================================== */ | 770 | /* }==================================================================== */ |
748 | 771 | ||
749 | 772 | ||
@@ -769,41 +792,87 @@ static void block (LexState *ls) { | |||
769 | FuncState *fs = ls->fs; | 792 | FuncState *fs = ls->fs; |
770 | int nactloc = fs->nactloc; | 793 | int nactloc = fs->nactloc; |
771 | chunk(ls); | 794 | chunk(ls); |
772 | luaK_adjuststack(fs, fs->nactloc - nactloc); /* remove local variables */ | ||
773 | removelocalvars(ls, fs->nactloc - nactloc); | 795 | removelocalvars(ls, fs->nactloc - nactloc); |
796 | fs->freereg = nactloc; /* free registers used by locals */ | ||
774 | } | 797 | } |
775 | 798 | ||
776 | 799 | ||
777 | static int assignment (LexState *ls, expdesc *v, int nvars) { | 800 | /* |
778 | int left = 0; /* number of values left in the stack after assignment */ | 801 | ** structure to chain all variables in the left-hand side of an |
779 | luaX_checklimit(ls, nvars, MAXVARSLH, l_s("variables in a multiple assignment")); | 802 | ** assignment |
803 | */ | ||
804 | struct LHS_assign { | ||
805 | struct LHS_assign *prev; | ||
806 | expdesc v; /* variable (global, local, or indexed) */ | ||
807 | }; | ||
808 | |||
809 | |||
810 | /* | ||
811 | ** check whether, in an assignment to a local variable, the local variable | ||
812 | ** is needed in a previous assignment (to a table). If so, save original | ||
813 | ** local value in a safe place and use this safe copy in the previous | ||
814 | ** assignment. | ||
815 | */ | ||
816 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | ||
817 | FuncState *fs = ls->fs; | ||
818 | int extra = fs->freereg; /* eventual position to save local variable */ | ||
819 | int conflict = 0; | ||
820 | for (; lh; lh = lh->prev) { | ||
821 | if (lh->v.k == VINDEXED) { | ||
822 | if (lh->v.u.i.info == v->u.i.info) { /* conflict? */ | ||
823 | conflict = 1; | ||
824 | lh->v.u.i.info = extra; /* previous assignment will use safe copy */ | ||
825 | } | ||
826 | if (lh->v.u.i.aux == v->u.i.info) { /* conflict? */ | ||
827 | conflict = 1; | ||
828 | lh->v.u.i.aux = extra; /* previous assignment will use safe copy */ | ||
829 | } | ||
830 | } | ||
831 | } | ||
832 | if (conflict) { | ||
833 | luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.i.info, 0); /* make copy */ | ||
834 | luaK_reserveregs(fs, 1); | ||
835 | } | ||
836 | } | ||
837 | |||
838 | |||
839 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | ||
840 | expdesc e; | ||
841 | check_condition(ls, lh->v.k == VLOCAL || lh->v.k == VGLOBAL || | ||
842 | lh->v.k == VINDEXED, | ||
843 | l_s("syntax error")); | ||
780 | if (ls->t.token == l_c(',')) { /* assignment -> `,' simpleexp assignment */ | 844 | if (ls->t.token == l_c(',')) { /* assignment -> `,' simpleexp assignment */ |
781 | expdesc nv; | 845 | struct LHS_assign nv; |
846 | nv.prev = lh; | ||
782 | next(ls); | 847 | next(ls); |
783 | simpleexp(ls, &nv); | 848 | simpleexp(ls, &nv.v); |
784 | check_condition(ls, (nv.k != VEXP), l_s("syntax error")); | 849 | if (nv.v.k == VLOCAL) |
785 | left = assignment(ls, &nv, nvars+1); | 850 | check_conflict(ls, lh, &nv.v); |
851 | assignment(ls, &nv, nvars+1); | ||
786 | } | 852 | } |
787 | else { /* assignment -> `=' explist1 */ | 853 | else { /* assignment -> `=' explist1 */ |
788 | int nexps; | 854 | int nexps; |
789 | check(ls, l_c('=')); | 855 | check(ls, l_c('=')); |
790 | nexps = explist1(ls); | 856 | nexps = explist1(ls, &e); |
791 | adjust_mult_assign(ls, nvars, nexps); | 857 | if (nexps != nvars) { |
792 | } | 858 | adjust_assign(ls, nvars, nexps, &e); |
793 | if (v->k != VINDEXED) | 859 | if (nexps > nvars) |
794 | luaK_storevar(ls, v); | 860 | ls->fs->freereg -= nexps - nvars; /* remove extra values */ |
795 | else { /* there may be garbage between table-index and value */ | 861 | } |
796 | luaK_code2(ls->fs, OP_SETTABLE, left+nvars+2, 1); | 862 | else { |
797 | left += 2; | 863 | luaK_storevar(ls->fs, &lh->v, &e); |
864 | return; /* avoid default */ | ||
865 | } | ||
798 | } | 866 | } |
799 | return left; | 867 | init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ |
868 | luaK_storevar(ls->fs, &lh->v, &e); | ||
800 | } | 869 | } |
801 | 870 | ||
802 | 871 | ||
803 | static void cond (LexState *ls, expdesc *v) { | 872 | static void cond (LexState *ls, expdesc *v) { |
804 | /* cond -> exp */ | 873 | /* cond -> exp */ |
805 | expr(ls, v); /* read condition */ | 874 | expr(ls, v); /* read condition */ |
806 | luaK_goiftrue(ls->fs, v, 0); | 875 | luaK_goiftrue(ls->fs, v); |
807 | } | 876 | } |
808 | 877 | ||
809 | 878 | ||
@@ -819,7 +888,7 @@ static void whilestat (LexState *ls, int line) { | |||
819 | check(ls, TK_DO); | 888 | check(ls, TK_DO); |
820 | block(ls); | 889 | block(ls); |
821 | luaK_patchlist(fs, luaK_jump(fs), while_init); | 890 | luaK_patchlist(fs, luaK_jump(fs), while_init); |
822 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); | 891 | luaK_patchlist(fs, v.f, luaK_getlabel(fs)); |
823 | check_match(ls, TK_END, TK_WHILE, line); | 892 | check_match(ls, TK_END, TK_WHILE, line); |
824 | leavebreak(fs, &bl); | 893 | leavebreak(fs, &bl); |
825 | } | 894 | } |
@@ -836,20 +905,28 @@ static void repeatstat (LexState *ls, int line) { | |||
836 | block(ls); | 905 | block(ls); |
837 | check_match(ls, TK_UNTIL, TK_REPEAT, line); | 906 | check_match(ls, TK_UNTIL, TK_REPEAT, line); |
838 | cond(ls, &v); | 907 | cond(ls, &v); |
839 | luaK_patchlist(fs, v.u.l.f, repeat_init); | 908 | luaK_patchlist(fs, v.f, repeat_init); |
840 | leavebreak(fs, &bl); | 909 | leavebreak(fs, &bl); |
841 | } | 910 | } |
842 | 911 | ||
843 | 912 | ||
913 | static void exp1 (LexState *ls) { | ||
914 | expdesc e; | ||
915 | expr(ls, &e); | ||
916 | luaK_exp2nextreg(ls->fs, &e); | ||
917 | } | ||
918 | |||
919 | |||
844 | static void forbody (LexState *ls, int nvar, OpCode prepfor, OpCode loopfor) { | 920 | static void forbody (LexState *ls, int nvar, OpCode prepfor, OpCode loopfor) { |
845 | /* forbody -> DO block END */ | 921 | /* forbody -> DO block END */ |
846 | FuncState *fs = ls->fs; | 922 | FuncState *fs = ls->fs; |
847 | int prep = luaK_code1(fs, prepfor, NO_JUMP); | 923 | int basereg = fs->freereg - nvar; |
924 | int prep = luaK_codeAsBc(fs, prepfor, basereg, NO_JUMP); | ||
848 | int blockinit = luaK_getlabel(fs); | 925 | int blockinit = luaK_getlabel(fs); |
849 | check(ls, TK_DO); | 926 | check(ls, TK_DO); |
850 | adjustlocalvars(ls, nvar); /* scope for control variables */ | 927 | adjustlocalvars(ls, nvar); /* scope for control variables */ |
851 | block(ls); | 928 | block(ls); |
852 | luaK_patchlist(fs, luaK_code1(fs, loopfor, NO_JUMP), blockinit); | 929 | luaK_patchlist(fs, luaK_codeAsBc(fs, loopfor, basereg, NO_JUMP), blockinit); |
853 | luaK_fixfor(fs, prep, luaK_getlabel(fs)); | 930 | luaK_fixfor(fs, prep, luaK_getlabel(fs)); |
854 | removelocalvars(ls, nvar); | 931 | removelocalvars(ls, nvar); |
855 | } | 932 | } |
@@ -864,8 +941,10 @@ static void fornum (LexState *ls, TString *varname) { | |||
864 | exp1(ls); /* limit */ | 941 | exp1(ls); /* limit */ |
865 | if (optional(ls, l_c(','))) | 942 | if (optional(ls, l_c(','))) |
866 | exp1(ls); /* optional step */ | 943 | exp1(ls); /* optional step */ |
867 | else | 944 | else { |
868 | luaK_code1(fs, OP_PUSHINT, 1); /* default step */ | 945 | luaK_codeAsBc(fs, OP_LOADINT, fs->freereg, 1); /* default step */ |
946 | luaK_reserveregs(fs, 1); | ||
947 | } | ||
869 | new_localvar(ls, varname, 0); | 948 | new_localvar(ls, varname, 0); |
870 | new_localvarstr(ls, l_s("(limit)"), 1); | 949 | new_localvarstr(ls, l_s("(limit)"), 1); |
871 | new_localvarstr(ls, l_s("(step)"), 2); | 950 | new_localvarstr(ls, l_s("(step)"), 2); |
@@ -889,7 +968,8 @@ static void forlist (LexState *ls, TString *indexname) { | |||
889 | new_localvarstr(ls, l_s("(index)"), 1); | 968 | new_localvarstr(ls, l_s("(index)"), 1); |
890 | new_localvar(ls, indexname, 2); | 969 | new_localvar(ls, indexname, 2); |
891 | new_localvar(ls, valname, 3); | 970 | new_localvar(ls, valname, 3); |
892 | forbody(ls, 4, OP_LFORPREP, OP_LFORLOOP); | 971 | luaK_reserveregs(ls->fs, 3); /* registers for control, index and val */ |
972 | forbody(ls, 4, OP_TFORPREP, OP_TFORLOOP); | ||
893 | } | 973 | } |
894 | 974 | ||
895 | 975 | ||
@@ -928,17 +1008,17 @@ static void ifstat (LexState *ls, int line) { | |||
928 | test_then_block(ls, &v); /* IF cond THEN block */ | 1008 | test_then_block(ls, &v); /* IF cond THEN block */ |
929 | while (ls->t.token == TK_ELSEIF) { | 1009 | while (ls->t.token == TK_ELSEIF) { |
930 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | 1010 | luaK_concat(fs, &escapelist, luaK_jump(fs)); |
931 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); | 1011 | luaK_patchlist(fs, v.f, luaK_getlabel(fs)); |
932 | test_then_block(ls, &v); /* ELSEIF cond THEN block */ | 1012 | test_then_block(ls, &v); /* ELSEIF cond THEN block */ |
933 | } | 1013 | } |
934 | if (ls->t.token == TK_ELSE) { | 1014 | if (ls->t.token == TK_ELSE) { |
935 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | 1015 | luaK_concat(fs, &escapelist, luaK_jump(fs)); |
936 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); | 1016 | luaK_patchlist(fs, v.f, luaK_getlabel(fs)); |
937 | next(ls); /* skip ELSE */ | 1017 | next(ls); /* skip ELSE */ |
938 | block(ls); /* `else' part */ | 1018 | block(ls); /* `else' part */ |
939 | } | 1019 | } |
940 | else | 1020 | else |
941 | luaK_concat(fs, &escapelist, v.u.l.f); | 1021 | luaK_concat(fs, &escapelist, v.f); |
942 | luaK_patchlist(fs, escapelist, luaK_getlabel(fs)); | 1022 | luaK_patchlist(fs, escapelist, luaK_getlabel(fs)); |
943 | check_match(ls, TK_END, TK_IF, line); | 1023 | check_match(ls, TK_END, TK_IF, line); |
944 | } | 1024 | } |
@@ -948,35 +1028,32 @@ static void localstat (LexState *ls) { | |||
948 | /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ | 1028 | /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ |
949 | int nvars = 0; | 1029 | int nvars = 0; |
950 | int nexps; | 1030 | int nexps; |
1031 | expdesc e; | ||
951 | do { | 1032 | do { |
952 | next(ls); /* skip LOCAL or `,' */ | 1033 | next(ls); /* skip LOCAL or `,' */ |
953 | new_localvar(ls, str_checkname(ls), nvars++); | 1034 | new_localvar(ls, str_checkname(ls), nvars++); |
954 | } while (ls->t.token == l_c(',')); | 1035 | } while (ls->t.token == l_c(',')); |
955 | if (optional(ls, l_c('='))) | 1036 | if (optional(ls, l_c('='))) |
956 | nexps = explist1(ls); | 1037 | nexps = explist1(ls, &e); |
957 | else | 1038 | else { |
1039 | e.k = VVOID; | ||
958 | nexps = 0; | 1040 | nexps = 0; |
959 | adjust_mult_assign(ls, nvars, nexps); | 1041 | } |
1042 | adjust_assign(ls, nvars, nexps, &e); | ||
960 | adjustlocalvars(ls, nvars); | 1043 | adjustlocalvars(ls, nvars); |
961 | } | 1044 | } |
962 | 1045 | ||
963 | 1046 | ||
964 | static int funcname (LexState *ls, expdesc *v) { | 1047 | static int funcname (LexState *ls, expdesc *v) { |
965 | /* funcname -> NAME {`.' NAME} [`:' NAME] */ | 1048 | /* funcname -> NAME {field} [`:' NAME] */ |
966 | int needself = 0; | 1049 | int needself = 0; |
967 | singlevar(ls, str_checkname(ls), v); | 1050 | singlevar(ls, str_checkname(ls), v); |
968 | while (ls->t.token == l_c('.')) { | 1051 | while (ls->t.token == l_c('.')) { |
969 | next(ls); | 1052 | luaY_field(ls, v); |
970 | luaK_tostack(ls, v, 1); | ||
971 | luaK_kstr(ls, checkname(ls)); | ||
972 | v->k = VINDEXED; | ||
973 | } | 1053 | } |
974 | if (ls->t.token == l_c(':')) { | 1054 | if (ls->t.token == l_c(':')) { |
975 | needself = 1; | 1055 | needself = 1; |
976 | next(ls); | 1056 | luaY_field(ls, v); |
977 | luaK_tostack(ls, v, 1); | ||
978 | luaK_kstr(ls, checkname(ls)); | ||
979 | v->k = VINDEXED; | ||
980 | } | 1057 | } |
981 | return needself; | 1058 | return needself; |
982 | } | 1059 | } |
@@ -985,26 +1062,25 @@ static int funcname (LexState *ls, expdesc *v) { | |||
985 | static void funcstat (LexState *ls, int line) { | 1062 | static void funcstat (LexState *ls, int line) { |
986 | /* funcstat -> FUNCTION funcname body */ | 1063 | /* funcstat -> FUNCTION funcname body */ |
987 | int needself; | 1064 | int needself; |
988 | expdesc v; | 1065 | expdesc v, b; |
989 | next(ls); /* skip FUNCTION */ | 1066 | next(ls); /* skip FUNCTION */ |
990 | needself = funcname(ls, &v); | 1067 | needself = funcname(ls, &v); |
991 | body(ls, needself, line); | 1068 | body(ls, &b, needself, line); |
992 | luaK_storevar(ls, &v); | 1069 | luaK_storevar(ls->fs, &v, &b); |
993 | } | 1070 | } |
994 | 1071 | ||
995 | 1072 | ||
996 | static void exprstat (LexState *ls) { | 1073 | static void exprstat (LexState *ls) { |
997 | /* stat -> func | assignment */ | 1074 | /* stat -> func | assignment */ |
998 | FuncState *fs = ls->fs; | 1075 | FuncState *fs = ls->fs; |
999 | expdesc v; | 1076 | struct LHS_assign v; |
1000 | simpleexp(ls, &v); | 1077 | simpleexp(ls, &v.v); |
1001 | if (v.k == VEXP) { /* stat -> func */ | 1078 | if (v.v.k == VCALL) { /* stat -> func */ |
1002 | check_condition(ls, luaK_lastisopen(fs), l_s("syntax error")); /* an upvalue? */ | 1079 | luaK_setcallreturns(fs, &v.v, 0); /* call statement uses no results */ |
1003 | luaK_setcallreturns(fs, 0); /* call statement uses no results */ | ||
1004 | } | 1080 | } |
1005 | else { /* stat -> assignment */ | 1081 | else { /* stat -> assignment */ |
1006 | int left = assignment(ls, &v, 1); | 1082 | v.prev = NULL; |
1007 | luaK_adjuststack(fs, left); /* remove eventual garbage left on stack */ | 1083 | assignment(ls, &v, 1); |
1008 | } | 1084 | } |
1009 | } | 1085 | } |
1010 | 1086 | ||
@@ -1012,26 +1088,45 @@ static void exprstat (LexState *ls) { | |||
1012 | static void retstat (LexState *ls) { | 1088 | static void retstat (LexState *ls) { |
1013 | /* stat -> RETURN explist */ | 1089 | /* stat -> RETURN explist */ |
1014 | FuncState *fs = ls->fs; | 1090 | FuncState *fs = ls->fs; |
1091 | expdesc e; | ||
1092 | int first, last1; /* registers with returned values */ | ||
1015 | next(ls); /* skip RETURN */ | 1093 | next(ls); /* skip RETURN */ |
1016 | if (!block_follow(ls->t.token) && ls->t.token != l_c(';')) | 1094 | if (block_follow(ls->t.token) || ls->t.token == l_c(';')) |
1017 | explist1(ls); /* optional return values */ | 1095 | first = last1 = 0; /* return no values */ |
1018 | luaK_code1(fs, OP_RETURN, ls->fs->nactloc); | 1096 | else { |
1019 | fs->stacklevel = fs->nactloc; /* removes all temp values */ | 1097 | int n = explist1(ls, &e); /* optional return values */ |
1098 | if (e.k == VCALL) { | ||
1099 | luaK_setcallreturns(fs, &e, NO_REG); | ||
1100 | first = fs->nactloc; | ||
1101 | last1 = NO_REG; /* return all values */ | ||
1102 | } | ||
1103 | else { | ||
1104 | if (n == 1) { /* only one value? */ | ||
1105 | luaK_exp2anyreg(fs, &e); | ||
1106 | first = e.u.i.info; | ||
1107 | last1 = first+1; /* return only this value */ | ||
1108 | } | ||
1109 | else { | ||
1110 | luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ | ||
1111 | first = fs->nactloc; | ||
1112 | last1 = fs->freereg; /* return all `active' values */ | ||
1113 | } | ||
1114 | } | ||
1115 | } | ||
1116 | luaK_codeABC(fs, OP_RETURN, first, last1, 0); | ||
1117 | fs->freereg = fs->nactloc; /* removes all temp values */ | ||
1020 | } | 1118 | } |
1021 | 1119 | ||
1022 | 1120 | ||
1023 | static void breakstat (LexState *ls) { | 1121 | static void breakstat (LexState *ls) { |
1024 | /* stat -> BREAK [NAME] */ | 1122 | /* stat -> BREAK [NAME] */ |
1025 | FuncState *fs = ls->fs; | 1123 | FuncState *fs = ls->fs; |
1026 | int currentlevel = fs->stacklevel; | ||
1027 | Breaklabel *bl = fs->bl; | 1124 | Breaklabel *bl = fs->bl; |
1028 | if (!bl) | 1125 | if (!bl) |
1029 | luaK_error(ls, l_s("no loop to break")); | 1126 | luaK_error(ls, l_s("no loop to break")); |
1030 | next(ls); /* skip BREAK */ | 1127 | next(ls); /* skip BREAK */ |
1031 | luaK_adjuststack(fs, currentlevel - bl->stacklevel); | ||
1032 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); | 1128 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); |
1033 | /* correct stack for compiler and symbolic execution */ | 1129 | /* correct stack for compiler and symbolic execution */ |
1034 | luaK_adjuststack(fs, bl->stacklevel - currentlevel); | ||
1035 | } | 1130 | } |
1036 | 1131 | ||
1037 | 1132 | ||
@@ -1105,7 +1200,7 @@ static void parlist (LexState *ls) { | |||
1105 | } | 1200 | } |
1106 | 1201 | ||
1107 | 1202 | ||
1108 | static void body (LexState *ls, int needself, int line) { | 1203 | static void body (LexState *ls, expdesc *e, int needself, int line) { |
1109 | /* body -> `(' parlist `)' chunk END */ | 1204 | /* body -> `(' parlist `)' chunk END */ |
1110 | FuncState new_fs; | 1205 | FuncState new_fs; |
1111 | open_func(ls, &new_fs); | 1206 | open_func(ls, &new_fs); |
@@ -1120,7 +1215,7 @@ static void body (LexState *ls, int needself, int line) { | |||
1120 | chunk(ls); | 1215 | chunk(ls); |
1121 | check_match(ls, TK_END, TK_FUNCTION, line); | 1216 | check_match(ls, TK_END, TK_FUNCTION, line); |
1122 | close_func(ls); | 1217 | close_func(ls); |
1123 | pushclosure(ls, &new_fs); | 1218 | pushclosure(ls, &new_fs, e); |
1124 | } | 1219 | } |
1125 | 1220 | ||
1126 | 1221 | ||
@@ -1133,7 +1228,10 @@ static void chunk (LexState *ls) { | |||
1133 | while (!islast && !block_follow(ls->t.token)) { | 1228 | while (!islast && !block_follow(ls->t.token)) { |
1134 | islast = statement(ls); | 1229 | islast = statement(ls); |
1135 | optional(ls, l_c(';')); | 1230 | optional(ls, l_c(';')); |
1136 | lua_assert(ls->fs->stacklevel == ls->fs->nactloc); | 1231 | if (ls->fs->freereg < ls->fs->nactloc) |
1232 | printf(">>>>>>> %d %d\n", ls->fs->freereg, ls->fs->nactloc); | ||
1233 | lua_assert(ls->fs->freereg >= ls->fs->nactloc); | ||
1234 | ls->fs->freereg = ls->fs->nactloc; /* free registers */ | ||
1137 | } | 1235 | } |
1138 | } | 1236 | } |
1139 | 1237 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.h,v 1.29 2000/12/28 12:55:41 roberto Exp roberto $ | 2 | ** $Id: lparser.h,v 1.30 2001/02/20 18:28:11 roberto Exp roberto $ |
3 | ** LL(1) Parser and code generator for Lua | 3 | ** LL(1) Parser and code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -16,25 +16,32 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | typedef enum { | 18 | typedef enum { |
19 | VGLOBAL, | 19 | VVOID, /* no value */ |
20 | VLOCAL, | 20 | VNIL, |
21 | VINDEXED, | 21 | VNUMBER, /* n = value */ |
22 | VEXP | 22 | VK, /* info = index of constant in `k' */ |
23 | VGLOBAL, /* info = index of global name in `k' */ | ||
24 | VLOCAL, /* info = local register */ | ||
25 | VINDEXED, /* info = table register; aux = index register (or `k') */ | ||
26 | VRELOCABLE, /* info = instruction pc */ | ||
27 | VNONRELOC, /* info = result register */ | ||
28 | VJMP, /* info = result register */ | ||
29 | VCALL /* info = result register */ | ||
23 | } expkind; | 30 | } expkind; |
24 | 31 | ||
25 | typedef struct expdesc { | 32 | typedef struct expdesc { |
26 | expkind k; | 33 | expkind k; |
27 | union { | 34 | union { |
28 | int index; /* VGLOBAL: `kstr' index of global name; VLOCAL: stack index */ | ||
29 | struct { | 35 | struct { |
30 | int t; /* patch list of `exit when true' */ | 36 | int info, aux; |
31 | int f; /* patch list of `exit when false' */ | 37 | } i; |
32 | } l; | 38 | lua_Number n; |
33 | } u; | 39 | } u; |
40 | int t; /* patch list of `exit when true' */ | ||
41 | int f; /* patch list of `exit when false' */ | ||
34 | } expdesc; | 42 | } expdesc; |
35 | 43 | ||
36 | 44 | ||
37 | |||
38 | /* state needed to generate code for a given function */ | 45 | /* state needed to generate code for a given function */ |
39 | typedef struct FuncState { | 46 | typedef struct FuncState { |
40 | Proto *f; /* current function header */ | 47 | Proto *f; /* current function header */ |
@@ -44,10 +51,9 @@ typedef struct FuncState { | |||
44 | int pc; /* next position to code (equivalent to `ncode') */ | 51 | int pc; /* next position to code (equivalent to `ncode') */ |
45 | int lasttarget; /* `pc' of last `jump target' */ | 52 | int lasttarget; /* `pc' of last `jump target' */ |
46 | int jlt; /* list of jumps to `lasttarget' */ | 53 | int jlt; /* list of jumps to `lasttarget' */ |
47 | int stacklevel; /* number of values on activation register */ | 54 | int freereg; /* first free register */ |
48 | int nkstr; /* number of elements in `kstr' */ | 55 | int nk; /* number of elements in `k' */ |
49 | int nkproto; /* number of elements in `kproto' */ | 56 | int nkproto; /* number of elements in `kproto' */ |
50 | int nknum; /* number of elements in `knum' */ | ||
51 | int nlineinfo; /* number of elements in `lineinfo' */ | 57 | int nlineinfo; /* number of elements in `lineinfo' */ |
52 | int nlocvars; /* number of elements in `locvars' */ | 58 | int nlocvars; /* number of elements in `locvars' */ |
53 | int nactloc; /* number of active local variables */ | 59 | int nactloc; /* number of active local variables */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 1.79 2001/04/17 17:35:54 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 1.80 2001/04/23 16:35:45 roberto Exp roberto $ |
3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -140,77 +140,65 @@ void *debug_realloc (void *block, size_t oldsize, size_t size) { | |||
140 | 140 | ||
141 | 141 | ||
142 | static const l_char *const instrname[NUM_OPCODES] = { | 142 | static const l_char *const instrname[NUM_OPCODES] = { |
143 | l_s("RETURN"), | 143 | l_s("OP_MOVE"), |
144 | l_s("CALL"), | 144 | l_s("OP_LOADK"), |
145 | l_s("PUSHNIL"), | 145 | l_s("OP_LOADINT"), |
146 | l_s("POP"), | 146 | l_s("OP_LOADNIL"), |
147 | l_s("PUSHINT"), | 147 | l_s("OP_LOADUPVAL"), |
148 | l_s("PUSHSTRING"), | 148 | l_s("OP_GETGLOBAL"), |
149 | l_s("PUSHNUM"), | 149 | l_s("OP_GETTABLE"), |
150 | l_s("PUSHNEGNUM"), | 150 | l_s("OP_SETGLOBAL"), |
151 | l_s("PUSHUPVALUE"), | 151 | l_s("OP_SETTABLE"), |
152 | l_s("GETLOCAL"), | 152 | l_s("OP_NEWTABLE"), |
153 | l_s("GETGLOBAL"), | 153 | l_s("OP_SELF"), |
154 | l_s("GETTABLE"), | 154 | l_s("OP_ADD"), |
155 | l_s("GETDOTTED"), | 155 | l_s("OP_SUB"), |
156 | l_s("GETINDEXED"), | 156 | l_s("OP_MUL"), |
157 | l_s("PUSHSELF"), | 157 | l_s("OP_DIV"), |
158 | l_s("CREATETABLE"), | 158 | l_s("OP_POW"), |
159 | l_s("SETLOCAL"), | 159 | l_s("OP_UNM"), |
160 | l_s("SETGLOBAL"), | 160 | l_s("OP_NOT"), |
161 | l_s("SETTABLE"), | 161 | l_s("OP_CONCAT"), |
162 | l_s("SETLIST"), | 162 | l_s("OP_JMP"), |
163 | l_s("SETMAP"), | 163 | l_s("OP_CJMP"), |
164 | l_s("ADD"), | 164 | l_s("OP_TESTEQ"), |
165 | l_s("ADDI"), | 165 | l_s("OP_TESTNE"), |
166 | l_s("SUB"), | 166 | l_s("OP_TESTLT"), |
167 | l_s("MULT"), | 167 | l_s("OP_TESTLE"), |
168 | l_s("DIV"), | 168 | l_s("OP_TESTGT"), |
169 | l_s("POW"), | 169 | l_s("OP_TESTGE"), |
170 | l_s("CONCAT"), | 170 | l_s("OP_TESTT"), |
171 | l_s("MINUS"), | 171 | l_s("OP_TESTF"), |
172 | l_s("NOT"), | 172 | l_s("OP_NILJMP"), |
173 | l_s("JMPNE"), | 173 | l_s("OP_CALL"), |
174 | l_s("JMPEQ"), | 174 | l_s("OP_RETURN"), |
175 | l_s("JMPLT"), | 175 | l_s("OP_FORPREP"), |
176 | l_s("JMPLE"), | 176 | l_s("OP_FORLOOP"), |
177 | l_s("JMPGT"), | 177 | l_s("OP_LFORPREP"), |
178 | l_s("JMPGE"), | 178 | l_s("OP_LFORLOOP"), |
179 | l_s("JMPT"), | 179 | l_s("OP_SETLIST"), |
180 | l_s("JMPF"), | 180 | l_s("OP_CLOSURE") |
181 | l_s("JMPONT"), | ||
182 | l_s("JMPONF"), | ||
183 | l_s("JMP"), | ||
184 | l_s("PUSHNILJMP"), | ||
185 | l_s("FORPREP"), | ||
186 | l_s("FORLOOP"), | ||
187 | l_s("LFORPREP"), | ||
188 | l_s("LFORLOOP"), | ||
189 | l_s("CLOSURE") | ||
190 | }; | 181 | }; |
191 | 182 | ||
192 | 183 | ||
193 | static void pushop (lua_State *L, Proto *p, int pc) { | 184 | static l_char *buildop (Proto *p, int pc, l_char *buff) { |
194 | l_char buff[100]; | ||
195 | Instruction i = p->code[pc]; | 185 | Instruction i = p->code[pc]; |
196 | OpCode o = GET_OPCODE(i); | 186 | OpCode o = GET_OPCODE(i); |
197 | const l_char *name = instrname[o]; | 187 | const l_char *name = instrname[o]; |
198 | sprintf(buff, l_s("%5d - "), luaG_getline(p->lineinfo, pc, 1, NULL)); | 188 | sprintf(buff, l_s("%4d - "), pc); |
199 | switch ((enum Mode)luaK_opproperties[o].mode) { | 189 | switch (getOpMode(o)) { |
200 | case iO: | 190 | case iABC: |
201 | sprintf(buff+8, l_s("%-12s"), name); | 191 | sprintf(buff+strlen(buff), l_s("%-12s%4d %4d %4d"), name, |
192 | GETARG_A(i), GETARG_B(i), GETARG_C(i)); | ||
202 | break; | 193 | break; |
203 | case iU: | 194 | case iABc: |
204 | sprintf(buff+8, l_s("%-12s%4u"), name, GETARG_U(i)); | 195 | sprintf(buff+strlen(buff), l_s("%-12s%4d %4d"), name, GETARG_A(i), GETARG_Bc(i)); |
205 | break; | 196 | break; |
206 | case iS: | 197 | case iAsBc: |
207 | sprintf(buff+8, l_s("%-12s%4d"), name, GETARG_S(i)); | 198 | sprintf(buff+strlen(buff), l_s("%-12s%4d %4d"), name, GETARG_A(i), GETARG_sBc(i)); |
208 | break; | ||
209 | case iAB: | ||
210 | sprintf(buff+8, l_s("%-12s%4d %4d"), name, GETARG_A(i), GETARG_B(i)); | ||
211 | break; | 199 | break; |
212 | } | 200 | } |
213 | lua_pushstring(L, buff); | 201 | return buff; |
214 | } | 202 | } |
215 | 203 | ||
216 | 204 | ||
@@ -224,24 +212,25 @@ static int listcode (lua_State *L) { | |||
224 | setnameval(L, l_s("maxstack"), p->maxstacksize); | 212 | setnameval(L, l_s("maxstack"), p->maxstacksize); |
225 | setnameval(L, l_s("numparams"), p->numparams); | 213 | setnameval(L, l_s("numparams"), p->numparams); |
226 | for (pc=0; pc<p->sizecode; pc++) { | 214 | for (pc=0; pc<p->sizecode; pc++) { |
215 | l_char buff[100]; | ||
227 | lua_pushnumber(L, pc+1); | 216 | lua_pushnumber(L, pc+1); |
228 | pushop(L, p, pc); | 217 | lua_pushstring(L, buildop(p, pc, buff)); |
229 | lua_settable(L, -3); | 218 | lua_settable(L, -3); |
230 | } | 219 | } |
231 | return 1; | 220 | return 1; |
232 | } | 221 | } |
233 | 222 | ||
234 | 223 | ||
235 | static int liststrings (lua_State *L) { | 224 | static int listk (lua_State *L) { |
236 | Proto *p; | 225 | Proto *p; |
237 | int i; | 226 | int i; |
238 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), | 227 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), |
239 | 1, l_s("Lua function expected")); | 228 | 1, l_s("Lua function expected")); |
240 | p = clvalue(luaA_index(L, 1))->f.l; | 229 | p = clvalue(luaA_index(L, 1))->f.l; |
241 | lua_newtable(L); | 230 | lua_newtable(L); |
242 | for (i=0; i<p->sizekstr; i++) { | 231 | for (i=0; i<p->sizek; i++) { |
243 | lua_pushnumber(L, i+1); | 232 | lua_pushnumber(L, i+1); |
244 | lua_pushstring(L, getstr(p->kstr[i])); | 233 | luaA_pushobject(L, p->k+i); |
245 | lua_settable(L, -3); | 234 | lua_settable(L, -3); |
246 | } | 235 | } |
247 | return 1; | 236 | return 1; |
@@ -276,20 +265,10 @@ static int get_limits (lua_State *L) { | |||
276 | lua_newtable(L); | 265 | lua_newtable(L); |
277 | setnameval(L, l_s("BITS_INT"), BITS_INT); | 266 | setnameval(L, l_s("BITS_INT"), BITS_INT); |
278 | setnameval(L, l_s("LFPF"), LFIELDS_PER_FLUSH); | 267 | setnameval(L, l_s("LFPF"), LFIELDS_PER_FLUSH); |
279 | setnameval(L, l_s("MAXARG_A"), MAXARG_A); | ||
280 | setnameval(L, l_s("MAXARG_B"), MAXARG_B); | ||
281 | setnameval(L, l_s("MAXARG_S"), MAXARG_S); | ||
282 | setnameval(L, l_s("MAXARG_U"), MAXARG_U); | ||
283 | setnameval(L, l_s("MAXLOCALS"), MAXLOCALS); | 268 | setnameval(L, l_s("MAXLOCALS"), MAXLOCALS); |
284 | setnameval(L, l_s("MAXPARAMS"), MAXPARAMS); | 269 | setnameval(L, l_s("MAXPARAMS"), MAXPARAMS); |
285 | setnameval(L, l_s("MAXSTACK"), MAXSTACK); | 270 | setnameval(L, l_s("MAXSTACK"), MAXSTACK); |
286 | setnameval(L, l_s("MAXUPVALUES"), MAXUPVALUES); | 271 | setnameval(L, l_s("MAXUPVALUES"), MAXUPVALUES); |
287 | setnameval(L, l_s("MAXVARSLH"), MAXVARSLH); | ||
288 | setnameval(L, l_s("RFPF"), RFIELDS_PER_FLUSH); | ||
289 | setnameval(L, l_s("SIZE_A"), SIZE_A); | ||
290 | setnameval(L, l_s("SIZE_B"), SIZE_B); | ||
291 | setnameval(L, l_s("SIZE_OP"), SIZE_OP); | ||
292 | setnameval(L, l_s("SIZE_U"), SIZE_U); | ||
293 | return 1; | 272 | return 1; |
294 | } | 273 | } |
295 | 274 | ||
@@ -700,7 +679,7 @@ static const struct luaL_reg tests_funcs[] = { | |||
700 | {l_s("hash"), hash_query}, | 679 | {l_s("hash"), hash_query}, |
701 | {l_s("limits"), get_limits}, | 680 | {l_s("limits"), get_limits}, |
702 | {l_s("listcode"), listcode}, | 681 | {l_s("listcode"), listcode}, |
703 | {l_s("liststrings"), liststrings}, | 682 | {l_s("listk"), listk}, |
704 | {l_s("listlocals"), listlocals}, | 683 | {l_s("listlocals"), listlocals}, |
705 | {l_s("loadlib"), loadlib}, | 684 | {l_s("loadlib"), loadlib}, |
706 | {l_s("querystr"), string_query}, | 685 | {l_s("querystr"), string_query}, |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.177 2001/03/26 14:31:49 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.178 2001/04/06 18:25:00 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -28,15 +28,14 @@ | |||
28 | 28 | ||
29 | 29 | ||
30 | 30 | ||
31 | int luaV_tonumber (TObject *obj) { | 31 | const TObject *luaV_tonumber (const TObject *obj, TObject *n) { |
32 | if (ttype(obj) != LUA_TSTRING) | 32 | if (ttype(obj) == LUA_TNUMBER) return obj; |
33 | return 1; | 33 | if (ttype(obj) == LUA_TSTRING && luaO_str2d(svalue(obj), &nvalue(n))) { |
34 | else { | 34 | ttype(n) = LUA_TNUMBER; |
35 | if (!luaO_str2d(svalue(obj), &nvalue(obj))) | 35 | return n; |
36 | return 2; | ||
37 | ttype(obj) = LUA_TNUMBER; | ||
38 | return 0; | ||
39 | } | 36 | } |
37 | else | ||
38 | return NULL; | ||
40 | } | 39 | } |
41 | 40 | ||
42 | 41 | ||
@@ -148,8 +147,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { | |||
148 | } | 147 | } |
149 | } | 148 | } |
150 | /* else will call the tag method */ | 149 | /* else will call the tag method */ |
151 | } | 150 | } else { /* not a table; try a `gettable' tag method */ |
152 | else { /* not a table; try a `gettable' tag method */ | ||
153 | tm = luaT_gettmbyObj(G(L), t, TM_GETTABLE); | 151 | tm = luaT_gettmbyObj(G(L), t, TM_GETTABLE); |
154 | if (tm == NULL) /* no tag method? */ | 152 | if (tm == NULL) /* no tag method? */ |
155 | luaG_typeerror(L, t, l_s("index")); | 153 | luaG_typeerror(L, t, l_s("index")); |
@@ -162,7 +160,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { | |||
162 | /* | 160 | /* |
163 | ** Receives table at `t', key at `key' and value at `val'. | 161 | ** Receives table at `t', key at `key' and value at `val'. |
164 | */ | 162 | */ |
165 | void luaV_settable (lua_State *L, StkId t, StkId key, StkId val) { | 163 | void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) { |
166 | Closure *tm; | 164 | Closure *tm; |
167 | if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ | 165 | if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ |
168 | int tg = hvalue(t)->htag; | 166 | int tg = hvalue(t)->htag; |
@@ -172,8 +170,7 @@ void luaV_settable (lua_State *L, StkId t, StkId key, StkId val) { | |||
172 | return; | 170 | return; |
173 | } | 171 | } |
174 | /* else will call the tag method */ | 172 | /* else will call the tag method */ |
175 | } | 173 | } else { /* not a table; try a `settable' tag method */ |
176 | else { /* not a table; try a `settable' tag method */ | ||
177 | tm = luaT_gettmbyObj(G(L), t, TM_SETTABLE); | 174 | tm = luaT_gettmbyObj(G(L), t, TM_SETTABLE); |
178 | if (tm == NULL) /* no tag method? */ | 175 | if (tm == NULL) /* no tag method? */ |
179 | luaG_typeerror(L, t, l_s("index")); | 176 | luaG_typeerror(L, t, l_s("index")); |
@@ -188,8 +185,7 @@ void luaV_getglobal (lua_State *L, TString *name, StkId res) { | |||
188 | if (!HAS_TM_GETGLOBAL(L, ttype(value)) || /* is there a tag method? */ | 185 | if (!HAS_TM_GETGLOBAL(L, ttype(value)) || /* is there a tag method? */ |
189 | (tm = luaT_gettmbyObj(G(L), value, TM_GETGLOBAL)) == NULL) { | 186 | (tm = luaT_gettmbyObj(G(L), value, TM_GETGLOBAL)) == NULL) { |
190 | setobj(res, value); /* default behavior */ | 187 | setobj(res, value); /* default behavior */ |
191 | } | 188 | } else |
192 | else | ||
193 | callTM(L, l_s("csor"), tm, name, value, res); | 189 | callTM(L, l_s("csor"), tm, name, value, res); |
194 | } | 190 | } |
195 | 191 | ||
@@ -200,8 +196,7 @@ void luaV_setglobal (lua_State *L, TString *name, StkId val) { | |||
200 | if (!HAS_TM_SETGLOBAL(L, ttype(oldvalue)) || /* no tag methods? */ | 196 | if (!HAS_TM_SETGLOBAL(L, ttype(oldvalue)) || /* no tag methods? */ |
201 | (tm = luaT_gettmbyObj(G(L), oldvalue, TM_SETGLOBAL)) == NULL) { | 197 | (tm = luaT_gettmbyObj(G(L), oldvalue, TM_SETGLOBAL)) == NULL) { |
202 | setobj(oldvalue, val); /* raw set */ | 198 | setobj(oldvalue, val); /* raw set */ |
203 | } | 199 | } else |
204 | else | ||
205 | callTM(L, l_s("csoo"), tm, name, oldvalue, val); | 200 | callTM(L, l_s("csoo"), tm, name, oldvalue, val); |
206 | } | 201 | } |
207 | 202 | ||
@@ -224,9 +219,10 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, | |||
224 | } | 219 | } |
225 | 220 | ||
226 | 221 | ||
227 | static void call_arith (lua_State *L, StkId p1, TMS event) { | 222 | static void call_arith (lua_State *L, StkId p1, TObject *p2, |
228 | if (!call_binTM(L, p1, p1+1, p1, event)) | 223 | StkId res, TMS event) { |
229 | luaG_binerror(L, p1, LUA_TNUMBER, l_s("perform arithmetic on")); | 224 | if (!call_binTM(L, p1, p2, res, event)) |
225 | luaG_aritherror(L, p1, p2); | ||
230 | } | 226 | } |
231 | 227 | ||
232 | 228 | ||
@@ -270,9 +266,8 @@ void luaV_strconc (lua_State *L, int total, StkId top) { | |||
270 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 266 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
271 | if (tostring(L, top-2) || tostring(L, top-1)) { | 267 | if (tostring(L, top-2) || tostring(L, top-1)) { |
272 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) | 268 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) |
273 | luaG_binerror(L, top-2, LUA_TSTRING, l_s("concat")); | 269 | luaG_concaterror(L, top-2, top-1); |
274 | } | 270 | } else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ |
275 | else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ | ||
276 | /* at least two string values; get as many as possible */ | 271 | /* at least two string values; get as many as possible */ |
277 | lu_mem tl = (lu_mem)tsvalue(top-1)->len + (lu_mem)tsvalue(top-2)->len; | 272 | lu_mem tl = (lu_mem)tsvalue(top-1)->len + (lu_mem)tsvalue(top-2)->len; |
278 | l_char *buffer; | 273 | l_char *buffer; |
@@ -321,7 +316,32 @@ static void adjust_varargs (lua_State *L, StkId base, int nfixargs) { | |||
321 | 316 | ||
322 | 317 | ||
323 | 318 | ||
324 | #define dojump(pc, i) ((pc) += GETARG_S(i)) | 319 | /* |
320 | ** some macros for common tasks in `luaV_execute' | ||
321 | */ | ||
322 | |||
323 | #define runtime_check(L, c) { if (!(c)) return L->top; } | ||
324 | |||
325 | #define RA(i) (base+GETARG_A(i)) | ||
326 | #define RB(i) (base+GETARG_B(i)) | ||
327 | #define RC(i) (base+GETARG_C(i)) | ||
328 | #define RKC(i) ((GETARG_C(i) < MAXSTACK) ? \ | ||
329 | base+GETARG_C(i) : \ | ||
330 | tf->k+GETARG_C(i)-MAXSTACK) | ||
331 | #define KBc(i) (tf->k+GETARG_Bc(i)) | ||
332 | |||
333 | #define Arith(op, optm) { \ | ||
334 | const TObject *b = RB(i); const TObject *c = RKC(i); \ | ||
335 | TObject tempb, tempc; \ | ||
336 | if ((ttype(b) == LUA_TNUMBER || (b = luaV_tonumber(b, &tempb)) != NULL) && \ | ||
337 | (ttype(c) == LUA_TNUMBER || (c = luaV_tonumber(c, &tempc)) != NULL)) { \ | ||
338 | setnvalue(RA(i), nvalue(b) op nvalue(c)); \ | ||
339 | } else \ | ||
340 | call_arith(L, RB(i), RKC(i), RA(i), optm); \ | ||
341 | } | ||
342 | |||
343 | |||
344 | #define dojump(pc, i) ((pc) += GETARG_sBc(i)) | ||
325 | 345 | ||
326 | /* | 346 | /* |
327 | ** Executes the given Lua function. Parameters are between [base,top). | 347 | ** Executes the given Lua function. Parameters are between [base,top). |
@@ -329,328 +349,294 @@ static void adjust_varargs (lua_State *L, StkId base, int nfixargs) { | |||
329 | */ | 349 | */ |
330 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | 350 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { |
331 | const Proto *const tf = cl->f.l; | 351 | const Proto *const tf = cl->f.l; |
332 | StkId top; /* keep top local, for performance */ | 352 | const Instruction *pc; |
333 | const Instruction *pc = tf->code; | 353 | lua_Hook linehook; |
334 | const lua_Hook linehook = L->linehook; | ||
335 | L->ci->pc = &pc; | ||
336 | if (tf->is_vararg) /* varargs? */ | 354 | if (tf->is_vararg) /* varargs? */ |
337 | adjust_varargs(L, base, tf->numparams); | 355 | adjust_varargs(L, base, tf->numparams); |
338 | luaD_adjusttop(L, base, tf->maxstacksize); | 356 | luaD_adjusttop(L, base, tf->maxstacksize); |
339 | top = base+tf->numparams+tf->is_vararg; | 357 | pc = tf->code; |
358 | L->ci->pc = &pc; | ||
359 | linehook = L->linehook; | ||
340 | /* main loop of interpreter */ | 360 | /* main loop of interpreter */ |
341 | for (;;) { | 361 | for (;;) { |
342 | const Instruction i = *pc++; | 362 | const Instruction i = *pc++; |
343 | lua_assert(L->top == base+tf->maxstacksize); | ||
344 | if (linehook) | 363 | if (linehook) |
345 | traceexec(L, linehook); | 364 | traceexec(L, linehook); |
346 | switch (GET_OPCODE(i)) { | 365 | switch (GET_OPCODE(i)) { |
347 | case OP_RETURN: { | 366 | case OP_MOVE: { |
348 | L->top = top; | 367 | setobj(RA(i), RB(i)); |
349 | return base+GETARG_U(i); | ||
350 | } | ||
351 | case OP_CALL: { | ||
352 | int nres = GETARG_B(i); | ||
353 | if (nres == MULT_RET) nres = LUA_MULTRET; | ||
354 | L->top = top; | ||
355 | luaD_call(L, base+GETARG_A(i), nres); | ||
356 | top = L->top; | ||
357 | L->top = base+tf->maxstacksize; | ||
358 | break; | ||
359 | } | ||
360 | case OP_PUSHNIL: { | ||
361 | int n = GETARG_U(i); | ||
362 | lua_assert(n>0); | ||
363 | do { | ||
364 | setnilvalue(top++); | ||
365 | } while (--n > 0); | ||
366 | break; | ||
367 | } | ||
368 | case OP_POP: { | ||
369 | top -= GETARG_U(i); | ||
370 | break; | ||
371 | } | ||
372 | case OP_PUSHINT: { | ||
373 | setnvalue(top, (lua_Number)GETARG_S(i)); | ||
374 | top++; | ||
375 | break; | ||
376 | } | ||
377 | case OP_PUSHSTRING: { | ||
378 | setsvalue(top, tf->kstr[GETARG_U(i)]); | ||
379 | top++; | ||
380 | break; | 368 | break; |
381 | } | 369 | } |
382 | case OP_PUSHNUM: { | 370 | case OP_LOADK: { |
383 | setnvalue(top, tf->knum[GETARG_U(i)]); | 371 | setobj(RA(i), KBc(i)); |
384 | top++; | ||
385 | break; | 372 | break; |
386 | } | 373 | } |
387 | case OP_PUSHNEGNUM: { | 374 | case OP_LOADINT: { |
388 | setnvalue(top, -tf->knum[GETARG_U(i)]); | 375 | setnvalue(RA(i), (lua_Number)GETARG_sBc(i)); |
389 | top++; | ||
390 | break; | 376 | break; |
391 | } | 377 | } |
392 | case OP_PUSHUPVALUE: { | 378 | case OP_LOADUPVAL: { |
393 | setobj(top++, &cl->upvalue[GETARG_U(i)]); | 379 | setobj(RA(i), cl->upvalue+GETARG_Bc(i)); |
394 | break; | 380 | break; |
395 | } | 381 | } |
396 | case OP_GETLOCAL: { | 382 | case OP_LOADNIL: { |
397 | setobj(top++, base+GETARG_U(i)); | 383 | TObject *ra = RA(i); |
384 | TObject *rb = RB(i); | ||
385 | do { | ||
386 | setnilvalue(ra++); | ||
387 | } while (ra <= rb); | ||
398 | break; | 388 | break; |
399 | } | 389 | } |
400 | case OP_GETGLOBAL: { | 390 | case OP_GETGLOBAL: { |
401 | luaV_getglobal(L, tf->kstr[GETARG_U(i)], top); | 391 | lua_assert(ttype(KBc(i)) == LUA_TSTRING); |
402 | top++; | 392 | luaV_getglobal(L, tsvalue(KBc(i)), RA(i)); |
403 | break; | 393 | break; |
404 | } | 394 | } |
405 | case OP_GETTABLE: { | 395 | case OP_GETTABLE: { |
406 | top--; | 396 | luaV_gettable(L, RB(i), RKC(i), RA(i)); |
407 | luaV_gettable(L, top-1, top, top-1); | ||
408 | break; | ||
409 | } | ||
410 | case OP_GETDOTTED: { | ||
411 | setsvalue(top, tf->kstr[GETARG_U(i)]); | ||
412 | luaV_gettable(L, top-1, top, top-1); | ||
413 | break; | ||
414 | } | ||
415 | case OP_GETINDEXED: { | ||
416 | luaV_gettable(L, top-1, base+GETARG_U(i), top-1); | ||
417 | break; | ||
418 | } | ||
419 | case OP_PUSHSELF: { | ||
420 | setobj(top, top-1); | ||
421 | setsvalue(top+1, tf->kstr[GETARG_U(i)]); | ||
422 | luaV_gettable(L, top-1, top+1, top-1); | ||
423 | top++; | ||
424 | break; | ||
425 | } | ||
426 | case OP_CREATETABLE: { | ||
427 | luaC_checkGC(L); | ||
428 | sethvalue(top, luaH_new(L, GETARG_U(i))); | ||
429 | top++; | ||
430 | break; | ||
431 | } | ||
432 | case OP_SETLOCAL: { | ||
433 | setobj(base+GETARG_U(i), --top); | ||
434 | break; | 397 | break; |
435 | } | 398 | } |
436 | case OP_SETGLOBAL: { | 399 | case OP_SETGLOBAL: { |
437 | top--; | 400 | lua_assert(ttype(KBc(i)) == LUA_TSTRING); |
438 | luaV_setglobal(L, tf->kstr[GETARG_U(i)], top); | 401 | luaV_setglobal(L, tsvalue(KBc(i)), RA(i)); |
439 | break; | 402 | break; |
440 | } | 403 | } |
441 | case OP_SETTABLE: { | 404 | case OP_SETTABLE: { |
442 | StkId t = top-GETARG_A(i); | 405 | luaV_settable(L, RB(i), RKC(i), RA(i)); |
443 | luaV_settable(L, t, t+1, top-1); | ||
444 | top -= GETARG_B(i); /* pop values */ | ||
445 | break; | 406 | break; |
446 | } | 407 | } |
447 | case OP_SETLIST: { | 408 | case OP_NEWTABLE: { |
448 | int aux = GETARG_A(i) * LFIELDS_PER_FLUSH; | 409 | luaC_checkGC(L); |
449 | TObject *t = base+GETARG_B(i); | 410 | sethvalue(RA(i), luaH_new(L, GETARG_Bc(i))); |
450 | Hash *h = hvalue(t); | ||
451 | int n; | ||
452 | for (n = top-t-1; n; n--) | ||
453 | setobj(luaH_setnum(L, h, n+aux), --top); | ||
454 | break; | 411 | break; |
455 | } | 412 | } |
456 | case OP_SETMAP: { | 413 | case OP_SELF: { |
457 | TObject *t = base+GETARG_U(i); | 414 | StkId ra = RA(i); |
458 | Hash *h = hvalue(t); | 415 | StkId rb = RB(i); |
459 | while (top-1 > t) { | 416 | setobj(ra+1, rb); |
460 | top-=2; | 417 | luaV_gettable(L, rb, RKC(i), ra); |
461 | setobj(luaH_set(L, h, top), top+1); | ||
462 | } | ||
463 | break; | 418 | break; |
464 | } | 419 | } |
465 | case OP_ADD: { | 420 | case OP_ADD: { |
466 | if (tonumber(top-2) || tonumber(top-1)) | 421 | Arith( + , TM_ADD); |
467 | call_arith(L, top-2, TM_ADD); | ||
468 | else | ||
469 | nvalue(top-2) += nvalue(top-1); | ||
470 | top--; | ||
471 | break; | ||
472 | } | ||
473 | case OP_ADDI: { | ||
474 | if (tonumber(top-1)) { | ||
475 | setnvalue(top, (lua_Number)GETARG_S(i)); | ||
476 | call_arith(L, top-1, TM_ADD); | ||
477 | } | ||
478 | else | ||
479 | nvalue(top-1) += (lua_Number)GETARG_S(i); | ||
480 | break; | 422 | break; |
481 | } | 423 | } |
482 | case OP_SUB: { | 424 | case OP_SUB: { |
483 | if (tonumber(top-2) || tonumber(top-1)) | 425 | Arith( - , TM_SUB); |
484 | call_arith(L, top-2, TM_SUB); | ||
485 | else | ||
486 | nvalue(top-2) -= nvalue(top-1); | ||
487 | top--; | ||
488 | break; | 426 | break; |
489 | } | 427 | } |
490 | case OP_MULT: { | 428 | case OP_MUL: { |
491 | if (tonumber(top-2) || tonumber(top-1)) | 429 | Arith( * , TM_MUL); |
492 | call_arith(L, top-2, TM_MUL); | ||
493 | else | ||
494 | nvalue(top-2) *= nvalue(top-1); | ||
495 | top--; | ||
496 | break; | 430 | break; |
497 | } | 431 | } |
498 | case OP_DIV: { | 432 | case OP_DIV: { |
499 | if (tonumber(top-2) || tonumber(top-1)) | 433 | Arith( / , TM_DIV); |
500 | call_arith(L, top-2, TM_DIV); | ||
501 | else | ||
502 | nvalue(top-2) /= nvalue(top-1); | ||
503 | top--; | ||
504 | break; | 434 | break; |
505 | } | 435 | } |
506 | case OP_POW: { | 436 | case OP_POW: { |
507 | if (!call_binTM(L, top-2, top-1, top-2, TM_POW)) | 437 | call_arith(L, RB(i), RKC(i), RA(i), TM_POW); |
508 | luaD_error(L, l_s("undefined operation")); | ||
509 | top--; | ||
510 | break; | 438 | break; |
511 | } | 439 | } |
512 | case OP_CONCAT: { | 440 | case OP_UNM: { |
513 | int n = GETARG_U(i); | 441 | const TObject *rb = RB(i); |
514 | luaV_strconc(L, n, top); | 442 | StkId ra = RA(i); |
515 | top -= n-1; | 443 | if (ttype(rb) == LUA_TNUMBER || (rb=luaV_tonumber(rb, ra)) != NULL) { |
516 | luaC_checkGC(L); | 444 | setnvalue(ra, -nvalue(rb)); |
517 | break; | 445 | } |
518 | } | 446 | else { |
519 | case OP_MINUS: { | 447 | TObject temp; |
520 | if (tonumber(top-1)) { | 448 | setnilvalue(&temp); |
521 | setnilvalue(top); | 449 | call_arith(L, RB(i), &temp, ra, TM_UNM); |
522 | call_arith(L, top-1, TM_UNM); | ||
523 | } | 450 | } |
524 | else | ||
525 | nvalue(top-1) = -nvalue(top-1); | ||
526 | break; | 451 | break; |
527 | } | 452 | } |
528 | case OP_NOT: { | 453 | case OP_NOT: { |
529 | ttype(top-1) = | 454 | if (ttype(RB(i)) == LUA_TNIL) { |
530 | (ttype(top-1) == LUA_TNIL) ? LUA_TNUMBER : LUA_TNIL; | 455 | setnvalue(RA(i), 1); |
531 | nvalue(top-1) = 1; | 456 | } else { |
457 | setnilvalue(RA(i)); | ||
458 | } | ||
532 | break; | 459 | break; |
533 | } | 460 | } |
534 | case OP_JMPNE: { | 461 | case OP_CONCAT: { |
535 | top -= 2; | 462 | StkId top = RC(i)+1; |
536 | if (!luaO_equalObj(top, top+1)) dojump(pc, i); | 463 | StkId rb = RB(i); |
464 | luaV_strconc(L, top-rb, top); | ||
465 | setobj(RA(i), rb); | ||
466 | luaC_checkGC(L); | ||
537 | break; | 467 | break; |
538 | } | 468 | } |
539 | case OP_JMPEQ: { | 469 | case OP_CJMP: |
540 | top -= 2; | 470 | case OP_JMP: { |
541 | if (luaO_equalObj(top, top+1)) dojump(pc, i); | 471 | dojump(pc, i); |
542 | break; | 472 | break; |
543 | } | 473 | } |
544 | case OP_JMPLT: { | 474 | case OP_TESTEQ: { |
545 | top -= 2; | 475 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
546 | if (luaV_lessthan(L, top, top+1)) dojump(pc, i); | 476 | if (luaO_equalObj(RB(i), RKC(i))) dojump(pc, *pc); |
477 | pc++; | ||
547 | break; | 478 | break; |
548 | } | 479 | } |
549 | case OP_JMPLE: { /* a <= b === !(b<a) */ | 480 | case OP_TESTNE: { |
550 | top -= 2; | 481 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
551 | if (!luaV_lessthan(L, top+1, top)) dojump(pc, i); | 482 | if (!luaO_equalObj(RB(i), RKC(i))) dojump(pc, *pc); |
483 | pc++; | ||
552 | break; | 484 | break; |
553 | } | 485 | } |
554 | case OP_JMPGT: { /* a > b === (b<a) */ | 486 | case OP_TESTLT: { |
555 | top -= 2; | 487 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
556 | if (luaV_lessthan(L, top+1, top)) dojump(pc, i); | 488 | if (luaV_lessthan(L, RB(i), RKC(i))) dojump(pc, *pc); |
489 | pc++; | ||
557 | break; | 490 | break; |
558 | } | 491 | } |
559 | case OP_JMPGE: { /* a >= b === !(a<b) */ | 492 | case OP_TESTLE: { /* b <= c === !(c<b) */ |
560 | top -= 2; | 493 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
561 | if (!luaV_lessthan(L, top, top+1)) dojump(pc, i); | 494 | if (!luaV_lessthan(L, RKC(i), RB(i))) dojump(pc, *pc); |
495 | pc++; | ||
562 | break; | 496 | break; |
563 | } | 497 | } |
564 | case OP_JMPT: { | 498 | case OP_TESTGT: { /* b > c === (c<b) */ |
565 | if (ttype(--top) != LUA_TNIL) dojump(pc, i); | 499 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
500 | if (luaV_lessthan(L, RKC(i), RB(i))) dojump(pc, *pc); | ||
501 | pc++; | ||
566 | break; | 502 | break; |
567 | } | 503 | } |
568 | case OP_JMPF: { | 504 | case OP_TESTGE: { /* b >= c === !(b<c) */ |
569 | if (ttype(--top) == LUA_TNIL) dojump(pc, i); | 505 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
506 | if (!luaV_lessthan(L, RB(i), RKC(i))) dojump(pc, *pc); | ||
507 | pc++; | ||
570 | break; | 508 | break; |
571 | } | 509 | } |
572 | case OP_JMPONT: { | 510 | case OP_TESTT: { |
573 | if (ttype(top-1) == LUA_TNIL) top--; | 511 | StkId rb = RB(i); |
574 | else dojump(pc, i); | 512 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
513 | if (ttype(rb) != LUA_TNIL) { | ||
514 | int a = GETARG_A(i); | ||
515 | if (a != NO_REG) setobj(base+a, rb); | ||
516 | dojump(pc, *pc); | ||
517 | } | ||
518 | pc++; | ||
575 | break; | 519 | break; |
576 | } | 520 | } |
577 | case OP_JMPONF: { | 521 | case OP_TESTF: { |
578 | if (ttype(top-1) != LUA_TNIL) top--; | 522 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
579 | else dojump(pc, i); | 523 | if (ttype(RB(i)) == LUA_TNIL) { |
524 | int a = GETARG_A(i); | ||
525 | if (a != NO_REG) setnilvalue(base+a); | ||
526 | dojump(pc, *pc); | ||
527 | } | ||
528 | pc++; | ||
580 | break; | 529 | break; |
581 | } | 530 | } |
582 | case OP_JMP: { | 531 | case OP_NILJMP: { |
583 | dojump(pc, i); | 532 | setnilvalue(RA(i)); |
533 | pc++; | ||
584 | break; | 534 | break; |
585 | } | 535 | } |
586 | case OP_PUSHNILJMP: { | 536 | case OP_CALL: { |
587 | setnilvalue(top++); | 537 | int nres; |
588 | pc++; | 538 | int b = GETARG_B(i); |
539 | if (b != NO_REG) | ||
540 | L->top = base+b; | ||
541 | nres = GETARG_C(i); | ||
542 | if (nres == NO_REG) nres = LUA_MULTRET; | ||
543 | luaD_call(L, RA(i), nres); | ||
544 | if (nres != LUA_MULTRET) { | ||
545 | lua_assert(L->top == RA(i)+nres); | ||
546 | L->top = base+tf->maxstacksize; | ||
547 | } | ||
589 | break; | 548 | break; |
590 | } | 549 | } |
550 | case OP_RETURN: { | ||
551 | int b = GETARG_B(i); | ||
552 | if (b != NO_REG) | ||
553 | L->top = base+b; | ||
554 | return RA(i); | ||
555 | } | ||
591 | case OP_FORPREP: { | 556 | case OP_FORPREP: { |
592 | int jmp = GETARG_S(i); | 557 | int jmp = GETARG_sBc(i); |
593 | if (tonumber(top-1)) | 558 | StkId breg = RA(i); |
594 | luaD_error(L, l_s("`for' step must be a number")); | 559 | if (luaV_tonumber(breg, breg) == NULL) |
595 | if (tonumber(top-2)) | ||
596 | luaD_error(L, l_s("`for' limit must be a number")); | ||
597 | if (tonumber(top-3)) | ||
598 | luaD_error(L, l_s("`for' initial value must be a number")); | 560 | luaD_error(L, l_s("`for' initial value must be a number")); |
561 | if (luaV_tonumber(breg+1, breg+1) == NULL) | ||
562 | luaD_error(L, l_s("`for' limit must be a number")); | ||
563 | if (luaV_tonumber(breg+2, breg+2) == NULL) | ||
564 | luaD_error(L, l_s("`for' step must be a number")); | ||
599 | pc += -jmp; /* `jump' to loop end (delta is negated here) */ | 565 | pc += -jmp; /* `jump' to loop end (delta is negated here) */ |
600 | goto forloop; /* do not increment index */ | 566 | nvalue(breg) -= nvalue(breg+2);/* decrement index (to be incremented) */ |
567 | /* go through */ | ||
601 | } | 568 | } |
602 | case OP_FORLOOP: { | 569 | case OP_FORLOOP: { |
603 | lua_assert(ttype(top-1) == LUA_TNUMBER); | 570 | StkId breg = RA(i); |
604 | lua_assert(ttype(top-2) == LUA_TNUMBER); | 571 | if (ttype(breg) != LUA_TNUMBER) |
605 | if (ttype(top-3) != LUA_TNUMBER) | ||
606 | luaD_error(L, l_s("`for' index must be a number")); | 572 | luaD_error(L, l_s("`for' index must be a number")); |
607 | nvalue(top-3) += nvalue(top-1); /* increment index */ | 573 | runtime_check(L, ttype(breg+1) == LUA_TNUMBER && |
608 | forloop: | 574 | ttype(breg+2) == LUA_TNUMBER); |
609 | if (nvalue(top-1) > 0 ? | 575 | nvalue(breg) += nvalue(breg+2); /* increment index */ |
610 | nvalue(top-3) > nvalue(top-2) : | 576 | if (nvalue(breg+2) > 0 ? |
611 | nvalue(top-3) < nvalue(top-2)) | 577 | nvalue(breg) <= nvalue(breg+1) : |
612 | top -= 3; /* end loop: remove control variables */ | 578 | nvalue(breg) >= nvalue(breg+1)) |
613 | else | ||
614 | dojump(pc, i); /* repeat loop */ | 579 | dojump(pc, i); /* repeat loop */ |
615 | break; | 580 | break; |
616 | } | 581 | } |
617 | case OP_LFORPREP: { | 582 | case OP_TFORPREP: { |
618 | int jmp = GETARG_S(i); | 583 | int jmp = GETARG_sBc(i); |
619 | if (ttype(top-1) != LUA_TTABLE) | 584 | StkId breg = RA(i); |
585 | if (ttype(breg) != LUA_TTABLE) | ||
620 | luaD_error(L, l_s("`for' table must be a table")); | 586 | luaD_error(L, l_s("`for' table must be a table")); |
621 | top += 3; /* index,key,value */ | 587 | setnvalue(breg+1, -1); /* initial index */ |
622 | setnvalue(top-3, -1); /* initial index */ | 588 | setnilvalue(breg+2); |
623 | setnilvalue(top-2); | 589 | setnilvalue(breg+3); |
624 | setnilvalue(top-1); | ||
625 | pc += -jmp; /* `jump' to loop end (delta is negated here) */ | 590 | pc += -jmp; /* `jump' to loop end (delta is negated here) */ |
626 | /* go through */ | 591 | /* go through */ |
627 | } | 592 | } |
628 | case OP_LFORLOOP: { | 593 | case OP_TFORLOOP: { |
629 | Hash *t = hvalue(top-4); | 594 | StkId breg = RA(i); |
630 | int n = (int)nvalue(top-3); | 595 | Hash *t; |
631 | lua_assert(ttype(top-3) == LUA_TNUMBER); | 596 | int n; |
632 | lua_assert(ttype(top-4) == LUA_TTABLE); | 597 | runtime_check(L, ttype(breg) == LUA_TTABLE); |
598 | runtime_check(L, ttype(breg+1) == LUA_TNUMBER); | ||
599 | t = hvalue(breg); | ||
600 | n = (int)nvalue(breg+1); | ||
633 | n = luaH_nexti(t, n); | 601 | n = luaH_nexti(t, n); |
634 | if (n == -1) /* end loop? */ | 602 | if (n != -1) { /* repeat loop? */ |
635 | top -= 4; /* remove table, index, key, and value */ | ||
636 | else { | ||
637 | Node *node = node(t, n); | 603 | Node *node = node(t, n); |
638 | setnvalue(top-3, n); /* index */ | 604 | setnvalue(breg+1, n); /* index */ |
639 | setkey2obj(top-2, node); | 605 | setkey2obj(breg+2, node); |
640 | setobj(top-1, val(node)); | 606 | setobj(breg+3, val(node)); |
641 | dojump(pc, i); /* repeat loop */ | 607 | dojump(pc, i); /* repeat loop */ |
642 | } | 608 | } |
643 | break; | 609 | break; |
644 | } | 610 | } |
611 | case OP_SETLIST: | ||
612 | case OP_SETLISTO: { | ||
613 | int bc; | ||
614 | int n; | ||
615 | Hash *h; | ||
616 | StkId ra = RA(i); | ||
617 | runtime_check(L, ttype(ra) == LUA_TTABLE); | ||
618 | h = hvalue(ra); | ||
619 | bc = GETARG_Bc(i); | ||
620 | if (GET_OPCODE(i) == OP_SETLIST) | ||
621 | n = (bc&(LFIELDS_PER_FLUSH-1)) + 1; | ||
622 | else | ||
623 | n = L->top - ra - 1; | ||
624 | bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */ | ||
625 | for (; n > 0; n--) | ||
626 | setobj(luaH_setnum(L, h, bc+n), ra+n); | ||
627 | break; | ||
628 | } | ||
645 | case OP_CLOSURE: { | 629 | case OP_CLOSURE: { |
646 | int nup = GETARG_B(i); | 630 | Proto *p = tf->kproto[GETARG_Bc(i)]; |
647 | luaC_checkGC(L); | 631 | int nup = p->nupvalues; |
648 | L->top = top; | 632 | StkId ra = RA(i); |
649 | luaV_Lclosure(L, tf->kproto[GETARG_A(i)], nup); | 633 | L->top = ra+nup; |
650 | top -= (nup-1); | 634 | luaV_Lclosure(L, p, nup); |
651 | L->top = base+tf->maxstacksize; | 635 | L->top = base+tf->maxstacksize; |
636 | luaC_checkGC(L); | ||
652 | break; | 637 | break; |
653 | } | 638 | } |
654 | } | 639 | } |
655 | } | 640 | } |
656 | } | 641 | } |
642 | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.h,v 1.28 2001/02/01 16:03:38 roberto Exp roberto $ | 2 | ** $Id: lvm.h,v 1.29 2001/02/07 18:13:49 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -13,14 +13,13 @@ | |||
13 | #include "ltm.h" | 13 | #include "ltm.h" |
14 | 14 | ||
15 | 15 | ||
16 | #define tonumber(o) ((ttype(o) != LUA_TNUMBER) && (luaV_tonumber(o) != 0)) | ||
17 | #define tostring(L,o) ((ttype(o) != LUA_TSTRING) && (luaV_tostring(L, o) != 0)) | 16 | #define tostring(L,o) ((ttype(o) != LUA_TSTRING) && (luaV_tostring(L, o) != 0)) |
18 | 17 | ||
19 | 18 | ||
20 | int luaV_tonumber (TObject *obj); | 19 | const TObject *luaV_tonumber (const TObject *obj, TObject *n); |
21 | int luaV_tostring (lua_State *L, TObject *obj); | 20 | int luaV_tostring (lua_State *L, TObject *obj); |
22 | void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res); | 21 | void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res); |
23 | void luaV_settable (lua_State *L, StkId t, StkId key, StkId val); | 22 | void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val); |
24 | void luaV_getglobal (lua_State *L, TString *s, StkId res); | 23 | void luaV_getglobal (lua_State *L, TString *s, StkId res); |
25 | void luaV_setglobal (lua_State *L, TString *s, StkId val); | 24 | void luaV_setglobal (lua_State *L, TString *s, StkId val); |
26 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base); | 25 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base); |