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 |