diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-02-22 11:31:43 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-02-22 11:31:43 -0200 |
| commit | 3bc925138ebcb534f863b3fb32b21eb8d52aa915 (patch) | |
| tree | 6fcbc3bf92357a5e2e1651bc38c79b9bbea42a51 | |
| parent | 39e1f079bdf045d64ad6f1b5da1eb48cc79c6c38 (diff) | |
| download | lua-3bc925138ebcb534f863b3fb32b21eb8d52aa915.tar.gz lua-3bc925138ebcb534f863b3fb32b21eb8d52aa915.tar.bz2 lua-3bc925138ebcb534f863b3fb32b21eb8d52aa915.zip | |
first version of code optimizer
| -rw-r--r-- | lopcodes.h | 36 | ||||
| -rw-r--r-- | lparser.c | 395 | ||||
| -rw-r--r-- | lparser.h | 74 | ||||
| -rw-r--r-- | lvm.c | 20 | ||||
| -rw-r--r-- | makefile | 57 |
5 files changed, 312 insertions, 270 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lopcodes.h,v 1.39 2000/02/11 16:52:54 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.40 2000/02/14 16:51:08 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 | */ |
| @@ -47,6 +47,11 @@ | |||
| 47 | 47 | ||
| 48 | 48 | ||
| 49 | 49 | ||
| 50 | /* | ||
| 51 | ** K = U argument used as index to `kstr' | ||
| 52 | ** J = S argument used as jump offset (relative to pc of next instruction) | ||
| 53 | */ | ||
| 54 | |||
| 50 | typedef enum { | 55 | typedef enum { |
| 51 | /* name parm before after side effect | 56 | /* name parm before after side effect |
| 52 | -----------------------------------------------------------------------------*/ | 57 | -----------------------------------------------------------------------------*/ |
| @@ -60,24 +65,25 @@ PUSHNIL,/* U - nil_0-nil_u */ | |||
| 60 | POP,/* U a_u-a_1 - */ | 65 | POP,/* U a_u-a_1 - */ |
| 61 | 66 | ||
| 62 | PUSHINT,/* S - (real)s */ | 67 | PUSHINT,/* S - (real)s */ |
| 63 | PUSHSTRING,/* U - KSTR[u] */ | 68 | PUSHSTRING,/* K - KSTR[k] */ |
| 64 | PUSHNUMBER,/* U - KNUM[u] */ | 69 | PUSHNUM,/* U - KNUM[u] */ |
| 70 | PUSHNEGNUM,/* U - -KNUM[u] */ | ||
| 65 | 71 | ||
| 66 | PUSHUPVALUE,/* U - Closure[u] */ | 72 | PUSHUPVALUE,/* U - Closure[u] */ |
| 67 | 73 | ||
| 68 | PUSHLOCAL,/* U - LOC[u] */ | 74 | PUSHLOCAL,/* U - LOC[u] */ |
| 69 | GETGLOBAL,/* U - VAR[CNST[u]] */ | 75 | GETGLOBAL,/* K - VAR[CNST[k]] */ |
| 70 | 76 | ||
| 71 | GETTABLE,/* - i t t[i] */ | 77 | GETTABLE,/* - i t t[i] */ |
| 72 | GETDOTTED,/* U t t[CNST[u]] */ | 78 | GETDOTTED,/* K t t[KSTR[k]] */ |
| 73 | PUSHSELF,/* U t t t[CNST[u]] */ | 79 | PUSHSELF,/* K t t t[KSTR[k]] */ |
| 74 | 80 | ||
| 75 | CREATETABLE,/* U - newarray(size = u) */ | 81 | CREATETABLE,/* U - newarray(size = u) */ |
| 76 | 82 | ||
| 77 | SETLOCAL,/* U x - LOC[u]=x */ | 83 | SETLOCAL,/* U x - LOC[u]=x */ |
| 78 | SETGLOBAL,/* U x - VAR[CNST[u]]=x */ | 84 | SETGLOBAL,/* K x - VAR[KSTR[k]]=x */ |
| 79 | SETTABLEPOP,/* - v i t - t[i]=v */ | 85 | SETTABLEPOP,/* - v i t - t[i]=v */ |
| 80 | SETTABLE,/* U v a_u-a_1 i t a_u-a_1 i t t[i]=v */ | 86 | SETTABLE,/* U v a_u-a_1 i t a_u-a_1 i t t[i]=v */ |
| 81 | 87 | ||
| 82 | SETLIST,/* A B v_b-v_0 t t t[i+a*FPF]=v_i */ | 88 | SETLIST,/* A B v_b-v_0 t t t[i+a*FPF]=v_i */ |
| 83 | SETMAP,/* U v_u k_u - v_0 k_0 t t t[k_i]=v_i */ | 89 | SETMAP,/* U v_u k_u - v_0 k_0 t t t[k_i]=v_i */ |
| @@ -88,7 +94,9 @@ LTOP,/* - y x (x<y)? 1 : nil */ | |||
| 88 | LEOP,/* - y x (x<y)? 1 : nil */ | 94 | LEOP,/* - y x (x<y)? 1 : nil */ |
| 89 | GTOP,/* - y x (x>y)? 1 : nil */ | 95 | GTOP,/* - y x (x>y)? 1 : nil */ |
| 90 | GEOP,/* - y x (x>=y)? 1 : nil */ | 96 | GEOP,/* - y x (x>=y)? 1 : nil */ |
| 97 | |||
| 91 | ADDOP,/* - y x x+y */ | 98 | ADDOP,/* - y x x+y */ |
| 99 | ADDI,/* S x x+s */ | ||
| 92 | SUBOP,/* - y x x-y */ | 100 | SUBOP,/* - y x x-y */ |
| 93 | MULTOP,/* - y x x*y */ | 101 | MULTOP,/* - y x x*y */ |
| 94 | DIVOP,/* - y x x/y */ | 102 | DIVOP,/* - y x x/y */ |
| @@ -97,11 +105,11 @@ CONCOP,/* - y x x..y */ | |||
| 97 | MINUSOP,/* - x -x */ | 105 | MINUSOP,/* - x -x */ |
| 98 | NOTOP,/* - x (x==nil)? 1 : nil */ | 106 | NOTOP,/* - x (x==nil)? 1 : nil */ |
| 99 | 107 | ||
| 100 | ONTJMP,/* S x (x!=nil)? x : - (x!=nil)? PC+=s */ | 108 | ONTJMP,/* J x (x!=nil)? x : - (x!=nil)? PC+=s */ |
| 101 | ONFJMP,/* S x (x==nil)? x : - (x==nil)? PC+=s */ | 109 | ONFJMP,/* J x (x==nil)? x : - (x==nil)? PC+=s */ |
| 102 | JMP,/* S - - PC+=s */ | 110 | JMP,/* J - - PC+=s */ |
| 103 | IFTJMP,/* S x - (x!=nil)? PC+=s */ | 111 | IFTJMP,/* J x - (x!=nil)? PC+=s */ |
| 104 | IFFJMP,/* S x - (x==nil)? PC+=s */ | 112 | IFFJMP,/* J x - (x==nil)? PC+=s */ |
| 105 | 113 | ||
| 106 | CLOSURE,/* A B v_b-v_1 closure(CNST[a], v_b-v_1) */ | 114 | CLOSURE,/* A B v_b-v_1 closure(CNST[a], v_b-v_1) */ |
| 107 | 115 | ||
| @@ -111,7 +119,7 @@ SETLINE/* U - - LINE=u */ | |||
| 111 | 119 | ||
| 112 | 120 | ||
| 113 | #define RFIELDS_PER_FLUSH 32 /* records (SETMAP) */ | 121 | #define RFIELDS_PER_FLUSH 32 /* records (SETMAP) */ |
| 114 | #define LFIELDS_PER_FLUSH 64 /* FPF - lists (SETLIST) (<MAXARG_B) */ | 122 | #define LFIELDS_PER_FLUSH 64 /* FPF - lists (SETLIST) (<=MAXARG_B) */ |
| 115 | 123 | ||
| 116 | 124 | ||
| 117 | #endif | 125 | #endif |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 1.58 2000/02/11 16:52:54 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.59 2000/02/14 16:51:08 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 | */ |
| @@ -8,6 +8,9 @@ | |||
| 8 | #include <stdio.h> | 8 | #include <stdio.h> |
| 9 | #include <string.h> | 9 | #include <string.h> |
| 10 | 10 | ||
| 11 | #define LUA_REENTRANT | ||
| 12 | |||
| 13 | #include "lcode.h" | ||
| 11 | #include "ldo.h" | 14 | #include "ldo.h" |
| 12 | #include "lfunc.h" | 15 | #include "lfunc.h" |
| 13 | #include "llex.h" | 16 | #include "llex.h" |
| @@ -19,50 +22,6 @@ | |||
| 19 | #include "lstring.h" | 22 | #include "lstring.h" |
| 20 | 23 | ||
| 21 | 24 | ||
| 22 | |||
| 23 | /* maximum number of local variables */ | ||
| 24 | #ifndef MAXLOCALS | ||
| 25 | #define MAXLOCALS 200 /* arbitrary limit (<MAXARG_B) */ | ||
| 26 | #endif | ||
| 27 | |||
| 28 | |||
| 29 | /* maximum number of upvalues */ | ||
| 30 | #ifndef MAXUPVALUES | ||
| 31 | #define MAXUPVALUES 32 /* arbitrary limit (<MAXARG_B) */ | ||
| 32 | #endif | ||
| 33 | |||
| 34 | |||
| 35 | /* maximum number of variables in the left side of an assignment */ | ||
| 36 | #ifndef MAXVARSLH | ||
| 37 | #define MAXVARSLH 100 /* arbitrary limit (<MAXARG_B) */ | ||
| 38 | #endif | ||
| 39 | |||
| 40 | |||
| 41 | /* maximum number of parameters in a function */ | ||
| 42 | #ifndef MAXPARAMS | ||
| 43 | #define MAXPARAMS 100 /* arbitrary limit (<MAXLOCALS) */ | ||
| 44 | #endif | ||
| 45 | |||
| 46 | |||
| 47 | /* | ||
| 48 | ** Variable descriptor: | ||
| 49 | ** must include an `exp' option because LL(1) cannot distinguish | ||
| 50 | ** between variables, upvalues and function calls on first sight. | ||
| 51 | */ | ||
| 52 | typedef enum { | ||
| 53 | VGLOBAL, /* info is constant index of global name */ | ||
| 54 | VLOCAL, /* info is stack index */ | ||
| 55 | VDOT, /* info is constant index of index name */ | ||
| 56 | VINDEXED, /* no info (table and index are on the stack) */ | ||
| 57 | VEXP /* info is pc index of a call (or 0 if exp is closed) */ | ||
| 58 | } varkind; | ||
| 59 | |||
| 60 | typedef struct vardesc { | ||
| 61 | varkind k; | ||
| 62 | int info; | ||
| 63 | } vardesc; | ||
| 64 | |||
| 65 | |||
| 66 | /* | 25 | /* |
| 67 | ** Expression List descriptor: | 26 | ** Expression List descriptor: |
| 68 | ** tells number of expressions in the list, | 27 | ** tells number of expressions in the list, |
| @@ -87,19 +46,6 @@ typedef struct constdesc { | |||
| 87 | } constdesc; | 46 | } constdesc; |
| 88 | 47 | ||
| 89 | 48 | ||
| 90 | /* state needed to generate code for a given function */ | ||
| 91 | typedef struct FuncState { | ||
| 92 | TProtoFunc *f; /* current function header */ | ||
| 93 | struct FuncState *prev; /* enclosing function */ | ||
| 94 | int pc; /* next position to code */ | ||
| 95 | int stacksize; /* number of values on activation register */ | ||
| 96 | int nlocalvar; /* number of active local variables */ | ||
| 97 | int nupvalues; /* number of upvalues */ | ||
| 98 | int nvars; /* number of entries in f->locvars (-1 if no debug information) */ | ||
| 99 | int lastsetline; /* line where last SETLINE was issued */ | ||
| 100 | vardesc upvalues[MAXUPVALUES]; /* upvalues */ | ||
| 101 | TaggedString *localvar[MAXLOCALS]; /* store local variable names */ | ||
| 102 | } FuncState; | ||
| 103 | 49 | ||
| 104 | 50 | ||
| 105 | /* | 51 | /* |
| @@ -112,40 +58,74 @@ static void expr (LexState *ls, vardesc *v); | |||
| 112 | static void exp1 (LexState *ls); | 58 | static void exp1 (LexState *ls); |
| 113 | 59 | ||
| 114 | 60 | ||
| 61 | static void next (LexState *ls) { | ||
| 62 | ls->token = luaX_lex(ls); | ||
| 63 | } | ||
| 64 | |||
| 115 | 65 | ||
| 116 | static void luaY_error (LexState *ls, const char *msg) { | 66 | static void luaY_error (LexState *ls, const char *msg) { |
| 117 | luaX_error(ls, msg, ls->token); | 67 | luaX_error(ls, msg, ls->token); |
| 118 | } | 68 | } |
| 119 | 69 | ||
| 120 | 70 | ||
| 121 | static void checklimit (LexState *ls, int val, int limit, const char *msg) { | 71 | static void error_expected (LexState *ls, int token) { |
| 122 | if (val > limit) { | 72 | char buff[100], t[TOKEN_LEN]; |
| 73 | luaX_token2str(token, t); | ||
| 74 | sprintf(buff, "`%.20s' expected", t); | ||
| 75 | luaY_error(ls, buff); | ||
| 76 | } | ||
| 77 | |||
| 78 | |||
| 79 | static void error_unexpected (LexState *ls) { | ||
| 80 | luaY_error(ls, "unexpected token"); | ||
| 81 | } | ||
| 82 | |||
| 83 | |||
| 84 | static void error_unmatched (LexState *ls, int what, int who, int where) { | ||
| 85 | if (where == ls->linenumber) | ||
| 86 | error_expected(ls, what); | ||
| 87 | else { | ||
| 123 | char buff[100]; | 88 | char buff[100]; |
| 124 | sprintf(buff, "too many %.50s (limit=%d)", msg, limit); | 89 | char t_what[TOKEN_LEN], t_who[TOKEN_LEN]; |
| 90 | luaX_token2str(what, t_what); | ||
| 91 | luaX_token2str(who, t_who); | ||
| 92 | sprintf(buff, "`%.20s' expected (to close `%.20s' at line %d)", | ||
| 93 | t_what, t_who, where); | ||
| 125 | luaY_error(ls, buff); | 94 | luaY_error(ls, buff); |
| 126 | } | 95 | } |
| 127 | } | 96 | } |
| 128 | 97 | ||
| 98 | static void check (LexState *ls, int c) { | ||
| 99 | if (ls->token != c) | ||
| 100 | error_expected(ls, c); | ||
| 101 | next(ls); | ||
| 102 | } | ||
| 103 | |||
| 129 | 104 | ||
| 130 | static int code_instruction (LexState *ls, Instruction i) { | 105 | static int optional (LexState *ls, int c) { |
| 131 | FuncState *fs = ls->fs; | 106 | if (ls->token == c) { |
| 132 | luaM_growvector(ls->L, fs->f->code, fs->pc, 1, Instruction, codeEM, MAXARG_S); | 107 | next(ls); |
| 133 | fs->f->code[fs->pc] = i; | 108 | return 1; |
| 134 | return fs->pc++; | 109 | } |
| 110 | else return 0; | ||
| 135 | } | 111 | } |
| 136 | 112 | ||
| 137 | 113 | ||
| 138 | static void fix_jump (LexState *ls, int pc, int dest) { | 114 | static void checklimit (LexState *ls, int val, int limit, const char *msg) { |
| 139 | Instruction *jmp = &ls->fs->f->code[pc]; | 115 | if (val > limit) { |
| 140 | /* jump is relative to position following jump instruction */ | 116 | char buff[100]; |
| 141 | *jmp = SETARG_S(*jmp, dest-(pc+1)); | 117 | sprintf(buff, "too many %.50s (limit=%d)", msg, limit); |
| 118 | luaY_error(ls, buff); | ||
| 119 | } | ||
| 142 | } | 120 | } |
| 143 | 121 | ||
| 144 | 122 | ||
| 123 | |||
| 145 | static void deltastack (LexState *ls, int delta) { | 124 | static void deltastack (LexState *ls, int delta) { |
| 146 | FuncState *fs = ls->fs; | 125 | FuncState *fs = ls->fs; |
| 147 | fs->stacksize += delta; | 126 | fs->stacksize += delta; |
| 148 | if (delta > 0 && fs->stacksize > fs->f->maxstacksize) { | 127 | if (delta > 0 && fs->stacksize > fs->f->maxstacksize) { |
| 128 | checklimit(ls, fs->stacksize, MAXSTACK, "temporaries or local variables"); | ||
| 149 | fs->f->maxstacksize = fs->stacksize; | 129 | fs->f->maxstacksize = fs->stacksize; |
| 150 | } | 130 | } |
| 151 | } | 131 | } |
| @@ -153,7 +133,7 @@ static void deltastack (LexState *ls, int delta) { | |||
| 153 | 133 | ||
| 154 | static int aux_code (LexState *ls, OpCode op, Instruction i, int delta) { | 134 | static int aux_code (LexState *ls, OpCode op, Instruction i, int delta) { |
| 155 | deltastack(ls, delta); | 135 | deltastack(ls, delta); |
| 156 | return code_instruction(ls, SET_OPCODE(i, op)); | 136 | return luaK_code(ls, SET_OPCODE(i, op)); |
| 157 | } | 137 | } |
| 158 | 138 | ||
| 159 | 139 | ||
| @@ -182,6 +162,22 @@ static int code_AB (LexState *ls, OpCode op, int a, int b, int delta) { | |||
| 182 | } | 162 | } |
| 183 | 163 | ||
| 184 | 164 | ||
| 165 | static void check_debugline (LexState *ls) { | ||
| 166 | if (ls->L->debug && ls->linenumber != ls->fs->lastsetline) { | ||
| 167 | code_U(ls, SETLINE, ls->linenumber, 0); | ||
| 168 | ls->fs->lastsetline = ls->linenumber; | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | |||
| 173 | static void check_match (LexState *ls, int what, int who, int where) { | ||
| 174 | if (ls->token != what) | ||
| 175 | error_unmatched(ls, what, who, where); | ||
| 176 | check_debugline(ls); /* to `mark' the `what' */ | ||
| 177 | next(ls); | ||
| 178 | } | ||
| 179 | |||
| 180 | |||
| 185 | static void code_kstr (LexState *ls, int c) { | 181 | static void code_kstr (LexState *ls, int c) { |
| 186 | code_U(ls, PUSHSTRING, c, 1); | 182 | code_U(ls, PUSHSTRING, c, 1); |
| 187 | } | 183 | } |
| @@ -228,10 +224,26 @@ static int real_constant (LexState *ls, real r) { | |||
| 228 | 224 | ||
| 229 | 225 | ||
| 230 | static void code_number (LexState *ls, real f) { | 226 | static void code_number (LexState *ls, real f) { |
| 231 | if ((real)(-MAXARG_S) <= f && f <= (real)MAXARG_S && (int)f == f) | 227 | if (f <= (real)MAXARG_S && (int)f == f) |
| 232 | code_S(ls, PUSHINT, (int)f, 1); /* f has a short integer value */ | 228 | code_S(ls, PUSHINT, (int)f, 1); /* f has a short integer value */ |
| 233 | else | 229 | else |
| 234 | code_U(ls, PUSHNUMBER, real_constant(ls, f), 1); | 230 | code_U(ls, PUSHNUM, real_constant(ls, f), 1); |
| 231 | } | ||
| 232 | |||
| 233 | |||
| 234 | static int checkname (LexState *ls) { | ||
| 235 | int sc; | ||
| 236 | if (ls->token != NAME) | ||
| 237 | luaY_error(ls, "<name> expected"); | ||
| 238 | sc = string_constant(ls, ls->fs, ls->seminfo.ts); | ||
| 239 | next(ls); | ||
| 240 | return sc; | ||
| 241 | } | ||
| 242 | |||
| 243 | |||
| 244 | static TaggedString *str_checkname (LexState *ls) { | ||
| 245 | int i = checkname(ls); /* this call may realloc `f->consts' */ | ||
| 246 | return ls->fs->f->kstr[i]; | ||
| 235 | } | 247 | } |
| 236 | 248 | ||
| 237 | 249 | ||
| @@ -327,15 +339,6 @@ static void pushupvalue (LexState *ls, TaggedString *n) { | |||
| 327 | } | 339 | } |
| 328 | 340 | ||
| 329 | 341 | ||
| 330 | |||
| 331 | static void check_debugline (LexState *ls) { | ||
| 332 | if (ls->L->debug && ls->linenumber != ls->fs->lastsetline) { | ||
| 333 | code_U(ls, SETLINE, ls->linenumber, 0); | ||
| 334 | ls->fs->lastsetline = ls->linenumber; | ||
| 335 | } | ||
| 336 | } | ||
| 337 | |||
| 338 | |||
| 339 | static void adjuststack (LexState *ls, int n) { | 342 | static void adjuststack (LexState *ls, int n) { |
| 340 | if (n > 0) | 343 | if (n > 0) |
| 341 | code_U(ls, POP, n, -n); | 344 | code_U(ls, POP, n, -n); |
| @@ -344,7 +347,7 @@ static void adjuststack (LexState *ls, int n) { | |||
| 344 | } | 347 | } |
| 345 | 348 | ||
| 346 | 349 | ||
| 347 | static void close_exp (LexState *ls, int pc, int nresults) { | 350 | static void close_call (LexState *ls, int pc, int nresults) { |
| 348 | if (pc > 0) { /* expression is an open function call? */ | 351 | if (pc > 0) { /* expression is an open function call? */ |
| 349 | Instruction *i = &ls->fs->f->code[pc]; | 352 | Instruction *i = &ls->fs->f->code[pc]; |
| 350 | *i = SETARG_B(*i, nresults); /* set nresults */ | 353 | *i = SETARG_B(*i, nresults); /* set nresults */ |
| @@ -364,10 +367,10 @@ static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) { | |||
| 364 | diff--; /* do not count function call itself */ | 367 | diff--; /* do not count function call itself */ |
| 365 | if (diff <= 0) { /* more variables than values? */ | 368 | if (diff <= 0) { /* more variables than values? */ |
| 366 | /* function call must provide extra values */ | 369 | /* function call must provide extra values */ |
| 367 | close_exp(ls, d->pc, -diff); | 370 | close_call(ls, d->pc, -diff); |
| 368 | } | 371 | } |
| 369 | else { /* more values than variables */ | 372 | else { /* more values than variables */ |
| 370 | close_exp(ls, d->pc, 0); /* call should provide no value */ | 373 | close_call(ls, d->pc, 0); /* call should provide no value */ |
| 371 | adjuststack(ls, diff); /* pop eventual extra values */ | 374 | adjuststack(ls, diff); /* pop eventual extra values */ |
| 372 | } | 375 | } |
| 373 | } | 376 | } |
| @@ -390,16 +393,21 @@ static void code_args (LexState *ls, int nparams, int dots) { | |||
| 390 | } | 393 | } |
| 391 | 394 | ||
| 392 | 395 | ||
| 393 | static void unloaddot (LexState *ls, vardesc *v) { | 396 | static int getvarname (LexState *ls, vardesc *var) { |
| 394 | /* dotted variables <a.x> must be stored as regular indexed vars <a["x"]> */ | 397 | switch (var->k) { |
| 395 | if (v->k == VDOT) { | 398 | case VGLOBAL: |
| 396 | code_kstr(ls, v->info); | 399 | return var->info; |
| 397 | v->k = VINDEXED; | 400 | case VLOCAL: |
| 401 | return string_constant(ls, ls->fs, ls->fs->localvar[var->info]); | ||
| 402 | break; | ||
| 403 | default: | ||
| 404 | error_unexpected(ls); /* there is no `var name' */ | ||
| 405 | return 0; /* to avoid warnings */ | ||
| 398 | } | 406 | } |
| 399 | } | 407 | } |
| 400 | 408 | ||
| 401 | 409 | ||
| 402 | static void lua_pushvar (LexState *ls, vardesc *var) { | 410 | static void close_exp (LexState *ls, vardesc *var) { |
| 403 | switch (var->k) { | 411 | switch (var->k) { |
| 404 | case VLOCAL: | 412 | case VLOCAL: |
| 405 | code_U(ls, PUSHLOCAL, var->info, 1); | 413 | code_U(ls, PUSHLOCAL, var->info, 1); |
| @@ -408,14 +416,11 @@ static void lua_pushvar (LexState *ls, vardesc *var) { | |||
| 408 | code_U(ls, GETGLOBAL, var->info, 1); | 416 | code_U(ls, GETGLOBAL, var->info, 1); |
| 409 | assertglobal(ls, var->info); /* make sure that there is a global */ | 417 | assertglobal(ls, var->info); /* make sure that there is a global */ |
| 410 | break; | 418 | break; |
| 411 | case VDOT: | ||
| 412 | code_U(ls, GETDOTTED, var->info, 0); | ||
| 413 | break; | ||
| 414 | case VINDEXED: | 419 | case VINDEXED: |
| 415 | code_0(ls, GETTABLE, -1); | 420 | code_0(ls, GETTABLE, -1); |
| 416 | break; | 421 | break; |
| 417 | case VEXP: | 422 | case VEXP: |
| 418 | close_exp(ls, var->info, 1); /* function must return 1 value */ | 423 | close_call(ls, var->info, 1); /* call must return 1 value */ |
| 419 | break; | 424 | break; |
| 420 | } | 425 | } |
| 421 | var->k = VEXP; | 426 | var->k = VEXP; |
| @@ -445,7 +450,7 @@ static void func_onstack (LexState *ls, FuncState *func) { | |||
| 445 | TProtoFunc *f = ls->fs->f; | 450 | TProtoFunc *f = ls->fs->f; |
| 446 | int i; | 451 | int i; |
| 447 | for (i=0; i<func->nupvalues; i++) | 452 | for (i=0; i<func->nupvalues; i++) |
| 448 | lua_pushvar(ls, &func->upvalues[i]); | 453 | close_exp(ls, &func->upvalues[i]); |
| 449 | luaM_growvector(ls->L, f->kproto, f->nkproto, 1, TProtoFunc *, | 454 | luaM_growvector(ls->L, f->kproto, f->nkproto, 1, TProtoFunc *, |
| 450 | constantEM, MAXARG_A); | 455 | constantEM, MAXARG_A); |
| 451 | f->kproto[f->nkproto++] = func->f; | 456 | f->kproto[f->nkproto++] = func->f; |
| @@ -466,6 +471,7 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) { | |||
| 466 | fs->f = f; | 471 | fs->f = f; |
| 467 | f->source = source; | 472 | f->source = source; |
| 468 | fs->pc = 0; | 473 | fs->pc = 0; |
| 474 | fs->last_pc = -1; /* invalid index to signal no last instruction */ | ||
| 469 | f->code = NULL; | 475 | f->code = NULL; |
| 470 | f->maxstacksize = 0; | 476 | f->maxstacksize = 0; |
| 471 | f->numparams = 0; /* default for main chunk */ | 477 | f->numparams = 0; /* default for main chunk */ |
| @@ -495,76 +501,6 @@ static void close_func (LexState *ls) { | |||
| 495 | } | 501 | } |
| 496 | 502 | ||
| 497 | 503 | ||
| 498 | static void next (LexState *ls) { | ||
| 499 | ls->token = luaX_lex(ls); | ||
| 500 | } | ||
| 501 | |||
| 502 | |||
| 503 | static void error_expected (LexState *ls, int token) { | ||
| 504 | char buff[100], t[TOKEN_LEN]; | ||
| 505 | luaX_token2str(token, t); | ||
| 506 | sprintf(buff, "`%.20s' expected", t); | ||
| 507 | luaY_error(ls, buff); | ||
| 508 | } | ||
| 509 | |||
| 510 | |||
| 511 | static void error_unexpected (LexState *ls) { | ||
| 512 | luaY_error(ls, "unexpected token"); | ||
| 513 | } | ||
| 514 | |||
| 515 | |||
| 516 | static void error_unmatched (LexState *ls, int what, int who, int where) { | ||
| 517 | if (where == ls->linenumber) | ||
| 518 | error_expected(ls, what); | ||
| 519 | else { | ||
| 520 | char buff[100]; | ||
| 521 | char t_what[TOKEN_LEN], t_who[TOKEN_LEN]; | ||
| 522 | luaX_token2str(what, t_what); | ||
| 523 | luaX_token2str(who, t_who); | ||
| 524 | sprintf(buff, "`%.20s' expected (to close `%.20s' at line %d)", | ||
| 525 | t_what, t_who, where); | ||
| 526 | luaY_error(ls, buff); | ||
| 527 | } | ||
| 528 | } | ||
| 529 | |||
| 530 | static void check (LexState *ls, int c) { | ||
| 531 | if (ls->token != c) | ||
| 532 | error_expected(ls, c); | ||
| 533 | next(ls); | ||
| 534 | } | ||
| 535 | |||
| 536 | static void check_match (LexState *ls, int what, int who, int where) { | ||
| 537 | if (ls->token != what) | ||
| 538 | error_unmatched(ls, what, who, where); | ||
| 539 | check_debugline(ls); /* to `mark' the `what' */ | ||
| 540 | next(ls); | ||
| 541 | } | ||
| 542 | |||
| 543 | static int checkname (LexState *ls) { | ||
| 544 | int sc; | ||
| 545 | if (ls->token != NAME) | ||
| 546 | luaY_error(ls, "<name> expected"); | ||
| 547 | sc = string_constant(ls, ls->fs, ls->seminfo.ts); | ||
| 548 | next(ls); | ||
| 549 | return sc; | ||
| 550 | } | ||
| 551 | |||
| 552 | |||
| 553 | static TaggedString *str_checkname (LexState *ls) { | ||
| 554 | int i = checkname(ls); /* this call may realloc `f->consts' */ | ||
| 555 | return ls->fs->f->kstr[i]; | ||
| 556 | } | ||
| 557 | |||
| 558 | |||
| 559 | static int optional (LexState *ls, int c) { | ||
| 560 | if (ls->token == c) { | ||
| 561 | next(ls); | ||
| 562 | return 1; | ||
| 563 | } | ||
| 564 | else return 0; | ||
| 565 | } | ||
| 566 | |||
| 567 | |||
| 568 | TProtoFunc *luaY_parser (lua_State *L, ZIO *z) { | 504 | TProtoFunc *luaY_parser (lua_State *L, ZIO *z) { |
| 569 | struct LexState lexstate; | 505 | struct LexState lexstate; |
| 570 | struct FuncState funcstate; | 506 | struct FuncState funcstate; |
| @@ -591,14 +527,14 @@ static void explist1 (LexState *ls, listdesc *d) { | |||
| 591 | d->n = 1; | 527 | d->n = 1; |
| 592 | while (ls->token == ',') { | 528 | while (ls->token == ',') { |
| 593 | d->n++; | 529 | d->n++; |
| 594 | lua_pushvar(ls, &v); | 530 | close_exp(ls, &v); |
| 595 | next(ls); | 531 | next(ls); |
| 596 | expr(ls, &v); | 532 | expr(ls, &v); |
| 597 | } | 533 | } |
| 598 | if (v.k == VEXP) | 534 | if (v.k == VEXP) |
| 599 | d->pc = v.info; | 535 | d->pc = v.info; |
| 600 | else { | 536 | else { |
| 601 | lua_pushvar(ls, &v); | 537 | close_exp(ls, &v); |
| 602 | d->pc = 0; | 538 | d->pc = 0; |
| 603 | } | 539 | } |
| 604 | } | 540 | } |
| @@ -628,7 +564,7 @@ static int funcparams (LexState *ls, int slf) { | |||
| 628 | next(ls); | 564 | next(ls); |
| 629 | explist(ls, &e); | 565 | explist(ls, &e); |
| 630 | check_match(ls, ')', '(', line); | 566 | check_match(ls, ')', '(', line); |
| 631 | close_exp(ls, e.pc, MULT_RET); /* close 1 for old semantics */ | 567 | close_call(ls, e.pc, MULT_RET); /* close 1 for old semantics */ |
| 632 | break; | 568 | break; |
| 633 | } | 569 | } |
| 634 | 570 | ||
| @@ -655,14 +591,14 @@ static void var_or_func_tail (LexState *ls, vardesc *v) { | |||
| 655 | switch (ls->token) { | 591 | switch (ls->token) { |
| 656 | case '.': /* var_or_func_tail -> '.' NAME */ | 592 | case '.': /* var_or_func_tail -> '.' NAME */ |
| 657 | next(ls); | 593 | next(ls); |
| 658 | lua_pushvar(ls, v); /* `v' must be on stack */ | 594 | close_exp(ls, v); /* `v' must be on stack */ |
| 659 | v->k = VDOT; | 595 | code_kstr(ls, checkname(ls)); |
| 660 | v->info = checkname(ls); | 596 | v->k = VINDEXED; |
| 661 | break; | 597 | break; |
| 662 | 598 | ||
| 663 | case '[': /* var_or_func_tail -> '[' exp1 ']' */ | 599 | case '[': /* var_or_func_tail -> '[' exp1 ']' */ |
| 664 | next(ls); | 600 | next(ls); |
| 665 | lua_pushvar(ls, v); /* `v' must be on stack */ | 601 | close_exp(ls, v); /* `v' must be on stack */ |
| 666 | exp1(ls); | 602 | exp1(ls); |
| 667 | check(ls, ']'); | 603 | check(ls, ']'); |
| 668 | v->k = VINDEXED; | 604 | v->k = VINDEXED; |
| @@ -672,7 +608,7 @@ static void var_or_func_tail (LexState *ls, vardesc *v) { | |||
| 672 | int name; | 608 | int name; |
| 673 | next(ls); | 609 | next(ls); |
| 674 | name = checkname(ls); | 610 | name = checkname(ls); |
| 675 | lua_pushvar(ls, v); /* `v' must be on stack */ | 611 | close_exp(ls, v); /* `v' must be on stack */ |
| 676 | code_U(ls, PUSHSELF, name, 1); | 612 | code_U(ls, PUSHSELF, name, 1); |
| 677 | v->k = VEXP; | 613 | v->k = VEXP; |
| 678 | v->info = funcparams(ls, 1); | 614 | v->info = funcparams(ls, 1); |
| @@ -680,7 +616,7 @@ static void var_or_func_tail (LexState *ls, vardesc *v) { | |||
| 680 | } | 616 | } |
| 681 | 617 | ||
| 682 | case '(': case STRING: case '{': /* var_or_func_tail -> funcparams */ | 618 | case '(': case STRING: case '{': /* var_or_func_tail -> funcparams */ |
| 683 | lua_pushvar(ls, v); /* `v' must be on stack */ | 619 | close_exp(ls, v); /* `v' must be on stack */ |
| 684 | v->k = VEXP; | 620 | v->k = VEXP; |
| 685 | v->info = funcparams(ls, 0); | 621 | v->info = funcparams(ls, 0); |
| 686 | break; | 622 | break; |
| @@ -711,6 +647,7 @@ static void var_or_func (LexState *ls, vardesc *v) { | |||
| 711 | ** ======================================================================= | 647 | ** ======================================================================= |
| 712 | */ | 648 | */ |
| 713 | 649 | ||
| 650 | |||
| 714 | static void recfield (LexState *ls) { | 651 | static void recfield (LexState *ls) { |
| 715 | /* recfield -> (NAME | '['exp1']') = exp1 */ | 652 | /* recfield -> (NAME | '['exp1']') = exp1 */ |
| 716 | switch (ls->token) { | 653 | switch (ls->token) { |
| @@ -788,23 +725,14 @@ static void constructor_part (LexState *ls, constdesc *cd) { | |||
| 788 | vardesc v; | 725 | vardesc v; |
| 789 | expr(ls, &v); | 726 | expr(ls, &v); |
| 790 | if (ls->token == '=') { | 727 | if (ls->token == '=') { |
| 791 | switch (v.k) { | 728 | code_kstr(ls, getvarname(ls, &v)); |
| 792 | case VGLOBAL: | 729 | next(ls); /* skip '=' */ |
| 793 | code_kstr(ls, v.info); | 730 | exp1(ls); |
| 794 | break; | ||
| 795 | case VLOCAL: | ||
| 796 | code_string(ls, ls->fs->localvar[v.info]); | ||
| 797 | break; | ||
| 798 | default: | ||
| 799 | error_unexpected(ls); | ||
| 800 | } | ||
| 801 | next(ls); | ||
| 802 | exp1(ls); | ||
| 803 | cd->n = recfields(ls); | 731 | cd->n = recfields(ls); |
| 804 | cd->k = 1; /* record */ | 732 | cd->k = 1; /* record */ |
| 805 | } | 733 | } |
| 806 | else { | 734 | else { |
| 807 | lua_pushvar(ls, &v); | 735 | close_exp(ls, &v); |
| 808 | cd->n = listfields(ls); | 736 | cd->n = listfields(ls); |
| 809 | cd->k = 0; /* list */ | 737 | cd->k = 0; /* list */ |
| 810 | } | 738 | } |
| @@ -923,18 +851,12 @@ static void pop_to (LexState *ls, stack_op *s, int prio) { | |||
| 923 | } | 851 | } |
| 924 | } | 852 | } |
| 925 | 853 | ||
| 926 | static void simpleexp (LexState *ls, vardesc *v, stack_op *s) { | 854 | static void simpleexp (LexState *ls, vardesc *v) { |
| 927 | check_debugline(ls); | 855 | check_debugline(ls); |
| 928 | switch (ls->token) { | 856 | switch (ls->token) { |
| 929 | case NUMBER: { /* simpleexp -> NUMBER */ | 857 | case NUMBER: { /* simpleexp -> NUMBER */ |
| 930 | real r = ls->seminfo.r; | 858 | real r = ls->seminfo.r; |
| 931 | next(ls); | 859 | next(ls); |
| 932 | /* dirty trick: check whether it is a -NUMBER not followed by '^' */ | ||
| 933 | /* (because the priority of '^' is higher than the priority of '-') */ | ||
| 934 | if (s->top > 0 && s->ops[s->top-1] == INDMINUS && ls->token != '^') { | ||
| 935 | s->top--; /* remove '-' from stack */ | ||
| 936 | r = -r; | ||
| 937 | } | ||
| 938 | code_number(ls, r); | 860 | code_number(ls, r); |
| 939 | break; | 861 | break; |
| 940 | } | 862 | } |
| @@ -982,7 +904,7 @@ static void prefixexp (LexState *ls, vardesc *v, stack_op *s) { | |||
| 982 | push(ls, s, (ls->token==NOT)?INDNOT:INDMINUS); | 904 | push(ls, s, (ls->token==NOT)?INDNOT:INDMINUS); |
| 983 | next(ls); | 905 | next(ls); |
| 984 | } | 906 | } |
| 985 | simpleexp(ls, v, s); | 907 | simpleexp(ls, v); |
| 986 | } | 908 | } |
| 987 | 909 | ||
| 988 | 910 | ||
| @@ -992,16 +914,16 @@ static void arith_exp (LexState *ls, vardesc *v) { | |||
| 992 | s.top = 0; | 914 | s.top = 0; |
| 993 | prefixexp(ls, v, &s); | 915 | prefixexp(ls, v, &s); |
| 994 | while ((op = binop(ls->token)) >= 0) { | 916 | while ((op = binop(ls->token)) >= 0) { |
| 995 | lua_pushvar(ls, v); | 917 | close_exp(ls, v); |
| 996 | /* '^' is right associative, so must 'simulate' a higher priority */ | 918 | /* '^' is right associative, so must 'simulate' a higher priority */ |
| 997 | pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]); | 919 | pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]); |
| 998 | push(ls, &s, op); | 920 | push(ls, &s, op); |
| 999 | next(ls); | 921 | next(ls); |
| 1000 | prefixexp(ls, v, &s); | 922 | prefixexp(ls, v, &s); |
| 1001 | lua_pushvar(ls, v); | 923 | close_exp(ls, v); |
| 1002 | } | 924 | } |
| 1003 | if (s.top > 0) { | 925 | if (s.top > 0) { |
| 1004 | lua_pushvar(ls, v); | 926 | close_exp(ls, v); |
| 1005 | pop_to(ls, &s, 0); | 927 | pop_to(ls, &s, 0); |
| 1006 | } | 928 | } |
| 1007 | } | 929 | } |
| @@ -1010,7 +932,7 @@ static void arith_exp (LexState *ls, vardesc *v) { | |||
| 1010 | static void exp1 (LexState *ls) { | 932 | static void exp1 (LexState *ls) { |
| 1011 | vardesc v; | 933 | vardesc v; |
| 1012 | expr(ls, &v); | 934 | expr(ls, &v); |
| 1013 | lua_pushvar(ls, &v); | 935 | close_exp(ls, &v); |
| 1014 | } | 936 | } |
| 1015 | 937 | ||
| 1016 | 938 | ||
| @@ -1020,12 +942,12 @@ static void expr (LexState *ls, vardesc *v) { | |||
| 1020 | while (ls->token == AND || ls->token == OR) { | 942 | while (ls->token == AND || ls->token == OR) { |
| 1021 | OpCode op = (ls->token == AND) ? ONFJMP : ONTJMP; | 943 | OpCode op = (ls->token == AND) ? ONFJMP : ONTJMP; |
| 1022 | int pc; | 944 | int pc; |
| 1023 | lua_pushvar(ls, v); | 945 | close_exp(ls, v); |
| 1024 | next(ls); | 946 | next(ls); |
| 1025 | pc = code_S(ls, op, 0, -1); | 947 | pc = code_S(ls, op, 0, -1); |
| 1026 | arith_exp(ls, v); | 948 | arith_exp(ls, v); |
| 1027 | lua_pushvar(ls, v); | 949 | close_exp(ls, v); |
| 1028 | fix_jump(ls, pc, ls->fs->pc); | 950 | luaK_fixjump(ls, pc, ls->fs->pc); |
| 1029 | } | 951 | } |
| 1030 | } | 952 | } |
| 1031 | 953 | ||
| @@ -1054,7 +976,6 @@ static void block (LexState *ls) { | |||
| 1054 | static int assignment (LexState *ls, vardesc *v, int nvars) { | 976 | static int assignment (LexState *ls, vardesc *v, int nvars) { |
| 1055 | int left = 0; | 977 | int left = 0; |
| 1056 | checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment"); | 978 | checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment"); |
| 1057 | unloaddot(ls, v); | ||
| 1058 | if (ls->token == ',') { /* assignment -> ',' NAME assignment */ | 979 | if (ls->token == ',') { /* assignment -> ',' NAME assignment */ |
| 1059 | vardesc nv; | 980 | vardesc nv; |
| 1060 | next(ls); | 981 | next(ls); |
| @@ -1083,19 +1004,37 @@ static int assignment (LexState *ls, vardesc *v, int nvars) { | |||
| 1083 | } | 1004 | } |
| 1084 | 1005 | ||
| 1085 | 1006 | ||
| 1007 | /* maximum size of a while condition */ | ||
| 1008 | #ifndef MAX_WHILE_EXP | ||
| 1009 | #define MAX_WHILE_EXP 200 /* arbitrary limit */ | ||
| 1010 | #endif | ||
| 1011 | |||
| 1086 | static void whilestat (LexState *ls, int line) { | 1012 | static void whilestat (LexState *ls, int line) { |
| 1087 | /* whilestat -> WHILE exp1 DO block END */ | 1013 | /* whilestat -> WHILE exp1 DO block END */ |
| 1014 | Instruction buffer[MAX_WHILE_EXP]; | ||
| 1088 | FuncState *fs = ls->fs; | 1015 | FuncState *fs = ls->fs; |
| 1089 | int while_init = fs->pc; | 1016 | int while_init = fs->pc; |
| 1090 | int j1; | 1017 | int cond_size; |
| 1091 | next(ls); | 1018 | int i; |
| 1092 | exp1(ls); | 1019 | next(ls); /* skip WHILE */ |
| 1093 | j1 = code_U(ls, IFFJMP, 0, -1); /* jump to exit loop */ | 1020 | exp1(ls); /* read condition */ |
| 1021 | cond_size = fs->pc - while_init; | ||
| 1022 | /* save condition (to move it to after body) */ | ||
| 1023 | if (cond_size > MAX_WHILE_EXP) | ||
| 1024 | luaY_error(ls, "while condition too complex"); | ||
| 1025 | for (i=0; i<cond_size; i++) buffer[i] = fs->f->code[while_init+i]; | ||
| 1026 | /* go back to state prior condition */ | ||
| 1027 | fs->pc = while_init; | ||
| 1028 | deltastack(ls, -1); | ||
| 1029 | code_S(ls, JMP, 0, 0); /* initial jump to condition */ | ||
| 1094 | check(ls, DO); | 1030 | check(ls, DO); |
| 1095 | block(ls); | 1031 | block(ls); |
| 1096 | check_match(ls, END, WHILE, line); | 1032 | check_match(ls, END, WHILE, line); |
| 1097 | fix_jump(ls, code_U(ls, JMP, 0, 0), while_init); /* jump to keep loop */ | 1033 | luaK_fixjump(ls, while_init, fs->pc); |
| 1098 | fix_jump(ls, j1, fs->pc); | 1034 | /* copy condition to new position, and correct stack */ |
| 1035 | for (i=0; i<cond_size; i++) luaK_primitivecode(ls, buffer[i]); | ||
| 1036 | deltastack(ls, 1); | ||
| 1037 | luaK_fixjump(ls, code_S(ls, IFTJMP, 0, -1), while_init+1); | ||
| 1099 | } | 1038 | } |
| 1100 | 1039 | ||
| 1101 | 1040 | ||
| @@ -1107,7 +1046,7 @@ static void repeatstat (LexState *ls, int line) { | |||
| 1107 | block(ls); | 1046 | block(ls); |
| 1108 | check_match(ls, UNTIL, REPEAT, line); | 1047 | check_match(ls, UNTIL, REPEAT, line); |
| 1109 | exp1(ls); | 1048 | exp1(ls); |
| 1110 | fix_jump(ls, code_U(ls, IFFJMP, 0, -1), repeat_init); | 1049 | luaK_fixjump(ls, code_S(ls, IFFJMP, 0, -1), repeat_init); |
| 1111 | } | 1050 | } |
| 1112 | 1051 | ||
| 1113 | 1052 | ||
| @@ -1157,7 +1096,7 @@ static int funcname (LexState *ls, vardesc *v) { | |||
| 1157 | if (ls->token == ':' || ls->token == '.') { | 1096 | if (ls->token == ':' || ls->token == '.') { |
| 1158 | needself = (ls->token == ':'); | 1097 | needself = (ls->token == ':'); |
| 1159 | next(ls); | 1098 | next(ls); |
| 1160 | lua_pushvar(ls, v); | 1099 | close_exp(ls, v); |
| 1161 | code_kstr(ls, checkname(ls)); | 1100 | code_kstr(ls, checkname(ls)); |
| 1162 | v->k = VINDEXED; | 1101 | v->k = VINDEXED; |
| 1163 | } | 1102 | } |
| @@ -1188,7 +1127,7 @@ static void namestat (LexState *ls) { | |||
| 1188 | if (v.k == VEXP) { /* stat -> func */ | 1127 | if (v.k == VEXP) { /* stat -> func */ |
| 1189 | if (v.info == 0) /* is just an upper value? */ | 1128 | if (v.info == 0) /* is just an upper value? */ |
| 1190 | luaY_error(ls, "syntax error"); | 1129 | luaY_error(ls, "syntax error"); |
| 1191 | close_exp(ls, v.info, 0); | 1130 | close_call(ls, v.info, 0); /* call statement uses no results */ |
| 1192 | } | 1131 | } |
| 1193 | else { /* stat -> ['%'] NAME assignment */ | 1132 | else { /* stat -> ['%'] NAME assignment */ |
| 1194 | int left = assignment(ls, &v, 1); | 1133 | int left = assignment(ls, &v, 1); |
| @@ -1200,14 +1139,16 @@ static void namestat (LexState *ls) { | |||
| 1200 | static void ifpart (LexState *ls, int line) { | 1139 | static void ifpart (LexState *ls, int line) { |
| 1201 | /* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */ | 1140 | /* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */ |
| 1202 | FuncState *fs = ls->fs; | 1141 | FuncState *fs = ls->fs; |
| 1203 | int c; | 1142 | int c; /* address of the conditional jump */ |
| 1204 | int je; | 1143 | int je; /* address of the unconditional jump (to skip `else' part) */ |
| 1144 | int elseinit; | ||
| 1205 | next(ls); /* skip IF or ELSEIF */ | 1145 | next(ls); /* skip IF or ELSEIF */ |
| 1206 | exp1(ls); /* cond */ | 1146 | exp1(ls); /* cond */ |
| 1207 | c = code_U(ls, IFFJMP, 0, -1); /* jump `then' if `cond' is false */ | 1147 | c = code_S(ls, IFFJMP, 0, -1); /* jump `then' if `cond' is false */ |
| 1208 | check(ls, THEN); | 1148 | check(ls, THEN); |
| 1209 | block(ls); /* `then' part */ | 1149 | block(ls); /* `then' part */ |
| 1210 | je = code_U(ls, JMP, 0, 0); /* jump `else' part after `then' */ | 1150 | je = code_S(ls, JMP, 0, 0); /* jump `else' part after `then' */ |
| 1151 | elseinit = fs->pc; | ||
| 1211 | if (ls->token == ELSEIF) | 1152 | if (ls->token == ELSEIF) |
| 1212 | ifpart(ls, line); | 1153 | ifpart(ls, line); |
| 1213 | else { | 1154 | else { |
| @@ -1215,13 +1156,14 @@ static void ifpart (LexState *ls, int line) { | |||
| 1215 | block(ls); /* `else' part */ | 1156 | block(ls); /* `else' part */ |
| 1216 | check_match(ls, END, IF, line); | 1157 | check_match(ls, END, IF, line); |
| 1217 | } | 1158 | } |
| 1218 | if (fs->pc == je+1) { /* `else' part empty? */ | 1159 | if (fs->pc > elseinit) /* is there an `else' part? */ |
| 1160 | luaK_fixjump(ls, je, fs->pc); /* last jump jumps over it */ | ||
| 1161 | else { | ||
| 1219 | fs->pc--; /* remove last jump */ | 1162 | fs->pc--; /* remove last jump */ |
| 1220 | je--; /* first jump will be smaller */ | 1163 | elseinit--; /* first jump will be smaller */ |
| 1164 | LUA_ASSERT(L, fs->pc == je, "jump out of place"); | ||
| 1221 | } | 1165 | } |
| 1222 | else | 1166 | luaK_fixjump(ls, c, elseinit); /* fix first jump to `else' part */ |
| 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 */ | ||
| 1225 | } | 1167 | } |
| 1226 | 1168 | ||
| 1227 | 1169 | ||
| @@ -1329,13 +1271,8 @@ static void ret (LexState *ls) { | |||
| 1329 | check_debugline(ls); | 1271 | check_debugline(ls); |
| 1330 | next(ls); | 1272 | next(ls); |
| 1331 | explist(ls, &e); | 1273 | explist(ls, &e); |
| 1332 | if (e.pc > 0) { /* expression is an open function call? */ | 1274 | close_call(ls, e.pc, MULT_RET); |
| 1333 | Instruction *i = &ls->fs->f->code[e.pc]; | 1275 | code_U(ls, RETCODE, ls->fs->nlocalvar, 0); |
| 1334 | *i = SET_OPCODE(*i, TAILCALL); /* instead of a conventional CALL */ | ||
| 1335 | *i = SETARG_B(*i, ls->fs->nlocalvar); | ||
| 1336 | } | ||
| 1337 | else | ||
| 1338 | code_U(ls, RETCODE, ls->fs->nlocalvar, 0); | ||
| 1339 | ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ | 1276 | ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ |
| 1340 | optional(ls, ';'); | 1277 | optional(ls, ';'); |
| 1341 | } | 1278 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.h,v 1.4 1999/08/16 20:52:00 roberto Exp roberto $ | 2 | ** $Id: lparser.h,v 1.5 1999/11/22 13:12:07 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 | */ |
| @@ -8,9 +8,81 @@ | |||
| 8 | #define lparser_h | 8 | #define lparser_h |
| 9 | 9 | ||
| 10 | #include "lobject.h" | 10 | #include "lobject.h" |
| 11 | #include "lopcodes.h" | ||
| 11 | #include "lzio.h" | 12 | #include "lzio.h" |
| 12 | 13 | ||
| 13 | 14 | ||
| 15 | /* maximum number of local variables */ | ||
| 16 | #ifndef MAXLOCALS | ||
| 17 | #define MAXLOCALS 200 /* arbitrary limit (<=MAXARG_B) */ | ||
| 18 | #endif | ||
| 19 | |||
| 20 | |||
| 21 | /* maximum number of upvalues */ | ||
| 22 | #ifndef MAXUPVALUES | ||
| 23 | #define MAXUPVALUES 32 /* arbitrary limit (<=MAXARG_B) */ | ||
| 24 | #endif | ||
| 25 | |||
| 26 | |||
| 27 | /* maximum number of variables in the left side of an assignment */ | ||
| 28 | #ifndef MAXVARSLH | ||
| 29 | #define MAXVARSLH 100 /* arbitrary limit (<=MAXARG_B) */ | ||
| 30 | #endif | ||
| 31 | |||
| 32 | |||
| 33 | /* maximum number of parameters in a function */ | ||
| 34 | #ifndef MAXPARAMS | ||
| 35 | #define MAXPARAMS 100 /* arbitrary limit (<=MAXLOCALS) */ | ||
| 36 | #endif | ||
| 37 | |||
| 38 | |||
| 39 | /* maximum stack size in a function */ | ||
| 40 | #ifndef MAXSTACK | ||
| 41 | #define MAXSTACK 256 /* arbitrary limit (<=MAXARG_A) */ | ||
| 42 | #endif | ||
| 43 | |||
| 44 | |||
| 45 | #if MAXLOCALS>MAXARG_U || MAXUPVALUES>MAXARG_B || MAXVARSLH>MAXARG_B || \ | ||
| 46 | MAXPARAMS>MAXLOCALS || MAXSTACK>MAXARG_A || LFIELDS_PER_FLUSH>MAXARG_B | ||
| 47 | #error invalid limits | ||
| 48 | #endif | ||
| 49 | |||
| 50 | |||
| 51 | |||
| 52 | /* | ||
| 53 | ** Variable descriptor: | ||
| 54 | ** must include an `exp' option because LL(1) cannot distinguish | ||
| 55 | ** between variables, upvalues and function calls on first sight. | ||
| 56 | */ | ||
| 57 | typedef enum { | ||
| 58 | VGLOBAL, /* info is constant index of global name */ | ||
| 59 | VLOCAL, /* info is stack index */ | ||
| 60 | VINDEXED, /* no info (table and index are on the stack) */ | ||
| 61 | VEXP /* info is pc index of a call (or 0 if exp is closed) */ | ||
| 62 | } varkind; | ||
| 63 | |||
| 64 | typedef struct vardesc { | ||
| 65 | varkind k; | ||
| 66 | int info; | ||
| 67 | } vardesc; | ||
| 68 | |||
| 69 | |||
| 70 | /* state needed to generate code for a given function */ | ||
| 71 | typedef struct FuncState { | ||
| 72 | TProtoFunc *f; /* current function header */ | ||
| 73 | struct FuncState *prev; /* enclosing function */ | ||
| 74 | int pc; /* next position to code */ | ||
| 75 | int last_pc; /* last instruction coded (for optimizations) */ | ||
| 76 | int stacksize; /* number of values on activation register */ | ||
| 77 | int nlocalvar; /* number of active local variables */ | ||
| 78 | int nupvalues; /* number of upvalues */ | ||
| 79 | int nvars; /* number of entries in f->locvars (-1 if no debug information) */ | ||
| 80 | int lastsetline; /* line where last SETLINE was issued */ | ||
| 81 | vardesc upvalues[MAXUPVALUES]; /* upvalues */ | ||
| 82 | TaggedString *localvar[MAXLOCALS]; /* store local variable names */ | ||
| 83 | } FuncState; | ||
| 84 | |||
| 85 | |||
| 14 | TProtoFunc *luaY_parser (lua_State *L, ZIO *z); | 86 | TProtoFunc *luaY_parser (lua_State *L, ZIO *z); |
| 15 | 87 | ||
| 16 | 88 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 1.86 2000/02/11 16:52:54 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.87 2000/02/14 16:51:08 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 | */ |
| @@ -376,12 +376,18 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf, | |||
| 376 | top++; | 376 | top++; |
| 377 | break; | 377 | break; |
| 378 | 378 | ||
| 379 | case PUSHNUMBER: | 379 | case PUSHNUM: |
| 380 | ttype(top) = LUA_T_NUMBER; | 380 | ttype(top) = LUA_T_NUMBER; |
| 381 | nvalue(top) = tf->knum[GETARG_U(i)]; | 381 | nvalue(top) = tf->knum[GETARG_U(i)]; |
| 382 | top++; | 382 | top++; |
| 383 | break; | 383 | break; |
| 384 | 384 | ||
| 385 | case PUSHNEGNUM: | ||
| 386 | ttype(top) = LUA_T_NUMBER; | ||
| 387 | nvalue(top) = -tf->knum[GETARG_U(i)]; | ||
| 388 | top++; | ||
| 389 | break; | ||
| 390 | |||
| 385 | case PUSHUPVALUE: | 391 | case PUSHUPVALUE: |
| 386 | *top++ = cl->consts[GETARG_U(i)+1]; | 392 | *top++ = cl->consts[GETARG_U(i)+1]; |
| 387 | break; | 393 | break; |
| @@ -524,6 +530,16 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf, | |||
| 524 | top--; | 530 | top--; |
| 525 | break; | 531 | break; |
| 526 | 532 | ||
| 533 | case ADDI: | ||
| 534 | if (tonumber(top-1)) { | ||
| 535 | ttype(top) = LUA_T_NUMBER; | ||
| 536 | nvalue(top) = (real)GETARG_S(i); | ||
| 537 | call_arith(L, top+1, IM_ADD); | ||
| 538 | } | ||
| 539 | else | ||
| 540 | nvalue(top-1) += (real)GETARG_S(i); | ||
| 541 | break; | ||
| 542 | |||
| 527 | case SUBOP: | 543 | case SUBOP: |
| 528 | if (tonumber(top-1) || tonumber(top-2)) | 544 | if (tonumber(top-1) || tonumber(top-2)) |
| 529 | call_arith(L, top, IM_SUB); | 545 | call_arith(L, top, IM_SUB); |
| @@ -1,5 +1,5 @@ | |||
| 1 | # | 1 | # |
| 2 | ## $Id: makefile,v 1.20 1999/08/17 20:21:52 roberto Exp roberto $ | 2 | ## $Id: makefile,v 1.21 1999/10/04 17:51:04 roberto Exp roberto $ |
| 3 | ## Makefile | 3 | ## Makefile |
| 4 | ## See Copyright Notice in lua.h | 4 | ## See Copyright Notice in lua.h |
| 5 | # | 5 | # |
| @@ -20,14 +20,17 @@ | |||
| 20 | # | 20 | # |
| 21 | # define LUA_COMPAT_GC if you need garbage-collect tag methods for tables | 21 | # define LUA_COMPAT_GC if you need garbage-collect tag methods for tables |
| 22 | # (only for compatibility with previous versions) | 22 | # (only for compatibility with previous versions) |
| 23 | # | ||
| 24 | # define COMPAT_READPATTERN if you need read patterns | ||
| 25 | # (only for compatibility with previous versions) | ||
| 23 | 26 | ||
| 24 | CONFIG = -DPOPEN -D_POSIX_SOURCE | 27 | CONFIG = -DPOPEN -D_POSIX_SOURCE |
| 25 | #CONFIG = -DOLD_ANSI -DDEBUG -DLUA_COMPAT_GC | 28 | #CONFIG = -DOLD_ANSI -DDEBUG -DLUA_COMPAT_GC -DCOMPAT_READPATTERN |
| 26 | 29 | ||
| 27 | 30 | ||
| 28 | # Compilation parameters | 31 | # Compilation parameters |
| 29 | CC = gcc | 32 | CC = gcc |
| 30 | CWARNS = -Wall -Wmissing-prototypes -Wshadow -pedantic -Wpointer-arith -Wcast-align -Waggregate-return -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-declarations -Wnested-externs -Werror | 33 | CWARNS = -Wall -W -Wmissing-prototypes -Wshadow -pedantic -Wpointer-arith -Wcast-align -Waggregate-return -Wwrite-strings -Wcast-qual -Wnested-externs |
| 31 | CFLAGS = $(CONFIG) $(CWARNS) -ansi -O2 | 34 | CFLAGS = $(CONFIG) $(CWARNS) -ansi -O2 |
| 32 | 35 | ||
| 33 | 36 | ||
| @@ -45,6 +48,7 @@ LUAOBJS = \ | |||
| 45 | lauxlib.o \ | 48 | lauxlib.o \ |
| 46 | lbuffer.o \ | 49 | lbuffer.o \ |
| 47 | lbuiltin.o \ | 50 | lbuiltin.o \ |
| 51 | ldebug.o \ | ||
| 48 | ldo.o \ | 52 | ldo.o \ |
| 49 | lfunc.o \ | 53 | lfunc.o \ |
| 50 | lgc.o \ | 54 | lgc.o \ |
| @@ -52,6 +56,7 @@ LUAOBJS = \ | |||
| 52 | lmem.o \ | 56 | lmem.o \ |
| 53 | lobject.o \ | 57 | lobject.o \ |
| 54 | lparser.o \ | 58 | lparser.o \ |
| 59 | lcode.o \ | ||
| 55 | lref.o \ | 60 | lref.o \ |
| 56 | lstate.o \ | 61 | lstate.o \ |
| 57 | lstring.o \ | 62 | lstring.o \ |
| @@ -59,7 +64,8 @@ LUAOBJS = \ | |||
| 59 | ltm.o \ | 64 | ltm.o \ |
| 60 | lvm.o \ | 65 | lvm.o \ |
| 61 | lundump.o \ | 66 | lundump.o \ |
| 62 | lzio.o | 67 | lzio.o \ |
| 68 | ltests.o | ||
| 63 | 69 | ||
| 64 | LIBOBJS = \ | 70 | LIBOBJS = \ |
| 65 | liolib.o \ | 71 | liolib.o \ |
| @@ -86,9 +92,7 @@ liblua.so.1.0 : lua.o | |||
| 86 | 92 | ||
| 87 | clear : | 93 | clear : |
| 88 | rcsclean | 94 | rcsclean |
| 89 | rm -f *.o | 95 | rm -f *.o *.a |
| 90 | rm -f | ||
| 91 | co $(CO_OPTIONS) lua.h lualib.h luadebug.h | ||
| 92 | 96 | ||
| 93 | 97 | ||
| 94 | %.h : RCS/%.h,v | 98 | %.h : RCS/%.h,v |
| @@ -98,42 +102,47 @@ clear : | |||
| 98 | co $(CO_OPTIONS) $@ | 102 | co $(CO_OPTIONS) $@ |
| 99 | 103 | ||
| 100 | 104 | ||
| 101 | lapi.o: lapi.c lapi.h lua.h lobject.h lauxlib.h ldo.h lstate.h \ | 105 | lapi.o: lapi.c lapi.h lobject.h lua.h lauxlib.h ldo.h lstate.h \ |
| 102 | luadebug.h lfunc.h lgc.h lmem.h lref.h lstring.h ltable.h ltm.h lvm.h | 106 | luadebug.h lfunc.h lgc.h lmem.h lref.h lstring.h ltable.h ltm.h lvm.h |
| 103 | lauxlib.o: lauxlib.c lauxlib.h lua.h luadebug.h | 107 | lauxlib.o: lauxlib.c lauxlib.h lua.h luadebug.h |
| 104 | lbuffer.o: lbuffer.c lauxlib.h lua.h lmem.h lstate.h lobject.h \ | 108 | lbuffer.o: lbuffer.c lauxlib.h lua.h lmem.h lstate.h lobject.h \ |
| 105 | luadebug.h | 109 | luadebug.h |
| 106 | lbuiltin.o: lbuiltin.c lapi.h lua.h lobject.h lauxlib.h lbuiltin.h \ | 110 | lbuiltin.o: lbuiltin.c lapi.h lobject.h lua.h lauxlib.h lbuiltin.h \ |
| 107 | ldo.h lstate.h luadebug.h lfunc.h lmem.h lstring.h ltable.h ltm.h \ | 111 | ldo.h lstate.h luadebug.h lfunc.h lmem.h lstring.h ltable.h ltm.h \ |
| 108 | lundump.h lzio.h lvm.h | 112 | lundump.h lzio.h lvm.h |
| 113 | lcode.o: lcode.c lcode.h llex.h lobject.h lua.h lzio.h lmem.h \ | ||
| 114 | lopcodes.h lparser.h | ||
| 109 | ldblib.o: ldblib.c lauxlib.h lua.h luadebug.h lualib.h | 115 | ldblib.o: ldblib.c lauxlib.h lua.h luadebug.h lualib.h |
| 110 | ldo.o: ldo.c lauxlib.h lua.h ldo.h lobject.h lstate.h luadebug.h lgc.h \ | 116 | ldebug.o: ldebug.c lapi.h lobject.h lua.h lauxlib.h ldebug.h \ |
| 111 | lmem.h lparser.h lzio.h lstring.h ltm.h lundump.h lvm.h | 117 | luadebug.h ldo.h lstate.h lfunc.h ltable.h ltm.h |
| 118 | ldo.o: ldo.c lauxlib.h lua.h ldebug.h lobject.h luadebug.h ldo.h \ | ||
| 119 | lstate.h lgc.h lmem.h lparser.h lopcodes.h lzio.h lstring.h ltm.h \ | ||
| 120 | lundump.h lvm.h | ||
| 112 | lfunc.o: lfunc.c lfunc.h lobject.h lua.h lmem.h lstate.h luadebug.h | 121 | lfunc.o: lfunc.c lfunc.h lobject.h lua.h lmem.h lstate.h luadebug.h |
| 113 | lgc.o: lgc.c ldo.h lobject.h lua.h lstate.h luadebug.h lfunc.h lgc.h \ | 122 | lgc.o: lgc.c ldo.h lobject.h lua.h lstate.h luadebug.h lfunc.h lgc.h \ |
| 114 | lref.h lstring.h ltable.h ltm.h | 123 | lmem.h lref.h lstring.h ltable.h ltm.h |
| 115 | linit.o: linit.c lua.h lualib.h | 124 | linit.o: linit.c lua.h lualib.h |
| 116 | liolib.o: liolib.c lauxlib.h lua.h luadebug.h lualib.h | 125 | liolib.o: liolib.c lauxlib.h lua.h luadebug.h lualib.h |
| 117 | llex.o: llex.c lauxlib.h lua.h llex.h lobject.h lzio.h lmem.h \ | 126 | llex.o: llex.c lauxlib.h lua.h llex.h lobject.h lzio.h lmem.h \ |
| 118 | lparser.h lstate.h luadebug.h lstring.h | 127 | lparser.h lopcodes.h lstate.h luadebug.h lstring.h |
| 119 | lmathlib.o: lmathlib.c lauxlib.h lua.h lualib.h | 128 | lmathlib.o: lmathlib.c lauxlib.h lua.h lualib.h |
| 120 | lmem.o: lmem.c lmem.h lstate.h lobject.h lua.h luadebug.h | 129 | lmem.o: lmem.c lmem.h lua.h lobject.h lstate.h luadebug.h |
| 121 | lobject.o: lobject.c lobject.h lua.h | 130 | lobject.o: lobject.c lobject.h lua.h |
| 122 | lparser.o: lparser.c ldo.h lobject.h lua.h lstate.h luadebug.h lfunc.h \ | 131 | lparser.o: lparser.c lcode.h llex.h lobject.h lua.h lzio.h ldo.h \ |
| 123 | llex.h lzio.h lmem.h lopcodes.h lparser.h lstring.h | 132 | lstate.h luadebug.h lfunc.h lmem.h lopcodes.h lparser.h lstring.h |
| 124 | lref.o: lref.c lmem.h lref.h lobject.h lua.h lstate.h luadebug.h | 133 | lref.o: lref.c lapi.h lobject.h lua.h lmem.h lref.h lstate.h \ |
| 125 | lstate.o: lstate.c lbuiltin.h ldo.h lobject.h lua.h lstate.h \ | 134 | luadebug.h |
| 126 | luadebug.h lgc.h llex.h lzio.h lmem.h lstring.h ltm.h | 135 | lstate.o: lstate.c lauxlib.h lua.h lbuiltin.h ldo.h lobject.h lstate.h \ |
| 127 | lstring.o: lstring.c lmem.h lobject.h lua.h lstate.h luadebug.h \ | 136 | luadebug.h lgc.h llex.h lzio.h lmem.h lref.h lstring.h ltm.h |
| 137 | lstring.o: lstring.c lmem.h lua.h lobject.h lstate.h luadebug.h \ | ||
| 128 | lstring.h | 138 | lstring.h |
| 129 | lstrlib.o: lstrlib.c lauxlib.h lua.h lualib.h | 139 | lstrlib.o: lstrlib.c lauxlib.h lua.h lualib.h |
| 130 | ltable.o: ltable.c lauxlib.h lua.h lmem.h lobject.h lstate.h \ | 140 | ltable.o: ltable.c lauxlib.h lua.h lmem.h lobject.h lstate.h \ |
| 131 | luadebug.h ltable.h | 141 | luadebug.h ltable.h |
| 132 | ltm.o: ltm.c lauxlib.h lua.h lmem.h lobject.h lstate.h luadebug.h \ | 142 | ltm.o: ltm.c lauxlib.h lua.h lmem.h lobject.h lstate.h luadebug.h \ |
| 133 | ltm.h | 143 | ltm.h |
| 134 | lua.o: lua.c lua.h luadebug.h lualib.h | ||
| 135 | lundump.o: lundump.c lauxlib.h lua.h lfunc.h lobject.h lmem.h \ | 144 | lundump.o: lundump.c lauxlib.h lua.h lfunc.h lobject.h lmem.h \ |
| 136 | lopcodes.h lstring.h lundump.h lzio.h | 145 | lopcodes.h lstring.h lstate.h luadebug.h lundump.h lzio.h |
| 137 | lvm.o: lvm.c lauxlib.h lua.h ldo.h lobject.h lstate.h luadebug.h \ | 146 | lvm.o: lvm.c lauxlib.h lua.h ldebug.h lobject.h luadebug.h ldo.h \ |
| 138 | lfunc.h lgc.h lopcodes.h lstring.h ltable.h ltm.h lvm.h | 147 | lstate.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h ltm.h lvm.h |
| 139 | lzio.o: lzio.c lzio.h | 148 | lzio.o: lzio.c lzio.h |
