diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-02-14 14:51:08 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-02-14 14:51:08 -0200 |
commit | 3afe85b2ce9ffdc8eca819ddc1c05414701606fd (patch) | |
tree | 4433002ba359cfb376c61c69c93af9de13e29331 /lparser.c | |
parent | 52aad0ab5937d4df6fe07aedbf9987f2f792698c (diff) | |
download | lua-3afe85b2ce9ffdc8eca819ddc1c05414701606fd.tar.gz lua-3afe85b2ce9ffdc8eca819ddc1c05414701606fd.tar.bz2 lua-3afe85b2ce9ffdc8eca819ddc1c05414701606fd.zip |
new version for INSTRUCTION formats
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 332 |
1 files changed, 122 insertions, 210 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.57 2000/01/28 16:53:00 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.58 2000/02/11 16:52:54 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 | */ |
@@ -20,30 +20,27 @@ | |||
20 | 20 | ||
21 | 21 | ||
22 | 22 | ||
23 | /* size of a "normal" jump instruction: OpCode + 1 byte */ | ||
24 | #define JMPSIZE 2 | ||
25 | |||
26 | /* maximum number of local variables */ | 23 | /* maximum number of local variables */ |
27 | #ifndef MAXLOCALS | 24 | #ifndef MAXLOCALS |
28 | #define MAXLOCALS 200 /* arbitrary limit (<256) */ | 25 | #define MAXLOCALS 200 /* arbitrary limit (<MAXARG_B) */ |
29 | #endif | 26 | #endif |
30 | 27 | ||
31 | 28 | ||
32 | /* maximum number of upvalues */ | 29 | /* maximum number of upvalues */ |
33 | #ifndef MAXUPVALUES | 30 | #ifndef MAXUPVALUES |
34 | #define MAXUPVALUES 32 /* arbitrary limit (<256) */ | 31 | #define MAXUPVALUES 32 /* arbitrary limit (<MAXARG_B) */ |
35 | #endif | 32 | #endif |
36 | 33 | ||
37 | 34 | ||
38 | /* maximum number of variables in the left side of an assignment */ | 35 | /* maximum number of variables in the left side of an assignment */ |
39 | #ifndef MAXVARSLH | 36 | #ifndef MAXVARSLH |
40 | #define MAXVARSLH 100 /* arbitrary limit (<255) */ | 37 | #define MAXVARSLH 100 /* arbitrary limit (<MAXARG_B) */ |
41 | #endif | 38 | #endif |
42 | 39 | ||
43 | 40 | ||
44 | /* maximum number of parameters in a function */ | 41 | /* maximum number of parameters in a function */ |
45 | #ifndef MAXPARAMS | 42 | #ifndef MAXPARAMS |
46 | #define MAXPARAMS 100 /* arbitrary limit (<ZEROVARARG) */ | 43 | #define MAXPARAMS 100 /* arbitrary limit (<MAXLOCALS) */ |
47 | #endif | 44 | #endif |
48 | 45 | ||
49 | 46 | ||
@@ -57,7 +54,7 @@ typedef enum { | |||
57 | VLOCAL, /* info is stack index */ | 54 | VLOCAL, /* info is stack index */ |
58 | VDOT, /* info is constant index of index name */ | 55 | VDOT, /* info is constant index of index name */ |
59 | VINDEXED, /* no info (table and index are on the stack) */ | 56 | VINDEXED, /* no info (table and index are on the stack) */ |
60 | VEXP /* info is pc index of `nparam' of a call (or 0 if exp is closed) */ | 57 | VEXP /* info is pc index of a call (or 0 if exp is closed) */ |
61 | } varkind; | 58 | } varkind; |
62 | 59 | ||
63 | typedef struct vardesc { | 60 | typedef struct vardesc { |
@@ -70,7 +67,7 @@ typedef struct vardesc { | |||
70 | ** Expression List descriptor: | 67 | ** Expression List descriptor: |
71 | ** tells number of expressions in the list, | 68 | ** tells number of expressions in the list, |
72 | ** and, if last expression is open (a function call), | 69 | ** and, if last expression is open (a function call), |
73 | ** where is its pc index of `nparam' | 70 | ** where is the call pc index. |
74 | */ | 71 | */ |
75 | typedef struct listdesc { | 72 | typedef struct listdesc { |
76 | int n; | 73 | int n; |
@@ -96,7 +93,6 @@ typedef struct FuncState { | |||
96 | struct FuncState *prev; /* enclosing function */ | 93 | struct FuncState *prev; /* enclosing function */ |
97 | int pc; /* next position to code */ | 94 | int pc; /* next position to code */ |
98 | int stacksize; /* number of values on activation register */ | 95 | int stacksize; /* number of values on activation register */ |
99 | int maxstacksize; /* maximum number of values on activation register */ | ||
100 | int nlocalvar; /* number of active local variables */ | 96 | int nlocalvar; /* number of active local variables */ |
101 | int nupvalues; /* number of upvalues */ | 97 | int nupvalues; /* number of upvalues */ |
102 | int nvars; /* number of entries in f->locvars (-1 if no debug information) */ | 98 | int nvars; /* number of entries in f->locvars (-1 if no debug information) */ |
@@ -131,89 +127,63 @@ static void checklimit (LexState *ls, int val, int limit, const char *msg) { | |||
131 | } | 127 | } |
132 | 128 | ||
133 | 129 | ||
134 | static void check_pc (LexState *ls, int n) { | 130 | static int code_instruction (LexState *ls, Instruction i) { |
135 | luaM_growvector(ls->L, ls->fs->f->code, ls->fs->pc, n, | 131 | FuncState *fs = ls->fs; |
136 | Byte, codeEM, MAX_INT); | 132 | luaM_growvector(ls->L, fs->f->code, fs->pc, 1, Instruction, codeEM, MAXARG_S); |
133 | fs->f->code[fs->pc] = i; | ||
134 | return fs->pc++; | ||
137 | } | 135 | } |
138 | 136 | ||
139 | 137 | ||
140 | static void code_byte (LexState *ls, Byte c) { | 138 | static void fix_jump (LexState *ls, int pc, int dest) { |
141 | check_pc(ls, 1); | 139 | Instruction *jmp = &ls->fs->f->code[pc]; |
142 | ls->fs->f->code[ls->fs->pc++] = c; | 140 | /* jump is relative to position following jump instruction */ |
141 | *jmp = SETARG_S(*jmp, dest-(pc+1)); | ||
143 | } | 142 | } |
144 | 143 | ||
145 | 144 | ||
146 | static void deltastack (LexState *ls, int delta) { | 145 | static void deltastack (LexState *ls, int delta) { |
147 | FuncState *fs = ls->fs; | 146 | FuncState *fs = ls->fs; |
148 | fs->stacksize += delta; | 147 | fs->stacksize += delta; |
149 | if (fs->stacksize > fs->maxstacksize) { | 148 | if (delta > 0 && fs->stacksize > fs->f->maxstacksize) { |
150 | if (fs->stacksize > MAX_BYTE) | 149 | fs->f->maxstacksize = fs->stacksize; |
151 | luaY_error(ls, "function or expression too complex"); | ||
152 | fs->maxstacksize = fs->stacksize; | ||
153 | } | 150 | } |
154 | } | 151 | } |
155 | 152 | ||
156 | 153 | ||
157 | static void code_oparg_at (LexState *ls, int pc, OpCode op, | 154 | static int aux_code (LexState *ls, OpCode op, Instruction i, int delta) { |
158 | int arg, int delta) { | ||
159 | Byte *code = ls->fs->f->code; | ||
160 | deltastack(ls, delta); | 155 | deltastack(ls, delta); |
161 | if (arg <= MAX_BYTE) { | 156 | return code_instruction(ls, SET_OPCODE(i, op)); |
162 | code[pc] = (Byte)op; | ||
163 | code[pc+1] = (Byte)arg; | ||
164 | } | ||
165 | else if (arg > MAX_ARG) | ||
166 | luaY_error(ls, "code too long"); | ||
167 | else { /* MAX_BYTE < arg < MAX_ARG */ | ||
168 | if (arg > MAX_WORD) { | ||
169 | code[pc] = (Byte)LONGARG; | ||
170 | code[pc+1] = (Byte)(arg>>16); | ||
171 | pc += 2; | ||
172 | } | ||
173 | code[pc] = (Byte)(op-1); /* opcode for word argument */ | ||
174 | code[pc+1] = (Byte)((arg&0xFFFF)>>8); | ||
175 | code[pc+2] = (Byte)(arg&0xFF); | ||
176 | } | ||
177 | } | 157 | } |
178 | 158 | ||
179 | 159 | ||
180 | static int codesize (int arg) { | 160 | static int code_0 (LexState *ls, OpCode op, int delta) { |
181 | if (arg <= MAX_BYTE) return 2; /* opcode + 1 byte */ | 161 | return aux_code(ls, op, 0, delta); |
182 | else if (arg <= MAX_WORD) return 3; /* opcode + 1 word (2 bytes) */ | ||
183 | else return 5; /* LONGARG + 1 byte + opcode + 1 word (2 bytes) */ | ||
184 | } | 162 | } |
185 | 163 | ||
186 | 164 | ||
187 | static int fix_opcode (LexState *ls, int pc, OpCode op, int arg) { | 165 | |
188 | int tomove = codesize(arg)-2; | 166 | static int code_U (LexState *ls, OpCode op, int u, int delta) { |
189 | if (tomove > 0) { /* need to open space? */ | 167 | Instruction i = SETARG_U(0, u); |
190 | FuncState *fs = ls->fs; | 168 | return aux_code(ls, op, i, delta); |
191 | TProtoFunc *f = fs->f; | ||
192 | check_pc(ls, tomove); | ||
193 | luaO_memup(f->code+pc+tomove, f->code+pc, fs->pc-pc); | ||
194 | fs->pc += tomove; | ||
195 | } | ||
196 | code_oparg_at(ls, pc, op, arg, 0); | ||
197 | return tomove; | ||
198 | } | 169 | } |
199 | 170 | ||
200 | 171 | ||
201 | static void code_oparg (LexState *ls, OpCode op, int arg, int delta) { | 172 | static int code_S (LexState *ls, OpCode op, int s, int delta) { |
202 | int size = codesize(arg); | 173 | Instruction i = SETARG_S(0, s); |
203 | check_pc(ls, size); | 174 | return aux_code(ls, op, i, delta); |
204 | code_oparg_at(ls, ls->fs->pc, op, arg, delta); | ||
205 | ls->fs->pc += size; | ||
206 | } | 175 | } |
207 | 176 | ||
208 | 177 | ||
209 | static void code_opcode (LexState *ls, OpCode op, int delta) { | 178 | static int code_AB (LexState *ls, OpCode op, int a, int b, int delta) { |
210 | deltastack(ls, delta); | 179 | Instruction i = SETARG_A(0, a); |
211 | code_byte(ls, (Byte)op); | 180 | i = SETARG_B(i, b); |
181 | return aux_code(ls, op, i, delta); | ||
212 | } | 182 | } |
213 | 183 | ||
214 | 184 | ||
215 | static void code_kstr (LexState *ls, int c) { | 185 | static void code_kstr (LexState *ls, int c) { |
216 | code_oparg(ls, PUSHSTRING, c, 1); | 186 | code_U(ls, PUSHSTRING, c, 1); |
217 | } | 187 | } |
218 | 188 | ||
219 | 189 | ||
@@ -226,8 +196,8 @@ static int string_constant (LexState *ls, FuncState *fs, TaggedString *s) { | |||
226 | TProtoFunc *f = fs->f; | 196 | TProtoFunc *f = fs->f; |
227 | int c = s->constindex; | 197 | int c = s->constindex; |
228 | if (c >= f->nkstr || f->kstr[c] != s) { | 198 | if (c >= f->nkstr || f->kstr[c] != s) { |
229 | luaM_growvector(ls->L, f->kstr, f->nkstr, 1, | 199 | luaM_growvector(ls->L, f->kstr, f->nkstr, 1, TaggedString *, |
230 | TaggedString *, constantEM, MAX_ARG); | 200 | constantEM, MAXARG_U); |
231 | c = f->nkstr++; | 201 | c = f->nkstr++; |
232 | f->kstr[c] = s; | 202 | f->kstr[c] = s; |
233 | s->constindex = c; /* hint for next time */ | 203 | s->constindex = c; /* hint for next time */ |
@@ -250,8 +220,7 @@ static int real_constant (LexState *ls, real r) { | |||
250 | while (--c >= lim) | 220 | while (--c >= lim) |
251 | if (f->knum[c] == r) return c; | 221 | if (f->knum[c] == r) return c; |
252 | /* not found; create a new entry */ | 222 | /* not found; create a new entry */ |
253 | luaM_growvector(ls->L, f->knum, f->nknum, 1, | 223 | luaM_growvector(ls->L, f->knum, f->nknum, 1, real, constantEM, MAXARG_U); |
254 | real, constantEM, MAX_ARG); | ||
255 | c = f->nknum++; | 224 | c = f->nknum++; |
256 | f->knum[c] = r; | 225 | f->knum[c] = r; |
257 | return c; | 226 | return c; |
@@ -259,27 +228,10 @@ static int real_constant (LexState *ls, real r) { | |||
259 | 228 | ||
260 | 229 | ||
261 | static void code_number (LexState *ls, real f) { | 230 | static void code_number (LexState *ls, real f) { |
262 | real af = (f<0) ? -f : f; | 231 | if ((real)(-MAXARG_S) <= f && f <= (real)MAXARG_S && (int)f == f) |
263 | if (0 <= af && af <= (real)MAX_WORD && (int)af == af) { | 232 | code_S(ls, PUSHINT, (int)f, 1); /* f has a short integer value */ |
264 | /* abs(f) has a short integer value */ | ||
265 | code_oparg(ls, (f<0) ? PUSHINTNEG : PUSHINT, (int)af, 1); | ||
266 | } | ||
267 | else | 233 | else |
268 | code_oparg(ls, PUSHNUMBER, real_constant(ls, f), 1); | 234 | code_U(ls, PUSHNUMBER, real_constant(ls, f), 1); |
269 | } | ||
270 | |||
271 | |||
272 | static void flush_record (LexState *ls, int n) { | ||
273 | if (n > 0) | ||
274 | code_oparg(ls, SETMAP, n-1, -2*n); | ||
275 | } | ||
276 | |||
277 | |||
278 | static void flush_list (LexState *ls, int m, int n) { | ||
279 | if (n > 0) { | ||
280 | code_oparg(ls, SETLIST, m, -n); | ||
281 | code_byte(ls, (Byte)n); | ||
282 | } | ||
283 | } | 235 | } |
284 | 236 | ||
285 | 237 | ||
@@ -371,14 +323,14 @@ static void pushupvalue (LexState *ls, TaggedString *n) { | |||
371 | luaX_syntaxerror(ls, "cannot access upvalue in main", n->str); | 323 | luaX_syntaxerror(ls, "cannot access upvalue in main", n->str); |
372 | if (aux_localname(ls->fs, n) >= 0) | 324 | if (aux_localname(ls->fs, n) >= 0) |
373 | luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str); | 325 | luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str); |
374 | code_oparg(ls, PUSHUPVALUE, indexupvalue(ls, n), 1); | 326 | code_U(ls, PUSHUPVALUE, indexupvalue(ls, n), 1); |
375 | } | 327 | } |
376 | 328 | ||
377 | 329 | ||
378 | 330 | ||
379 | static void check_debugline (LexState *ls) { | 331 | static void check_debugline (LexState *ls) { |
380 | if (ls->L->debug && ls->linenumber != ls->fs->lastsetline) { | 332 | if (ls->L->debug && ls->linenumber != ls->fs->lastsetline) { |
381 | code_oparg(ls, SETLINE, ls->linenumber, 0); | 333 | code_U(ls, SETLINE, ls->linenumber, 0); |
382 | ls->fs->lastsetline = ls->linenumber; | 334 | ls->fs->lastsetline = ls->linenumber; |
383 | } | 335 | } |
384 | } | 336 | } |
@@ -386,16 +338,16 @@ static void check_debugline (LexState *ls) { | |||
386 | 338 | ||
387 | static void adjuststack (LexState *ls, int n) { | 339 | static void adjuststack (LexState *ls, int n) { |
388 | if (n > 0) | 340 | if (n > 0) |
389 | code_oparg(ls, POP, n, -n); | 341 | code_U(ls, POP, n, -n); |
390 | else if (n < 0) | 342 | else if (n < 0) |
391 | code_oparg(ls, PUSHNIL, (-n)-1, -n); | 343 | code_U(ls, PUSHNIL, (-n)-1, -n); |
392 | } | 344 | } |
393 | 345 | ||
394 | 346 | ||
395 | static void close_exp (LexState *ls, int pc, int nresults) { | 347 | static void close_exp (LexState *ls, int pc, int nresults) { |
396 | if (pc > 0) { /* expression is an open function call? */ | 348 | if (pc > 0) { /* expression is an open function call? */ |
397 | Byte *code = ls->fs->f->code; | 349 | Instruction *i = &ls->fs->f->code[pc]; |
398 | code[pc-1] = (Byte)nresults; /* set nresults */ | 350 | *i = SETARG_B(*i, nresults); /* set nresults */ |
399 | if (nresults != MULT_RET) | 351 | if (nresults != MULT_RET) |
400 | deltastack(ls, nresults); /* push results */ | 352 | deltastack(ls, nresults); /* push results */ |
401 | } | 353 | } |
@@ -426,13 +378,12 @@ static void code_args (LexState *ls, int nparams, int dots) { | |||
426 | FuncState *fs = ls->fs; | 378 | FuncState *fs = ls->fs; |
427 | adjustlocalvars(ls, nparams, 0); | 379 | adjustlocalvars(ls, nparams, 0); |
428 | checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters"); | 380 | checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters"); |
429 | nparams = fs->nlocalvar; | 381 | nparams = fs->nlocalvar; /* `self' could be there already */ |
430 | if (!dots) { | 382 | fs->f->numparams = nparams; |
431 | fs->f->code[1] = (Byte)nparams; /* fill-in arg information */ | 383 | fs->f->is_vararg = dots; |
384 | if (!dots) | ||
432 | deltastack(ls, nparams); | 385 | deltastack(ls, nparams); |
433 | } | ||
434 | else { | 386 | else { |
435 | fs->f->code[1] = (Byte)(nparams+ZEROVARARG); | ||
436 | deltastack(ls, nparams+1); | 387 | deltastack(ls, nparams+1); |
437 | add_localvar(ls, luaS_newfixed(ls->L, "arg")); | 388 | add_localvar(ls, luaS_newfixed(ls->L, "arg")); |
438 | } | 389 | } |
@@ -451,17 +402,17 @@ static void unloaddot (LexState *ls, vardesc *v) { | |||
451 | static void lua_pushvar (LexState *ls, vardesc *var) { | 402 | static void lua_pushvar (LexState *ls, vardesc *var) { |
452 | switch (var->k) { | 403 | switch (var->k) { |
453 | case VLOCAL: | 404 | case VLOCAL: |
454 | code_oparg(ls, PUSHLOCAL, var->info, 1); | 405 | code_U(ls, PUSHLOCAL, var->info, 1); |
455 | break; | 406 | break; |
456 | case VGLOBAL: | 407 | case VGLOBAL: |
457 | code_oparg(ls, GETGLOBAL, var->info, 1); | 408 | code_U(ls, GETGLOBAL, var->info, 1); |
458 | assertglobal(ls, var->info); /* make sure that there is a global */ | 409 | assertglobal(ls, var->info); /* make sure that there is a global */ |
459 | break; | 410 | break; |
460 | case VDOT: | 411 | case VDOT: |
461 | code_oparg(ls, GETDOTTED, var->info, 0); | 412 | code_U(ls, GETDOTTED, var->info, 0); |
462 | break; | 413 | break; |
463 | case VINDEXED: | 414 | case VINDEXED: |
464 | code_opcode(ls, GETTABLE, -1); | 415 | code_0(ls, GETTABLE, -1); |
465 | break; | 416 | break; |
466 | case VEXP: | 417 | case VEXP: |
467 | close_exp(ls, var->info, 1); /* function must return 1 value */ | 418 | close_exp(ls, var->info, 1); /* function must return 1 value */ |
@@ -475,14 +426,14 @@ static void lua_pushvar (LexState *ls, vardesc *var) { | |||
475 | static void storevar (LexState *ls, const vardesc *var) { | 426 | static void storevar (LexState *ls, const vardesc *var) { |
476 | switch (var->k) { | 427 | switch (var->k) { |
477 | case VLOCAL: | 428 | case VLOCAL: |
478 | code_oparg(ls, SETLOCAL, var->info, -1); | 429 | code_U(ls, SETLOCAL, var->info, -1); |
479 | break; | 430 | break; |
480 | case VGLOBAL: | 431 | case VGLOBAL: |
481 | code_oparg(ls, SETGLOBAL, var->info, -1); | 432 | code_U(ls, SETGLOBAL, var->info, -1); |
482 | assertglobal(ls, var->info); /* make sure that there is a global */ | 433 | assertglobal(ls, var->info); /* make sure that there is a global */ |
483 | break; | 434 | break; |
484 | case VINDEXED: | 435 | case VINDEXED: |
485 | code_opcode(ls, SETTABLEPOP, -3); | 436 | code_0(ls, SETTABLEPOP, -3); |
486 | break; | 437 | break; |
487 | default: | 438 | default: |
488 | LUA_INTERNALERROR(ls->L, "invalid var kind to store"); | 439 | LUA_INTERNALERROR(ls->L, "invalid var kind to store"); |
@@ -490,43 +441,16 @@ static void storevar (LexState *ls, const vardesc *var) { | |||
490 | } | 441 | } |
491 | 442 | ||
492 | 443 | ||
493 | static int fix_jump (LexState *ls, int pc, OpCode op, int n) { | ||
494 | /* jump is relative to position following jump instruction */ | ||
495 | return fix_opcode(ls, pc, op, n-(pc+JMPSIZE)); | ||
496 | } | ||
497 | |||
498 | |||
499 | static void fix_upjmp (LexState *ls, OpCode op, int pos) { | ||
500 | int delta = ls->fs->pc+JMPSIZE - pos; /* jump is relative */ | ||
501 | code_oparg(ls, op, delta+(codesize(delta)-2), 0); | ||
502 | } | ||
503 | |||
504 | |||
505 | static void codeIf (LexState *ls, int thenAdd, int elseAdd) { | ||
506 | FuncState *fs = ls->fs; | ||
507 | int elseinit = elseAdd+JMPSIZE; | ||
508 | if (fs->pc == elseinit) { /* no else part? */ | ||
509 | fs->pc -= JMPSIZE; | ||
510 | elseinit = fs->pc; | ||
511 | } | ||
512 | else | ||
513 | elseinit += fix_jump(ls, elseAdd, JMP, fs->pc); | ||
514 | fix_jump(ls, thenAdd, IFFJMP, elseinit); | ||
515 | } | ||
516 | |||
517 | |||
518 | static void func_onstack (LexState *ls, FuncState *func) { | 444 | static void func_onstack (LexState *ls, FuncState *func) { |
519 | FuncState *fs = ls->fs; | 445 | TProtoFunc *f = ls->fs->f; |
520 | TProtoFunc *f = fs->f; | ||
521 | int i; | 446 | int i; |
522 | luaM_growvector(ls->L, f->kproto, f->nkproto, 1, | ||
523 | TProtoFunc *, constantEM, MAX_ARG); | ||
524 | f->kproto[f->nkproto] = func->f; | ||
525 | for (i=0; i<func->nupvalues; i++) | 447 | for (i=0; i<func->nupvalues; i++) |
526 | lua_pushvar(ls, &func->upvalues[i]); | 448 | lua_pushvar(ls, &func->upvalues[i]); |
449 | luaM_growvector(ls->L, f->kproto, f->nkproto, 1, TProtoFunc *, | ||
450 | constantEM, MAXARG_A); | ||
451 | f->kproto[f->nkproto++] = func->f; | ||
527 | deltastack(ls, 1); /* CLOSURE puts one extra element (before popping) */ | 452 | deltastack(ls, 1); /* CLOSURE puts one extra element (before popping) */ |
528 | code_oparg(ls, CLOSURE, f->nkproto++, -func->nupvalues); | 453 | code_AB(ls, CLOSURE, f->nkproto-1, func->nupvalues, -func->nupvalues); |
529 | code_byte(ls, (Byte)func->nupvalues); | ||
530 | } | 454 | } |
531 | 455 | ||
532 | 456 | ||
@@ -536,7 +460,6 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) { | |||
536 | fs->prev = ls->fs; /* linked list of funcstates */ | 460 | fs->prev = ls->fs; /* linked list of funcstates */ |
537 | ls->fs = fs; | 461 | ls->fs = fs; |
538 | fs->stacksize = 0; | 462 | fs->stacksize = 0; |
539 | fs->maxstacksize = 0; | ||
540 | fs->nlocalvar = 0; | 463 | fs->nlocalvar = 0; |
541 | fs->nupvalues = 0; | 464 | fs->nupvalues = 0; |
542 | fs->lastsetline = 0; | 465 | fs->lastsetline = 0; |
@@ -544,9 +467,10 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) { | |||
544 | f->source = source; | 467 | f->source = source; |
545 | fs->pc = 0; | 468 | fs->pc = 0; |
546 | f->code = NULL; | 469 | f->code = NULL; |
470 | f->maxstacksize = 0; | ||
471 | f->numparams = 0; /* default for main chunk */ | ||
472 | f->is_vararg = 0; /* default for main chunk */ | ||
547 | fs->nvars = (L->debug) ? 0 : -1; /* flag no debug information? */ | 473 | fs->nvars = (L->debug) ? 0 : -1; /* flag no debug information? */ |
548 | code_byte(ls, 0); /* to be filled with maxstacksize */ | ||
549 | code_byte(ls, 0); /* to be filled with arg information */ | ||
550 | /* push function (to avoid GC) */ | 474 | /* push function (to avoid GC) */ |
551 | tfvalue(L->top) = f; | 475 | tfvalue(L->top) = f; |
552 | ttype(L->top) = LUA_T_LPROTO; | 476 | ttype(L->top) = LUA_T_LPROTO; |
@@ -557,9 +481,8 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) { | |||
557 | static void close_func (LexState *ls) { | 481 | static void close_func (LexState *ls) { |
558 | FuncState *fs = ls->fs; | 482 | FuncState *fs = ls->fs; |
559 | TProtoFunc *f = fs->f; | 483 | TProtoFunc *f = fs->f; |
560 | code_opcode(ls, ENDCODE, 0); | 484 | code_0(ls, ENDCODE, 0); |
561 | f->code[0] = (Byte)fs->maxstacksize; | 485 | luaM_reallocvector(ls->L, f->code, fs->pc, Instruction); |
562 | luaM_reallocvector(ls->L, f->code, fs->pc, Byte); | ||
563 | luaM_reallocvector(ls->L, f->kstr, f->nkstr, TaggedString *); | 486 | luaM_reallocvector(ls->L, f->kstr, f->nkstr, TaggedString *); |
564 | luaM_reallocvector(ls->L, f->knum, f->nknum, real); | 487 | luaM_reallocvector(ls->L, f->knum, f->nknum, real); |
565 | luaM_reallocvector(ls->L, f->kproto, f->nkproto, TProtoFunc *); | 488 | luaM_reallocvector(ls->L, f->kproto, f->nkproto, TProtoFunc *); |
@@ -662,28 +585,6 @@ TProtoFunc *luaY_parser (lua_State *L, ZIO *z) { | |||
662 | /*============================================================*/ | 585 | /*============================================================*/ |
663 | 586 | ||
664 | 587 | ||
665 | |||
666 | static int SaveWord (LexState *ls) { | ||
667 | int res = ls->fs->pc; | ||
668 | check_pc(ls, JMPSIZE); | ||
669 | ls->fs->pc += JMPSIZE; /* open space */ | ||
670 | return res; | ||
671 | } | ||
672 | |||
673 | |||
674 | static int SaveWordPop (LexState *ls) { | ||
675 | deltastack(ls, -1); /* pop condition */ | ||
676 | return SaveWord(ls); | ||
677 | } | ||
678 | |||
679 | |||
680 | static int cond (LexState *ls) { | ||
681 | /* cond -> exp1 */ | ||
682 | exp1(ls); | ||
683 | return SaveWordPop(ls); | ||
684 | } | ||
685 | |||
686 | |||
687 | static void explist1 (LexState *ls, listdesc *d) { | 588 | static void explist1 (LexState *ls, listdesc *d) { |
688 | vardesc v; | 589 | vardesc v; |
689 | expr(ls, &v); | 590 | expr(ls, &v); |
@@ -744,11 +645,8 @@ static int funcparams (LexState *ls, int slf) { | |||
744 | luaY_error(ls, "function arguments expected"); | 645 | luaY_error(ls, "function arguments expected"); |
745 | break; | 646 | break; |
746 | } | 647 | } |
747 | code_byte(ls, CALL); | ||
748 | code_byte(ls, 0); /* save space for nresult */ | ||
749 | code_byte(ls, (Byte)slevel); | ||
750 | fs->stacksize = slevel; /* call will remove func and params */ | 648 | fs->stacksize = slevel; /* call will remove func and params */ |
751 | return fs->pc-1; | 649 | return code_AB(ls, CALL, slevel, 0, 0); |
752 | } | 650 | } |
753 | 651 | ||
754 | 652 | ||
@@ -775,7 +673,7 @@ static void var_or_func_tail (LexState *ls, vardesc *v) { | |||
775 | next(ls); | 673 | next(ls); |
776 | name = checkname(ls); | 674 | name = checkname(ls); |
777 | lua_pushvar(ls, v); /* `v' must be on stack */ | 675 | lua_pushvar(ls, v); /* `v' must be on stack */ |
778 | code_oparg(ls, PUSHSELF, name, 1); | 676 | code_U(ls, PUSHSELF, name, 1); |
779 | v->k = VEXP; | 677 | v->k = VEXP; |
780 | v->info = funcparams(ls, 1); | 678 | v->info = funcparams(ls, 1); |
781 | break; | 679 | break; |
@@ -836,16 +734,20 @@ static void recfield (LexState *ls) { | |||
836 | static int recfields (LexState *ls) { | 734 | static int recfields (LexState *ls) { |
837 | /* recfields -> { ',' recfield } [','] */ | 735 | /* recfields -> { ',' recfield } [','] */ |
838 | int n = 1; /* one has been read before */ | 736 | int n = 1; /* one has been read before */ |
737 | int mod_n = 1; /* mod_n == n%RFIELDS_PER_FLUSH */ | ||
839 | while (ls->token == ',') { | 738 | while (ls->token == ',') { |
840 | next(ls); | 739 | next(ls); |
841 | if (ls->token == ';' || ls->token == '}') | 740 | if (ls->token == ';' || ls->token == '}') |
842 | break; | 741 | break; |
843 | recfield(ls); | 742 | recfield(ls); |
844 | n++; | 743 | n++; |
845 | if (n%RFIELDS_PER_FLUSH == 0) | 744 | if (++mod_n == RFIELDS_PER_FLUSH) { |
846 | flush_record(ls, RFIELDS_PER_FLUSH); | 745 | code_U(ls, SETMAP, RFIELDS_PER_FLUSH-1, -2*RFIELDS_PER_FLUSH); |
746 | mod_n = 0; | ||
747 | } | ||
847 | } | 748 | } |
848 | flush_record(ls, n%RFIELDS_PER_FLUSH); | 749 | if (mod_n) |
750 | code_U(ls, SETMAP, mod_n-1, -2*mod_n); | ||
849 | return n; | 751 | return n; |
850 | } | 752 | } |
851 | 753 | ||
@@ -853,16 +755,23 @@ static int recfields (LexState *ls) { | |||
853 | static int listfields (LexState *ls) { | 755 | static int listfields (LexState *ls) { |
854 | /* listfields -> { ',' exp1 } [','] */ | 756 | /* listfields -> { ',' exp1 } [','] */ |
855 | int n = 1; /* one has been read before */ | 757 | int n = 1; /* one has been read before */ |
758 | int mod_n = 1; /* mod_n == n%LFIELDS_PER_FLUSH */ | ||
856 | while (ls->token == ',') { | 759 | while (ls->token == ',') { |
857 | next(ls); | 760 | next(ls); |
858 | if (ls->token == ';' || ls->token == '}') | 761 | if (ls->token == ';' || ls->token == '}') |
859 | break; | 762 | break; |
860 | exp1(ls); | 763 | exp1(ls); |
861 | n++; | 764 | n++; |
862 | if (n%LFIELDS_PER_FLUSH == 0) | 765 | checklimit(ls, n, MAXARG_A*LFIELDS_PER_FLUSH, |
863 | flush_list(ls, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH); | 766 | "items in a list initializer"); |
767 | if (++mod_n == LFIELDS_PER_FLUSH) { | ||
768 | code_AB(ls, SETLIST, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH-1, | ||
769 | -LFIELDS_PER_FLUSH); | ||
770 | mod_n = 0; | ||
771 | } | ||
864 | } | 772 | } |
865 | flush_list(ls, n/LFIELDS_PER_FLUSH, n%LFIELDS_PER_FLUSH); | 773 | if (mod_n > 0) |
774 | code_AB(ls, SETLIST, n/LFIELDS_PER_FLUSH, mod_n-1, -mod_n); | ||
866 | return n; | 775 | return n; |
867 | } | 776 | } |
868 | 777 | ||
@@ -920,10 +829,9 @@ static void constructor_part (LexState *ls, constdesc *cd) { | |||
920 | static void constructor (LexState *ls) { | 829 | static void constructor (LexState *ls) { |
921 | /* constructor -> '{' constructor_part [';' constructor_part] '}' */ | 830 | /* constructor -> '{' constructor_part [';' constructor_part] '}' */ |
922 | int line = ls->linenumber; | 831 | int line = ls->linenumber; |
923 | int pc = SaveWord(ls); | 832 | int pc = code_U(ls, CREATETABLE, 0, 1); |
924 | int nelems; | 833 | int nelems; |
925 | constdesc cd; | 834 | constdesc cd; |
926 | deltastack(ls, 1); | ||
927 | check(ls, '{'); | 835 | check(ls, '{'); |
928 | constructor_part(ls, &cd); | 836 | constructor_part(ls, &cd); |
929 | nelems = cd.n; | 837 | nelems = cd.n; |
@@ -936,7 +844,8 @@ static void constructor (LexState *ls) { | |||
936 | nelems += other_cd.n; | 844 | nelems += other_cd.n; |
937 | } | 845 | } |
938 | check_match(ls, '}', '{', line); | 846 | check_match(ls, '}', '{', line); |
939 | fix_opcode(ls, pc, CREATEARRAY, nelems); | 847 | /* set initial table size */ |
848 | ls->fs->f->code[pc] = SETARG_U(ls->fs->f->code[pc], nelems); | ||
940 | } | 849 | } |
941 | 850 | ||
942 | /* }====================================================================== */ | 851 | /* }====================================================================== */ |
@@ -1009,7 +918,7 @@ static void push (LexState *ls, stack_op *s, int op) { | |||
1009 | static void pop_to (LexState *ls, stack_op *s, int prio) { | 918 | static void pop_to (LexState *ls, stack_op *s, int prio) { |
1010 | int op; | 919 | int op; |
1011 | while (s->top > 0 && priority[(op=s->ops[s->top-1])] >= prio) { | 920 | while (s->top > 0 && priority[(op=s->ops[s->top-1])] >= prio) { |
1012 | code_opcode(ls, opcodes[op], op<FIRSTBIN?0:-1); | 921 | code_0(ls, opcodes[op], op<FIRSTBIN?0:-1); |
1013 | s->top--; | 922 | s->top--; |
1014 | } | 923 | } |
1015 | } | 924 | } |
@@ -1113,10 +1022,10 @@ static void expr (LexState *ls, vardesc *v) { | |||
1113 | int pc; | 1022 | int pc; |
1114 | lua_pushvar(ls, v); | 1023 | lua_pushvar(ls, v); |
1115 | next(ls); | 1024 | next(ls); |
1116 | pc = SaveWordPop(ls); | 1025 | pc = code_S(ls, op, 0, -1); |
1117 | arith_exp(ls, v); | 1026 | arith_exp(ls, v); |
1118 | lua_pushvar(ls, v); | 1027 | lua_pushvar(ls, v); |
1119 | fix_jump(ls, pc, op, ls->fs->pc); | 1028 | fix_jump(ls, pc, ls->fs->pc); |
1120 | } | 1029 | } |
1121 | } | 1030 | } |
1122 | 1031 | ||
@@ -1167,7 +1076,7 @@ static int assignment (LexState *ls, vardesc *v, int nvars) { | |||
1167 | storevar(ls, v); | 1076 | storevar(ls, v); |
1168 | } | 1077 | } |
1169 | else { /* indexed var with values in between*/ | 1078 | else { /* indexed var with values in between*/ |
1170 | code_oparg(ls, SETTABLE, left+(nvars-1), -1); | 1079 | code_U(ls, SETTABLE, left+(nvars-1), -1); |
1171 | left += 2; /* table&index are not popped, because they aren't on top */ | 1080 | left += 2; /* table&index are not popped, because they aren't on top */ |
1172 | } | 1081 | } |
1173 | return left; | 1082 | return left; |
@@ -1175,22 +1084,18 @@ static int assignment (LexState *ls, vardesc *v, int nvars) { | |||
1175 | 1084 | ||
1176 | 1085 | ||
1177 | static void whilestat (LexState *ls, int line) { | 1086 | static void whilestat (LexState *ls, int line) { |
1178 | /* whilestat -> WHILE cond DO block END */ | 1087 | /* whilestat -> WHILE exp1 DO block END */ |
1179 | FuncState *fs = ls->fs; | 1088 | FuncState *fs = ls->fs; |
1180 | TProtoFunc *f = fs->f; | ||
1181 | int while_init = fs->pc; | 1089 | int while_init = fs->pc; |
1182 | int cond_end, cond_size; | 1090 | int j1; |
1183 | next(ls); | 1091 | next(ls); |
1184 | cond_end = cond(ls); | 1092 | exp1(ls); |
1093 | j1 = code_U(ls, IFFJMP, 0, -1); /* jump to exit loop */ | ||
1185 | check(ls, DO); | 1094 | check(ls, DO); |
1186 | block(ls); | 1095 | block(ls); |
1187 | check_match(ls, END, WHILE, line); | 1096 | check_match(ls, END, WHILE, line); |
1188 | cond_size = cond_end-while_init; | 1097 | fix_jump(ls, code_U(ls, JMP, 0, 0), while_init); /* jump to keep loop */ |
1189 | check_pc(ls, cond_size); | 1098 | fix_jump(ls, j1, fs->pc); |
1190 | memcpy(f->code+fs->pc, f->code+while_init, cond_size); | ||
1191 | luaO_memdown(f->code+while_init, f->code+cond_end, fs->pc-while_init); | ||
1192 | while_init += JMPSIZE + fix_jump(ls, while_init, JMP, fs->pc-cond_size); | ||
1193 | fix_upjmp(ls, IFTUPJMP, while_init); | ||
1194 | } | 1099 | } |
1195 | 1100 | ||
1196 | 1101 | ||
@@ -1202,8 +1107,7 @@ static void repeatstat (LexState *ls, int line) { | |||
1202 | block(ls); | 1107 | block(ls); |
1203 | check_match(ls, UNTIL, REPEAT, line); | 1108 | check_match(ls, UNTIL, REPEAT, line); |
1204 | exp1(ls); | 1109 | exp1(ls); |
1205 | fix_upjmp(ls, IFFUPJMP, repeat_init); | 1110 | fix_jump(ls, code_U(ls, IFFJMP, 0, -1), repeat_init); |
1206 | deltastack(ls, -1); /* pops condition */ | ||
1207 | } | 1111 | } |
1208 | 1112 | ||
1209 | 1113 | ||
@@ -1295,21 +1199,29 @@ static void namestat (LexState *ls) { | |||
1295 | 1199 | ||
1296 | static void ifpart (LexState *ls, int line) { | 1200 | static void ifpart (LexState *ls, int line) { |
1297 | /* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */ | 1201 | /* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */ |
1202 | FuncState *fs = ls->fs; | ||
1298 | int c; | 1203 | int c; |
1299 | int e; | 1204 | int je; |
1300 | next(ls); /* skip IF or ELSEIF */ | 1205 | next(ls); /* skip IF or ELSEIF */ |
1301 | c = cond(ls); | 1206 | exp1(ls); /* cond */ |
1207 | c = code_U(ls, IFFJMP, 0, -1); /* jump `then' if `cond' is false */ | ||
1302 | check(ls, THEN); | 1208 | check(ls, THEN); |
1303 | block(ls); | 1209 | block(ls); /* `then' part */ |
1304 | e = SaveWord(ls); | 1210 | je = code_U(ls, JMP, 0, 0); /* jump `else' part after `then' */ |
1305 | if (ls->token == ELSEIF) | 1211 | if (ls->token == ELSEIF) |
1306 | ifpart(ls, line); | 1212 | ifpart(ls, line); |
1307 | else { | 1213 | else { |
1308 | if (optional(ls, ELSE)) | 1214 | if (optional(ls, ELSE)) |
1309 | block(ls); | 1215 | block(ls); /* `else' part */ |
1310 | check_match(ls, END, IF, line); | 1216 | check_match(ls, END, IF, line); |
1311 | } | 1217 | } |
1312 | codeIf(ls, c, e); | 1218 | if (fs->pc == je+1) { /* `else' part empty? */ |
1219 | fs->pc--; /* remove last jump */ | ||
1220 | je--; /* first jump will be smaller */ | ||
1221 | } | ||
1222 | else | ||
1223 | fix_jump(ls, je, fs->pc); /* fix last jump */ | ||
1224 | fix_jump(ls, c, je+1); /* fix first jump to beginning of `else' part */ | ||
1313 | } | 1225 | } |
1314 | 1226 | ||
1315 | 1227 | ||
@@ -1395,9 +1307,9 @@ static void parlist (LexState *ls) { | |||
1395 | 1307 | ||
1396 | static void body (LexState *ls, int needself, int line) { | 1308 | static void body (LexState *ls, int needself, int line) { |
1397 | /* body -> '(' parlist ')' chunk END */ | 1309 | /* body -> '(' parlist ')' chunk END */ |
1398 | FuncState newfs; | 1310 | FuncState new_fs; |
1399 | init_state(ls, &newfs, ls->fs->f->source); | 1311 | init_state(ls, &new_fs, ls->fs->f->source); |
1400 | newfs.f->lineDefined = line; | 1312 | new_fs.f->lineDefined = line; |
1401 | check(ls, '('); | 1313 | check(ls, '('); |
1402 | if (needself) | 1314 | if (needself) |
1403 | add_localvar(ls, luaS_newfixed(ls->L, "self")); | 1315 | add_localvar(ls, luaS_newfixed(ls->L, "self")); |
@@ -1406,7 +1318,7 @@ static void body (LexState *ls, int needself, int line) { | |||
1406 | chunk(ls); | 1318 | chunk(ls); |
1407 | check_match(ls, END, FUNCTION, line); | 1319 | check_match(ls, END, FUNCTION, line); |
1408 | close_func(ls); | 1320 | close_func(ls); |
1409 | func_onstack(ls, &newfs); | 1321 | func_onstack(ls, &new_fs); |
1410 | } | 1322 | } |
1411 | 1323 | ||
1412 | 1324 | ||
@@ -1418,12 +1330,12 @@ static void ret (LexState *ls) { | |||
1418 | next(ls); | 1330 | next(ls); |
1419 | explist(ls, &e); | 1331 | explist(ls, &e); |
1420 | if (e.pc > 0) { /* expression is an open function call? */ | 1332 | if (e.pc > 0) { /* expression is an open function call? */ |
1421 | Byte *code = ls->fs->f->code; | 1333 | Instruction *i = &ls->fs->f->code[e.pc]; |
1422 | code[e.pc-2] = TAILCALL; /* instead of a conventional CALL */ | 1334 | *i = SET_OPCODE(*i, TAILCALL); /* instead of a conventional CALL */ |
1423 | code[e.pc-1] = (Byte)ls->fs->nlocalvar; | 1335 | *i = SETARG_B(*i, ls->fs->nlocalvar); |
1424 | } | 1336 | } |
1425 | else | 1337 | else |
1426 | code_oparg(ls, RETCODE, ls->fs->nlocalvar, 0); | 1338 | code_U(ls, RETCODE, ls->fs->nlocalvar, 0); |
1427 | ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ | 1339 | ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ |
1428 | optional(ls, ';'); | 1340 | optional(ls, ';'); |
1429 | } | 1341 | } |