diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1997-09-16 16:33:21 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1997-09-16 16:33:21 -0300 |
commit | 8cd67ac676fd7ff6c085e1ad6675ba6af0cb1fc3 (patch) | |
tree | a428bf2e179afe7d43f3f7c1850aec99234adaa2 | |
parent | 9828893f7e73f39fa8ad268ca58a94929fa67d5c (diff) | |
download | lua-8cd67ac676fd7ff6c085e1ad6675ba6af0cb1fc3.tar.gz lua-8cd67ac676fd7ff6c085e1ad6675ba6af0cb1fc3.tar.bz2 lua-8cd67ac676fd7ff6c085e1ad6675ba6af0cb1fc3.zip |
Syntax analizer and code generator
-rw-r--r-- | lparser.h | 20 | ||||
-rw-r--r-- | lua.stx | 771 |
2 files changed, 444 insertions, 347 deletions
diff --git a/lparser.h b/lparser.h new file mode 100644 index 00000000..5df77abc --- /dev/null +++ b/lparser.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | ** $Id: $ | ||
3 | ** Syntax analizer and code generator | ||
4 | ** See Copyright Notice in lua.h | ||
5 | */ | ||
6 | |||
7 | #ifndef lparser_h | ||
8 | #define lparser_h | ||
9 | |||
10 | #include "lobject.h" | ||
11 | #include "lzio.h" | ||
12 | |||
13 | |||
14 | void luaY_codedebugline (int line); | ||
15 | TProtoFunc *luaY_parser (ZIO *z, char *chunkname); | ||
16 | void luaY_error (char *s); | ||
17 | void luaY_syntaxerror (char *s, char *token); | ||
18 | |||
19 | |||
20 | #endif | ||
@@ -1,84 +1,121 @@ | |||
1 | %{ | 1 | %{ |
2 | /* | ||
3 | ** $Id: $ | ||
4 | ** Syntax analizer and code generator | ||
5 | ** See Copyright Notice in lua.h | ||
6 | */ | ||
2 | 7 | ||
3 | char *rcs_luastx = "$Id: lua.stx,v 3.50 1997/07/31 20:46:59 roberto Exp roberto $"; | ||
4 | 8 | ||
5 | #include <stdlib.h> | 9 | #include <stdlib.h> |
6 | 10 | ||
7 | #include "luadebug.h" | 11 | #include "lauxlib.h" |
8 | #include "luamem.h" | 12 | #include "ldo.h" |
9 | #include "lex.h" | 13 | #include "lfunc.h" |
10 | #include "opcode.h" | 14 | #include "lglobal.h" |
11 | #include "hash.h" | 15 | #include "llex.h" |
12 | #include "inout.h" | 16 | #include "lmem.h" |
13 | #include "tree.h" | 17 | #include "lopcodes.h" |
14 | #include "table.h" | 18 | #include "lparser.h" |
19 | #include "lstring.h" | ||
15 | #include "lua.h" | 20 | #include "lua.h" |
16 | #include "func.h" | 21 | #include "luadebug.h" |
22 | #include "lzio.h" | ||
17 | 23 | ||
18 | /* to avoid warnings generated by yacc */ | ||
19 | int yyparse (void); | ||
20 | #define malloc luaI_malloc | ||
21 | #define realloc luaI_realloc | ||
22 | #define free luaI_free | ||
23 | 24 | ||
24 | #ifndef LISTING | 25 | /* to avoid warnings generated by yacc */ |
25 | #define LISTING 0 | 26 | int luaY_parse (void); |
26 | #endif | 27 | #define malloc luaM_malloc |
28 | #define realloc luaM_realloc | ||
29 | #define free luaM_free | ||
27 | 30 | ||
28 | #ifndef CODE_BLOCK | ||
29 | #define CODE_BLOCK 1000 | ||
30 | #endif | ||
31 | 31 | ||
32 | /* maximum number of local variables */ | ||
32 | #define MAXLOCALS 32 | 33 | #define MAXLOCALS 32 |
33 | 34 | ||
35 | /* maximum number of variables in a multiple assignment */ | ||
36 | #define MAXVAR 32 | ||
37 | |||
38 | /* maximum number of nested functions */ | ||
39 | #define MAXSTATES 6 | ||
40 | |||
41 | /* maximum number of upvalues */ | ||
42 | #define MAXUPVALUES 8 | ||
43 | |||
44 | /* | ||
45 | ** Variable descriptor: if n>0, represents global variable indexed | ||
46 | ** by (n-1); if n<0, represents local variable index (-n)-1; | ||
47 | ** if n==0, represents an indexed variable (table and index on top of stack) | ||
48 | ** Must be long to store negative Word values. | ||
49 | */ | ||
50 | typedef long vardesc; | ||
51 | |||
52 | |||
34 | /* state needed to generate code for a given function */ | 53 | /* state needed to generate code for a given function */ |
35 | struct State { | 54 | static struct State { |
36 | TFunc *f; /* current function header */ | 55 | TProtoFunc *f; /* current function header */ |
37 | int codesize; | ||
38 | int pc; /* next position to code */ | 56 | int pc; /* next position to code */ |
39 | TaggedString *localvar[MAXLOCALS]; /* store local variable names */ | 57 | TaggedString *localvar[MAXLOCALS]; /* store local variable names */ |
58 | int stacksize; /* number of values on activation register */ | ||
59 | int maxstacksize; /* maximum number of values on activation register */ | ||
40 | int nlocalvar; /* number of active local variables */ | 60 | int nlocalvar; /* number of active local variables */ |
41 | int maxconsts; /* size of consts vector */ | 61 | int nvars; /* number of entries in f->locvars */ |
42 | int nvars; /* total number of local variables (for debugging information) */ | 62 | int maxcode; /* size of f->code */ |
43 | int maxvars; /* = -1 if no debug information */ | 63 | int maxvars; /* size of f->locvars (-1 if no debug information) */ |
44 | } stateMain, stateFunc, *currState; | 64 | int maxconsts; /* size of f->consts */ |
45 | 65 | vardesc varbuffer[MAXVAR]; /* variables in an assignment list */ | |
46 | 66 | vardesc upvalues[MAXUPVALUES]; /* upvalues */ | |
47 | #define MAXVAR 32 | 67 | } *mainState, *currState; |
48 | static Long varbuffer[MAXVAR]; /* variables in an assignment list; | ||
49 | it's long to store negative Word values */ | ||
50 | static int nvarbuffer=0; /* number of variables at a list */ | ||
51 | 68 | ||
52 | 69 | ||
53 | int lua_debug = 0; | ||
54 | 70 | ||
55 | /* Internal functions */ | ||
56 | 71 | ||
57 | static void yyerror (char *s) | 72 | void luaY_syntaxerror (char *s, char *token) |
58 | { | 73 | { |
59 | luaI_syntaxerror(s); | 74 | if (token[0] == 0) |
75 | token = "<eof>"; | ||
76 | luaL_verror("%.100s;\n> last token read: \"%.50s\" at line %d in file %.50s", | ||
77 | s, token, luaX_linenumber, mainState->f->fileName->str); | ||
60 | } | 78 | } |
61 | 79 | ||
62 | static void check_space (int i) | 80 | |
81 | void luaY_error (char *s) | ||
63 | { | 82 | { |
64 | if (currState->pc+i >= currState->codesize) | 83 | luaY_syntaxerror(s, luaX_lasttoken()); |
65 | currState->codesize = growvector(&currState->f->code, currState->codesize, | ||
66 | Byte, codeEM, MAX_INT); | ||
67 | } | 84 | } |
68 | 85 | ||
69 | 86 | ||
70 | static void code_byte (Byte c) | 87 | static void code_byte (Byte c) |
71 | { | 88 | { |
72 | check_space(1); | 89 | if (currState->pc >= currState->maxcode) |
90 | currState->maxcode = luaM_growvector(&currState->f->code, | ||
91 | currState->maxcode, Byte, codeEM, MAX_INT); | ||
73 | currState->f->code[currState->pc++] = c; | 92 | currState->f->code[currState->pc++] = c; |
74 | } | 93 | } |
75 | 94 | ||
76 | 95 | ||
96 | static void deltastack (int delta) | ||
97 | { | ||
98 | currState->stacksize += delta; | ||
99 | if (currState->stacksize > currState->maxstacksize) { | ||
100 | if (currState->stacksize > 255) | ||
101 | luaY_error("expression too complex"); | ||
102 | currState->maxstacksize = currState->stacksize; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | |||
107 | static void code_opcode (OpCode op, int delta) | ||
108 | { | ||
109 | code_byte(op); | ||
110 | deltastack(delta); | ||
111 | } | ||
112 | |||
113 | |||
77 | static void code_word_at (int pc, int n) | 114 | static void code_word_at (int pc, int n) |
78 | { | 115 | { |
79 | Word w = n; | 116 | Word w = n; |
80 | if (w != n) | 117 | if (w != n) |
81 | yyerror("block too big"); | 118 | luaY_error("block too big"); |
82 | currState->f->code[pc] = n&0xFF; | 119 | currState->f->code[pc] = n&0xFF; |
83 | currState->f->code[pc+1] = n>>8; | 120 | currState->f->code[pc+1] = n>>8; |
84 | } | 121 | } |
@@ -92,11 +129,11 @@ static void code_word (int n) | |||
92 | static void code_constant (int c) | 129 | static void code_constant (int c) |
93 | { | 130 | { |
94 | if (c <= 255) { | 131 | if (c <= 255) { |
95 | code_byte(PUSHCONSTANTB); | 132 | code_opcode(PUSHCONSTANTB, 1); |
96 | code_byte(c); | 133 | code_byte(c); |
97 | } | 134 | } |
98 | else { | 135 | else { |
99 | code_byte(PUSHCONSTANT); | 136 | code_opcode(PUSHCONSTANT, 1); |
100 | code_word(c); | 137 | code_word(c); |
101 | } | 138 | } |
102 | } | 139 | } |
@@ -104,10 +141,10 @@ static void code_constant (int c) | |||
104 | 141 | ||
105 | static int next_constant (void) | 142 | static int next_constant (void) |
106 | { | 143 | { |
107 | TFunc *f = currState->f; | 144 | TProtoFunc *f = currState->f; |
108 | if (f->nconsts >= currState->maxconsts) { | 145 | if (f->nconsts >= currState->maxconsts) { |
109 | currState->maxconsts = | 146 | currState->maxconsts = |
110 | growvector(&f->consts, currState->maxconsts, TObject, | 147 | luaM_growvector(&f->consts, currState->maxconsts, TObject, |
111 | constantEM, MAX_WORD); | 148 | constantEM, MAX_WORD); |
112 | } | 149 | } |
113 | return f->nconsts++; | 150 | return f->nconsts++; |
@@ -116,7 +153,7 @@ static int next_constant (void) | |||
116 | 153 | ||
117 | static int string_constant (TaggedString *s) | 154 | static int string_constant (TaggedString *s) |
118 | { | 155 | { |
119 | TFunc *f = currState->f; | 156 | TProtoFunc *f = currState->f; |
120 | int c = s->u.s.constindex; | 157 | int c = s->u.s.constindex; |
121 | if (!(0 <= c && c < f->nconsts && | 158 | if (!(0 <= c && c < f->nconsts && |
122 | ttype(&f->consts[c]) == LUA_T_STRING && tsvalue(&f->consts[c]) == s)) { | 159 | ttype(&f->consts[c]) == LUA_T_STRING && tsvalue(&f->consts[c]) == s)) { |
@@ -125,7 +162,6 @@ static int string_constant (TaggedString *s) | |||
125 | tsvalue(&f->consts[c]) = s; | 162 | tsvalue(&f->consts[c]) = s; |
126 | s->u.s.constindex = c; /* hint for next time */ | 163 | s->u.s.constindex = c; /* hint for next time */ |
127 | } | 164 | } |
128 | luaI_releasestring(s); | ||
129 | return c; | 165 | return c; |
130 | } | 166 | } |
131 | 167 | ||
@@ -136,7 +172,7 @@ static void code_string (TaggedString *s) | |||
136 | } | 172 | } |
137 | 173 | ||
138 | 174 | ||
139 | #define LIM 10 | 175 | #define LIM 13 |
140 | static int real_constant (real r) | 176 | static int real_constant (real r) |
141 | { | 177 | { |
142 | /* check whether 'r' has appeared within the last LIM entries */ | 178 | /* check whether 'r' has appeared within the last LIM entries */ |
@@ -147,7 +183,7 @@ static int real_constant (real r) | |||
147 | if (ttype(&cnt[c]) == LUA_T_NUMBER && nvalue(&cnt[c]) == r) | 183 | if (ttype(&cnt[c]) == LUA_T_NUMBER && nvalue(&cnt[c]) == r) |
148 | return c; | 184 | return c; |
149 | } | 185 | } |
150 | /* not found; create a new entry */ | 186 | /* not found; create a luaM_new entry */ |
151 | c = next_constant(); | 187 | c = next_constant(); |
152 | cnt = currState->f->consts; /* 'next_constant' may reallocate this vector */ | 188 | cnt = currState->f->consts; /* 'next_constant' may reallocate this vector */ |
153 | ttype(&cnt[c]) = LUA_T_NUMBER; | 189 | ttype(&cnt[c]) = LUA_T_NUMBER; |
@@ -157,17 +193,17 @@ static int real_constant (real r) | |||
157 | 193 | ||
158 | 194 | ||
159 | static void code_number (real f) | 195 | static void code_number (real f) |
160 | { | 196 | { |
161 | Word i; | 197 | Word i; |
162 | if (f >= 0 && f <= (real)MAX_WORD && (real)(i=(Word)f) == f) { | 198 | if (f >= 0 && f <= (real)MAX_WORD && (real)(i=(Word)f) == f) { |
163 | /* f has an (short) integer value */ | 199 | /* f has an (short) integer value */ |
164 | if (i <= 2) code_byte(PUSH0 + i); | 200 | if (i <= 2) code_opcode(PUSH0 + i, 1); |
165 | else if (i <= 255) { | 201 | else if (i <= 255) { |
166 | code_byte(PUSHBYTE); | 202 | code_opcode(PUSHBYTE, 1); |
167 | code_byte(i); | 203 | code_byte(i); |
168 | } | 204 | } |
169 | else { | 205 | else { |
170 | code_byte(PUSHWORD); | 206 | code_opcode(PUSHWORD, 1); |
171 | code_word(i); | 207 | code_word(i); |
172 | } | 208 | } |
173 | } | 209 | } |
@@ -179,7 +215,7 @@ static void code_number (real f) | |||
179 | static void flush_record (int n) | 215 | static void flush_record (int n) |
180 | { | 216 | { |
181 | if (n == 0) return; | 217 | if (n == 0) return; |
182 | code_byte(STOREMAP); | 218 | code_opcode(SETMAP, -2*n); |
183 | code_byte(n); | 219 | code_byte(n); |
184 | } | 220 | } |
185 | 221 | ||
@@ -187,15 +223,13 @@ static void flush_list (int m, int n) | |||
187 | { | 223 | { |
188 | if (n == 0) return; | 224 | if (n == 0) return; |
189 | if (m == 0) | 225 | if (m == 0) |
190 | code_byte(STORELIST0); | 226 | code_opcode(SETLIST0, -n); |
191 | else | 227 | else if (m < 255) { |
192 | if (m < 255) | 228 | code_opcode(SETLIST, -n); |
193 | { | ||
194 | code_byte(STORELIST); | ||
195 | code_byte(m); | 229 | code_byte(m); |
196 | } | 230 | } |
197 | else | 231 | else |
198 | yyerror ("list constructor too long"); | 232 | luaY_error("list constructor too long"); |
199 | code_byte(n); | 233 | code_byte(n); |
200 | } | 234 | } |
201 | 235 | ||
@@ -204,7 +238,7 @@ static void luaI_registerlocalvar (TaggedString *varname, int line) | |||
204 | { | 238 | { |
205 | if (currState->maxvars != -1) { /* debug information? */ | 239 | if (currState->maxvars != -1) { /* debug information? */ |
206 | if (currState->nvars >= currState->maxvars) | 240 | if (currState->nvars >= currState->maxvars) |
207 | currState->maxvars = growvector(&currState->f->locvars, | 241 | currState->maxvars = luaM_growvector(&currState->f->locvars, |
208 | currState->maxvars, LocVar, "", MAX_WORD); | 242 | currState->maxvars, LocVar, "", MAX_WORD); |
209 | currState->f->locvars[currState->nvars].varname = varname; | 243 | currState->f->locvars[currState->nvars].varname = varname; |
210 | currState->f->locvars[currState->nvars].line = line; | 244 | currState->f->locvars[currState->nvars].line = line; |
@@ -221,12 +255,11 @@ static void luaI_unregisterlocalvar (int line) | |||
221 | 255 | ||
222 | static void store_localvar (TaggedString *name, int n) | 256 | static void store_localvar (TaggedString *name, int n) |
223 | { | 257 | { |
224 | luaI_fixstring(name); /* local var names cannot be GC */ | ||
225 | if (currState->nlocalvar+n < MAXLOCALS) | 258 | if (currState->nlocalvar+n < MAXLOCALS) |
226 | currState->localvar[currState->nlocalvar+n] = name; | 259 | currState->localvar[currState->nlocalvar+n] = name; |
227 | else | 260 | else |
228 | yyerror ("too many local variables"); | 261 | luaY_error("too many local variables"); |
229 | luaI_registerlocalvar(name, lua_linenumber); | 262 | luaI_registerlocalvar(name, luaX_linenumber); |
230 | } | 263 | } |
231 | 264 | ||
232 | static void add_localvar (TaggedString *name) | 265 | static void add_localvar (TaggedString *name) |
@@ -235,165 +268,202 @@ static void add_localvar (TaggedString *name) | |||
235 | currState->nlocalvar++; | 268 | currState->nlocalvar++; |
236 | } | 269 | } |
237 | 270 | ||
238 | static void add_varbuffer (Long var) | 271 | static void add_varbuffer (vardesc var, int n) |
239 | { | 272 | { |
240 | if (nvarbuffer < MAXVAR) | 273 | if (n >= MAXVAR) |
241 | varbuffer[nvarbuffer++] = var; | 274 | luaY_error("variable buffer overflow"); |
242 | else | 275 | currState->varbuffer[n] = var; |
243 | yyerror ("variable buffer overflow"); | ||
244 | } | 276 | } |
245 | 277 | ||
246 | 278 | ||
247 | /* | 279 | static int aux_localname (TaggedString *n, struct State *st) |
248 | ** Search a local name and if find return its index. If do not find return -1 | ||
249 | */ | ||
250 | static int lua_localname (TaggedString *n) | ||
251 | { | 280 | { |
252 | int i; | 281 | int i; |
253 | for (i=currState->nlocalvar-1; i >= 0; i--) | 282 | for (i=st->nlocalvar-1; i >= 0; i--) |
254 | if (n == currState->localvar[i]) return i; /* local var */ | 283 | if (n == st->localvar[i]) return i; /* local var index */ |
255 | return -1; /* global var */ | 284 | return -1; /* not found */ |
256 | } | 285 | } |
257 | 286 | ||
258 | /* | 287 | |
259 | ** Push a variable given a number. If number is positive, push global variable | 288 | static vardesc singlevar (TaggedString *n, struct State *st) |
260 | ** indexed by (number -1). If negative, push local indexed by ABS(number)-1. | 289 | { |
261 | ** Otherwise, if zero, push indexed variable (record). | 290 | int i = aux_localname(n, st); |
262 | */ | 291 | if (i == -1) { /* check shadowing */ |
263 | static void lua_pushvar (Long number) | 292 | int l; |
264 | { | 293 | for (l=1; l<=(st-mainState); l++) |
265 | if (number > 0) /* global var */ | 294 | if (aux_localname(n, st-l) >= 0) |
266 | { | 295 | luaY_syntaxerror("cannot access a variable in outer scope", n->str); |
267 | code_byte(PUSHGLOBAL); | 296 | return luaG_findsymbol(n)+1; /* positive value */ |
268 | code_word(number-1); | ||
269 | } | ||
270 | else if (number < 0) /* local var */ | ||
271 | { | ||
272 | number = (-number) - 1; | ||
273 | if (number < 10) code_byte(PUSHLOCAL0 + number); | ||
274 | else | ||
275 | { | ||
276 | code_byte(PUSHLOCAL); | ||
277 | code_byte(number); | ||
278 | } | 297 | } |
279 | } | 298 | else return -(i+1); /* negative value */ |
280 | else | ||
281 | { | ||
282 | code_byte(PUSHINDEXED); | ||
283 | } | ||
284 | } | 299 | } |
285 | 300 | ||
286 | static void lua_codeadjust (int n) | 301 | |
302 | static int indexupvalue (TaggedString *n) | ||
287 | { | 303 | { |
288 | n += currState->nlocalvar; | 304 | vardesc v = singlevar(n, currState-1); |
289 | if (n == 0) | 305 | int i; |
290 | code_byte(ADJUST0); | 306 | for (i=0; i<currState->f->nupvalues; i++) { |
291 | else { | 307 | if (currState->upvalues[i] == v) |
292 | code_byte(ADJUST); | 308 | return i; |
293 | code_byte(n); | ||
294 | } | 309 | } |
310 | /* new one */ | ||
311 | if (++currState->f->nupvalues > MAXUPVALUES) | ||
312 | luaY_error("too many upvalues in a single function"); | ||
313 | currState->upvalues[i] = v; /* i = currState->f->nupvalues - 1 */ | ||
314 | return i; | ||
295 | } | 315 | } |
296 | 316 | ||
297 | 317 | ||
318 | static void pushupvalue (TaggedString *n) | ||
319 | { | ||
320 | int i; | ||
321 | if (currState == mainState) | ||
322 | luaY_error("cannot access upvalue in main"); | ||
323 | if (aux_localname(n, currState) >= 0) | ||
324 | luaY_syntaxerror("cannot access an upvalue in current scope", n->str); | ||
325 | i = indexupvalue(n); | ||
326 | if (i == 0) | ||
327 | code_opcode(PUSHUPVALUE0, 1); | ||
328 | else { | ||
329 | code_opcode(PUSHUPVALUE, 1); | ||
330 | code_byte(i); | ||
331 | } | ||
332 | } | ||
333 | |||
298 | 334 | ||
299 | void luaI_codedebugline (int line) | 335 | void luaY_codedebugline (int line) |
300 | { | 336 | { |
301 | static int lastline = 0; | 337 | static int lastline = 0; |
302 | if (lua_debug && line != lastline) | 338 | if (lua_debug && line != lastline) { |
303 | { | 339 | code_opcode(SETLINE, 0); |
304 | code_byte(SETLINE); | ||
305 | code_word(line); | 340 | code_word(line); |
306 | lastline = line; | 341 | lastline = line; |
307 | } | 342 | } |
308 | } | 343 | } |
309 | 344 | ||
310 | static int adjust_functioncall (Long exp, int i) | 345 | |
346 | static void adjuststack (int n) | ||
347 | { | ||
348 | if (n > 0) { | ||
349 | code_opcode(POPS, -n); | ||
350 | code_byte(n); | ||
351 | } | ||
352 | else if (n < 0) { | ||
353 | if (n == -1) | ||
354 | code_opcode(PUSHNIL, 1); | ||
355 | else { | ||
356 | code_opcode(PUSHNILS, -n); | ||
357 | code_byte(-n); | ||
358 | } | ||
359 | } | ||
360 | } | ||
361 | |||
362 | |||
363 | static long adjust_functioncall (long exp, int i) | ||
311 | { | 364 | { |
312 | if (exp <= 0) | 365 | if (exp <= 0) |
313 | return -exp; /* exp is -list length */ | 366 | return -exp; /* exp is -list length */ |
314 | else { | 367 | else { |
315 | int temp = currState->f->code[exp]; | 368 | int temp = currState->f->code[exp]; |
316 | currState->f->code[exp] = i; | 369 | currState->f->code[exp] = i; |
370 | if (i != MULT_RET) | ||
371 | deltastack(i); | ||
317 | return temp+i; | 372 | return temp+i; |
318 | } | 373 | } |
319 | } | 374 | } |
320 | 375 | ||
321 | static void adjust_mult_assign (int vars, Long exps, int temps) | 376 | |
377 | static void adjust_mult_assign (int vars, long exps) | ||
322 | { | 378 | { |
323 | if (exps > 0) { /* must correct function call */ | 379 | if (exps > 0) { /* must correct function call */ |
324 | int diff = vars - currState->f->code[exps]; | 380 | int diff = currState->f->code[exps] - vars; |
325 | if (diff >= 0) | 381 | if (diff < 0) |
326 | adjust_functioncall(exps, diff); | 382 | adjust_functioncall(exps, -diff); |
327 | else { | 383 | else { |
328 | adjust_functioncall(exps, 0); | 384 | adjust_functioncall(exps, 0); |
329 | lua_codeadjust(temps); | 385 | adjuststack(diff); |
330 | } | 386 | } |
331 | } | 387 | } |
332 | else if (vars != -exps) | 388 | else adjuststack((-exps)-vars); |
333 | lua_codeadjust(temps); | ||
334 | } | 389 | } |
335 | 390 | ||
336 | static int close_parlist (int dots) | 391 | |
392 | static void code_args (int dots) | ||
337 | { | 393 | { |
338 | if (!dots) | 394 | if (!dots) { |
339 | lua_codeadjust(0); | 395 | code_opcode(ARGS, currState->nlocalvar); |
396 | code_byte(currState->nlocalvar); | ||
397 | } | ||
340 | else { | 398 | else { |
341 | code_byte(VARARGS); | 399 | code_opcode(VARARGS, currState->nlocalvar+1); |
342 | code_byte(currState->nlocalvar); | 400 | code_byte(currState->nlocalvar); |
343 | add_localvar(luaI_createstring("arg")); | 401 | add_localvar(luaS_new("arg")); |
344 | } | 402 | } |
345 | return lua_linenumber; | 403 | } |
346 | } | 404 | |
347 | 405 | ||
348 | 406 | static void lua_pushvar (vardesc number) | |
349 | static void storesinglevar (Long v) | 407 | { |
350 | { | 408 | if (number > 0) { /* global var */ |
351 | if (v > 0) /* global var */ | 409 | code_opcode(PUSHGLOBAL, 1); |
352 | { | 410 | code_word(number-1); |
353 | code_byte(STOREGLOBAL); | 411 | } |
354 | code_word(v-1); | 412 | else if (number < 0) { /* local var */ |
355 | } | 413 | number = (-number) - 1; |
356 | else if (v < 0) /* local var */ | 414 | if (number < 10) |
357 | { | 415 | code_opcode(PUSHLOCAL0 + number, 1); |
358 | int number = (-v) - 1; | 416 | else { |
359 | if (number < 10) code_byte(STORELOCAL0 + number); | 417 | code_opcode(PUSHLOCAL, 1); |
360 | else | 418 | code_byte(number); |
361 | { | 419 | } |
362 | code_byte(STORELOCAL); | 420 | } |
363 | code_byte(number); | 421 | else { |
364 | } | 422 | code_opcode(PUSHTABLE, -1); |
365 | } | ||
366 | else | ||
367 | code_byte(STOREINDEXED0); | ||
368 | } | ||
369 | |||
370 | |||
371 | static void lua_codestore (int i) | ||
372 | { | ||
373 | if (varbuffer[i] != 0) /* global or local var */ | ||
374 | storesinglevar(varbuffer[i]); | ||
375 | else /* indexed var */ | ||
376 | { | ||
377 | int j; | ||
378 | int upper=0; /* number of indexed variables upper */ | ||
379 | int param; /* number of itens until indexed expression */ | ||
380 | for (j=i+1; j <nvarbuffer; j++) | ||
381 | if (varbuffer[j] == 0) upper++; | ||
382 | param = upper*2 + i; | ||
383 | if (param == 0) | ||
384 | code_byte(STOREINDEXED0); | ||
385 | else | ||
386 | { | ||
387 | code_byte(STOREINDEXED); | ||
388 | code_byte(param); | ||
389 | } | 423 | } |
390 | } | ||
391 | } | 424 | } |
392 | 425 | ||
393 | static void codeIf (Long thenAdd, Long elseAdd) | 426 | |
427 | static void storevar (vardesc number) | ||
428 | { | ||
429 | if (number == 0) /* indexed var */ | ||
430 | code_opcode(SETTABLE0, -3); | ||
431 | else if (number > 0) { /* global var */ | ||
432 | code_opcode(SETGLOBAL, -1); | ||
433 | code_word(number-1); | ||
434 | } | ||
435 | else { /* number < 0 - local var */ | ||
436 | number = (-number) - 1; | ||
437 | if (number < 10) | ||
438 | code_opcode(SETLOCAL0 + number, -1); | ||
439 | else { | ||
440 | code_opcode(SETLOCAL, -1); | ||
441 | code_byte(number); | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | |||
446 | |||
447 | /* returns how many elements are left as 'garbage' on the stack */ | ||
448 | static int lua_codestore (int i, int left) | ||
394 | { | 449 | { |
395 | Long elseinit = elseAdd+sizeof(Word)+1; | 450 | if (currState->varbuffer[i] != 0 || /* global or local var or */ |
396 | if (currState->pc == elseinit) { /* no else */ | 451 | left+i == 0) { /* indexed var without values in between */ |
452 | storevar(currState->varbuffer[i]); | ||
453 | return left; | ||
454 | } | ||
455 | else { /* indexed var with values in between*/ | ||
456 | code_opcode(SETTABLE, -1); | ||
457 | code_byte(left+i); /* number of elements between table/index and value */ | ||
458 | return left+2; /* table/index are not poped, since they are not on top */ | ||
459 | } | ||
460 | } | ||
461 | |||
462 | |||
463 | static void codeIf (int thenAdd, int elseAdd) | ||
464 | { | ||
465 | int elseinit = elseAdd+sizeof(Word)+1; | ||
466 | if (currState->pc == elseinit) { /* no else part */ | ||
397 | currState->pc -= sizeof(Word)+1; | 467 | currState->pc -= sizeof(Word)+1; |
398 | elseinit = currState->pc; | 468 | elseinit = currState->pc; |
399 | } | 469 | } |
@@ -413,13 +483,39 @@ static void code_shortcircuit (int pc, Byte jmp) | |||
413 | } | 483 | } |
414 | 484 | ||
415 | 485 | ||
416 | static void init_state (TFunc *f) | 486 | static void codereturn (void) |
417 | { | 487 | { |
488 | code_opcode(RETCODE, 0); | ||
489 | code_byte(currState->nlocalvar); | ||
490 | currState->stacksize = currState->nlocalvar; | ||
491 | } | ||
492 | |||
493 | |||
494 | static void func_onstack (TProtoFunc *f) | ||
495 | { | ||
496 | int i; | ||
497 | int nupvalues = (currState+1)->f->nupvalues; | ||
498 | int c = next_constant(); | ||
499 | ttype(&currState->f->consts[c]) = LUA_T_PROTO; | ||
500 | currState->f->consts[c].value.tf = (currState+1)->f; | ||
501 | for (i=0; i<nupvalues; i++) | ||
502 | lua_pushvar((currState+1)->upvalues[i]); | ||
503 | code_constant(c); | ||
504 | code_opcode(CLOSURE, -nupvalues); | ||
505 | } | ||
506 | |||
507 | |||
508 | static void init_state (TaggedString *filename) | ||
509 | { | ||
510 | TProtoFunc *f = luaF_newproto(); | ||
511 | currState->stacksize = 0; | ||
512 | currState->maxstacksize = 0; | ||
418 | currState->nlocalvar = 0; | 513 | currState->nlocalvar = 0; |
419 | currState->f = f; | 514 | currState->f = f; |
515 | f->fileName = filename; | ||
420 | currState->pc = 0; | 516 | currState->pc = 0; |
421 | currState->codesize = CODE_BLOCK; | 517 | currState->maxcode = 0; |
422 | f->code = newvector(CODE_BLOCK, Byte); | 518 | f->code = NULL; |
423 | currState->maxconsts = 0; | 519 | currState->maxconsts = 0; |
424 | if (lua_debug) { | 520 | if (lua_debug) { |
425 | currState->nvars = 0; | 521 | currState->nvars = 0; |
@@ -427,74 +523,63 @@ static void init_state (TFunc *f) | |||
427 | } | 523 | } |
428 | else | 524 | else |
429 | currState->maxvars = -1; /* flag no debug information */ | 525 | currState->maxvars = -1; /* flag no debug information */ |
526 | code_byte(0); /* to be filled with stacksize */ | ||
430 | } | 527 | } |
431 | 528 | ||
432 | 529 | ||
433 | static void init_func (Long v) | 530 | static void init_func (void) |
434 | { | 531 | { |
435 | TFunc *f = new(TFunc); | 532 | if (currState-mainState >= MAXSTATES-1) |
436 | int c = next_constant(); | 533 | luaY_error("too many nested functions"); |
437 | ttype(&currState->f->consts[c]) = LUA_T_FUNCTION; | 534 | currState++; |
438 | currState->f->consts[c].value.tf = f; | 535 | init_state(mainState->f->fileName); |
439 | code_constant(c); | 536 | luaY_codedebugline(luaX_linenumber); |
440 | storesinglevar(v); | 537 | currState->f->lineDefined = luaX_linenumber; |
441 | currState = &stateFunc; | ||
442 | luaI_initTFunc(f); | ||
443 | init_state(f); | ||
444 | luaI_codedebugline(lua_linenumber); | ||
445 | } | 538 | } |
446 | 539 | ||
447 | 540 | ||
448 | static void codereturn (void) | ||
449 | { | ||
450 | if (currState->nlocalvar == 0) | ||
451 | code_byte(RETCODE0); | ||
452 | else | ||
453 | { | ||
454 | code_byte(RETCODE); | ||
455 | code_byte(currState->nlocalvar); | ||
456 | } | ||
457 | } | ||
458 | |||
459 | 541 | ||
460 | static void close_func (void) | 542 | static TProtoFunc *close_func (void) |
461 | { | 543 | { |
462 | codereturn(); | 544 | TProtoFunc *f = currState->f; |
463 | code_byte(ENDCODE); | 545 | code_opcode(ENDCODE, 0); |
464 | currState->f->code = shrinkvector(currState->f->code, currState->pc, Byte); | 546 | f->code[0] = currState->maxstacksize; |
465 | currState->f->consts = shrinkvector(currState->f->consts, | 547 | f->code = luaM_reallocvector(f->code, currState->pc, Byte); |
466 | currState->f->nconsts, TObject); | 548 | f->consts = luaM_reallocvector(f->consts, f->nconsts, TObject); |
467 | if (currState->maxvars != -1) { /* debug information? */ | 549 | if (currState->maxvars != -1) { /* debug information? */ |
468 | luaI_registerlocalvar(NULL, -1); /* flag end of vector */ | 550 | luaI_registerlocalvar(NULL, -1); /* flag end of vector */ |
469 | currState->f->locvars = shrinkvector(currState->f->locvars, | 551 | f->locvars = luaM_reallocvector(f->locvars, currState->nvars, LocVar); |
470 | currState->nvars, LocVar); | ||
471 | } | 552 | } |
553 | currState--; | ||
554 | return f; | ||
472 | } | 555 | } |
473 | 556 | ||
474 | 557 | ||
475 | /* | 558 | /* |
476 | ** Parse LUA code. | 559 | ** Parse LUA code. |
477 | */ | 560 | */ |
478 | void lua_parse (TFunc *tf) | 561 | TProtoFunc *luaY_parser (ZIO *z, char *chunkname) |
479 | { | 562 | { |
480 | currState = &stateMain; | 563 | struct State state[MAXSTATES]; |
481 | init_state(tf); | 564 | currState = mainState = &state[0]; |
482 | if (yyparse ()) lua_error("parse error"); | 565 | luaX_setinput(z); |
483 | currState = &stateMain; | 566 | init_state(luaS_new(chunkname)); |
484 | close_func(); | 567 | if (luaY_parse ()) lua_error("parse error"); |
568 | return close_func(); | ||
485 | } | 569 | } |
486 | 570 | ||
487 | 571 | ||
488 | %} | 572 | %} |
489 | 573 | ||
490 | 574 | ||
491 | %union | 575 | %union |
492 | { | 576 | { |
493 | int vInt; | 577 | int vInt; |
494 | real vReal; | 578 | real vReal; |
495 | char *pChar; | 579 | char *pChar; |
496 | Long vLong; | 580 | long vLong; |
497 | TaggedString *pTStr; | 581 | TaggedString *pTStr; |
582 | TProtoFunc *pFunc; | ||
498 | } | 583 | } |
499 | 584 | ||
500 | %start chunk | 585 | %start chunk |
@@ -509,7 +594,7 @@ void lua_parse (TFunc *tf) | |||
509 | %token <vReal> NUMBER | 594 | %token <vReal> NUMBER |
510 | %token <pTStr> NAME STRING | 595 | %token <pTStr> NAME STRING |
511 | 596 | ||
512 | %type <vLong> PrepJump | 597 | %type <vInt> PrepJump, PrepJumpPop |
513 | %type <vLong> exprlist, exprlist1 /* if > 0, points to function return | 598 | %type <vLong> exprlist, exprlist1 /* if > 0, points to function return |
514 | counter (which has list length); if <= 0, -list lenght */ | 599 | counter (which has list length); if <= 0, -list lenght */ |
515 | %type <vLong> functioncall, expr /* if != 0, points to function return | 600 | %type <vLong> functioncall, expr /* if != 0, points to function return |
@@ -518,8 +603,10 @@ void lua_parse (TFunc *tf) | |||
518 | %type <vInt> fieldlist, localdeclist, decinit | 603 | %type <vInt> fieldlist, localdeclist, decinit |
519 | %type <vInt> ffieldlist, ffieldlist1, semicolonpart | 604 | %type <vInt> ffieldlist, ffieldlist1, semicolonpart |
520 | %type <vInt> lfieldlist, lfieldlist1 | 605 | %type <vInt> lfieldlist, lfieldlist1 |
521 | %type <vInt> parlist, parlist1, par | 606 | %type <vInt> parlist1, par |
522 | %type <vLong> var, singlevar | 607 | %type <vLong> var, singlevar, funcname /* vardesc */ |
608 | %type <pFunc> body | ||
609 | |||
523 | 610 | ||
524 | %left AND OR | 611 | %left AND OR |
525 | %left EQ NE '>' '<' LE GE | 612 | %left EQ NE '>' '<' LE GE |
@@ -532,89 +619,82 @@ void lua_parse (TFunc *tf) | |||
532 | 619 | ||
533 | %% /* beginning of rules section */ | 620 | %% /* beginning of rules section */ |
534 | 621 | ||
535 | chunk : chunklist ret ; | ||
536 | |||
537 | chunklist : /* empty */ | ||
538 | | chunklist stat sc | ||
539 | | chunklist function | ||
540 | ; | ||
541 | 622 | ||
542 | function : FUNCTION funcname body | 623 | chunk : statlist ret |
543 | ; | 624 | ; |
544 | |||
545 | funcname : var { init_func($1); } | ||
546 | | varexp ':' NAME | ||
547 | { | ||
548 | code_string($3); | ||
549 | init_func(0); /* indexed variable */ | ||
550 | add_localvar(luaI_createstring("self")); | ||
551 | } | ||
552 | ; | ||
553 | |||
554 | body : '(' parlist ')' block END | ||
555 | { | ||
556 | close_func(); | ||
557 | currState->f->lineDefined = $2; | ||
558 | currState = &stateMain; /* change back to main code */ | ||
559 | } | ||
560 | ; | ||
561 | 625 | ||
562 | statlist : /* empty */ | 626 | statlist : /* empty */ |
563 | | statlist stat sc | 627 | | statlist stat sc { if (currState->stacksize != currState->nlocalvar) |
628 | { luaY_error("contagem"); exit(1); }} | ||
564 | ; | 629 | ; |
565 | 630 | ||
566 | sc : /* empty */ | ';' ; | 631 | sc : /* empty */ | ';' ; |
567 | 632 | ||
568 | stat : IF expr1 THEN PrepJump block PrepJump elsepart END | 633 | stat : IF expr1 THEN PrepJumpPop block PrepJump elsepart END |
569 | { codeIf($4, $6); } | 634 | { codeIf($4, $6); } |
570 | 635 | ||
571 | | WHILE {$<vLong>$=currState->pc;} expr1 DO PrepJump block PrepJump END | 636 | | WHILE {$<vInt>$=currState->pc;} expr1 DO PrepJumpPop block PrepJump END |
572 | { | 637 | { |
573 | currState->f->code[$5] = IFFJMP; | 638 | currState->f->code[$5] = IFFJMP; |
574 | code_word_at($5+1, currState->pc - ($5+sizeof(Word)+1)); | 639 | code_word_at($5+1, currState->pc - ($5+sizeof(Word)+1)); |
575 | currState->f->code[$7] = UPJMP; | 640 | currState->f->code[$7] = UPJMP; |
576 | code_word_at($7+1, currState->pc - ($<vLong>2)); | 641 | code_word_at($7+1, currState->pc - ($<vInt>2)); |
577 | } | 642 | } |
578 | 643 | ||
579 | | REPEAT {$<vLong>$=currState->pc;} block UNTIL expr1 PrepJump | 644 | | REPEAT {$<vInt>$=currState->pc;} block UNTIL expr1 PrepJumpPop |
580 | { | 645 | { |
581 | currState->f->code[$6] = IFFUPJMP; | 646 | currState->f->code[$6] = IFFUPJMP; |
582 | code_word_at($6+1, currState->pc - ($<vLong>2)); | 647 | code_word_at($6+1, currState->pc - ($<vInt>2)); |
583 | } | 648 | } |
584 | 649 | ||
585 | | varlist1 '=' exprlist1 | 650 | | varlist1 '=' exprlist1 |
586 | { | 651 | {{ |
587 | { | 652 | int i; |
588 | int i; | 653 | int left = 0; |
589 | adjust_mult_assign(nvarbuffer, $3, $1 * 2 + nvarbuffer); | 654 | adjust_mult_assign($1, $3); |
590 | for (i=nvarbuffer-1; i>=0; i--) | 655 | for (i=$1-1; i>=0; i--) |
591 | lua_codestore(i); | 656 | left = lua_codestore(i, left); |
592 | if ($1 > 1 || ($1 == 1 && varbuffer[0] != 0)) | 657 | adjuststack(left); /* remove eventual 'garbage' left on stack */ |
593 | lua_codeadjust(0); | 658 | }} |
594 | } | 659 | | functioncall |
595 | } | ||
596 | | functioncall {;} | ||
597 | | LOCAL localdeclist decinit | 660 | | LOCAL localdeclist decinit |
598 | { currState->nlocalvar += $2; | 661 | { |
599 | adjust_mult_assign($2, $3, 0); | 662 | currState->nlocalvar += $2; |
600 | } | 663 | adjust_mult_assign($2, $3); |
664 | } | ||
665 | | FUNCTION funcname body | ||
666 | { | ||
667 | func_onstack($3); | ||
668 | storevar($2); | ||
669 | } | ||
601 | ; | 670 | ; |
602 | 671 | ||
672 | block : {$<vInt>$ = currState->nlocalvar;} chunk | ||
673 | { | ||
674 | adjuststack(currState->nlocalvar - $<vInt>1); | ||
675 | for (; currState->nlocalvar > $<vInt>1; currState->nlocalvar--) | ||
676 | luaI_unregisterlocalvar(luaX_linenumber); | ||
677 | } | ||
678 | ; | ||
679 | |||
680 | funcname : var { init_func(); $$ = $1; } | ||
681 | | varexp ':' NAME | ||
682 | { | ||
683 | code_string($3); | ||
684 | $$ = 0; /* indexed variable */ | ||
685 | init_func(); | ||
686 | add_localvar(luaS_new("self")); | ||
687 | } | ||
688 | ; | ||
689 | |||
690 | body : '(' parlist ')' chunk END { $$ = close_func(); } | ||
691 | ; | ||
692 | |||
603 | elsepart : /* empty */ | 693 | elsepart : /* empty */ |
604 | | ELSE block | 694 | | ELSE block |
605 | | ELSEIF expr1 THEN PrepJump block PrepJump elsepart | 695 | | ELSEIF expr1 THEN PrepJumpPop block PrepJump elsepart |
606 | { codeIf($4, $6); } | 696 | { codeIf($4, $6); } |
607 | ; | 697 | ; |
608 | |||
609 | block : {$<vInt>$ = currState->nlocalvar;} statlist ret | ||
610 | { | ||
611 | if (currState->nlocalvar != $<vInt>1) { | ||
612 | for (; currState->nlocalvar > $<vInt>1; currState->nlocalvar--) | ||
613 | luaI_unregisterlocalvar(lua_linenumber); | ||
614 | lua_codeadjust(0); | ||
615 | } | ||
616 | } | ||
617 | ; | ||
618 | 698 | ||
619 | ret : /* empty */ | 699 | ret : /* empty */ |
620 | | RETURN exprlist sc | 700 | | RETURN exprlist sc |
@@ -625,30 +705,33 @@ ret : /* empty */ | |||
625 | ; | 705 | ; |
626 | 706 | ||
627 | PrepJump : /* empty */ | 707 | PrepJump : /* empty */ |
628 | { | 708 | { |
629 | $$ = currState->pc; | 709 | $$ = currState->pc; |
630 | code_byte(0); /* open space */ | 710 | code_opcode(0, 0); /* open space */ |
631 | code_word(0); | 711 | code_word(0); |
632 | } | 712 | } |
633 | ; | 713 | ; |
634 | 714 | ||
715 | PrepJumpPop : PrepJump { $$ = $1; deltastack(-1); /* pop condition */ } | ||
716 | ; | ||
717 | |||
635 | expr1 : expr { adjust_functioncall($1, 1); } | 718 | expr1 : expr { adjust_functioncall($1, 1); } |
636 | ; | 719 | ; |
637 | 720 | ||
638 | expr : '(' expr ')' { $$ = $2; } | 721 | expr : '(' expr ')' { $$ = $2; } |
639 | | expr1 EQ expr1 { code_byte(EQOP); $$ = 0; } | 722 | | expr1 EQ expr1 { code_opcode(EQOP, -1); $$ = 0; } |
640 | | expr1 '<' expr1 { code_byte(LTOP); $$ = 0; } | 723 | | expr1 '<' expr1 { code_opcode(LTOP, -1); $$ = 0; } |
641 | | expr1 '>' expr1 { code_byte(GTOP); $$ = 0; } | 724 | | expr1 '>' expr1 { code_opcode(GTOP, -1); $$ = 0; } |
642 | | expr1 NE expr1 { code_byte(EQOP); code_byte(NOTOP); $$ = 0; } | 725 | | expr1 NE expr1 { code_opcode(NEQOP, -1); $$ = 0; } |
643 | | expr1 LE expr1 { code_byte(LEOP); $$ = 0; } | 726 | | expr1 LE expr1 { code_opcode(LEOP, -1); $$ = 0; } |
644 | | expr1 GE expr1 { code_byte(GEOP); $$ = 0; } | 727 | | expr1 GE expr1 { code_opcode(GEOP, -1); $$ = 0; } |
645 | | expr1 '+' expr1 { code_byte(ADDOP); $$ = 0; } | 728 | | expr1 '+' expr1 { code_opcode(ADDOP, -1); $$ = 0; } |
646 | | expr1 '-' expr1 { code_byte(SUBOP); $$ = 0; } | 729 | | expr1 '-' expr1 { code_opcode(SUBOP, -1); $$ = 0; } |
647 | | expr1 '*' expr1 { code_byte(MULTOP); $$ = 0; } | 730 | | expr1 '*' expr1 { code_opcode(MULTOP, -1); $$ = 0; } |
648 | | expr1 '/' expr1 { code_byte(DIVOP); $$ = 0; } | 731 | | expr1 '/' expr1 { code_opcode(DIVOP, -1); $$ = 0; } |
649 | | expr1 '^' expr1 { code_byte(POWOP); $$ = 0; } | 732 | | expr1 '^' expr1 { code_opcode(POWOP, -1); $$ = 0; } |
650 | | expr1 CONC expr1 { code_byte(CONCOP); $$ = 0; } | 733 | | expr1 CONC expr1 { code_opcode(CONCOP, -1); $$ = 0; } |
651 | | '-' expr1 %prec UNARY { code_byte(MINUSOP); $$ = 0;} | 734 | | '-' expr1 %prec UNARY { code_opcode(MINUSOP, 0); $$ = 0;} |
652 | | table { $$ = 0; } | 735 | | table { $$ = 0; } |
653 | | varexp { $$ = 0;} | 736 | | varexp { $$ = 0;} |
654 | | NUMBER { code_number($1); $$ = 0; } | 737 | | NUMBER { code_number($1); $$ = 0; } |
@@ -657,45 +740,46 @@ expr : '(' expr ')' { $$ = $2; } | |||
657 | code_string($1); | 740 | code_string($1); |
658 | $$ = 0; | 741 | $$ = 0; |
659 | } | 742 | } |
660 | | NIL {code_byte(PUSHNIL); $$ = 0; } | 743 | | NIL {code_opcode(PUSHNIL, 1); $$ = 0; } |
661 | | functioncall { $$ = $1; } | 744 | | functioncall { $$ = $1; } |
662 | | NOT expr1 { code_byte(NOTOP); $$ = 0;} | 745 | | NOT expr1 { code_opcode(NOTOP, 0); $$ = 0;} |
663 | | expr1 AND PrepJump expr1 | 746 | | expr1 AND PrepJumpPop expr1 |
664 | { | 747 | { |
665 | code_shortcircuit($3, ONFJMP); | 748 | code_shortcircuit($3, ONFJMP); |
666 | $$ = 0; | 749 | $$ = 0; |
667 | } | 750 | } |
668 | | expr1 OR PrepJump expr1 | 751 | | expr1 OR PrepJumpPop expr1 |
669 | { | 752 | { |
670 | code_shortcircuit($3, ONTJMP); | 753 | code_shortcircuit($3, ONTJMP); |
671 | $$ = 0; | 754 | $$ = 0; |
672 | } | 755 | } |
756 | | FUNCTION { init_func(); } body { func_onstack($3); $$ = 0; } | ||
673 | ; | 757 | ; |
674 | 758 | ||
675 | table : | 759 | table : |
676 | { | 760 | { |
677 | code_byte(CREATEARRAY); | 761 | code_opcode(CREATEARRAY, 1); |
678 | $<vLong>$ = currState->pc; code_word(0); | 762 | $<vInt>$ = currState->pc; code_word(0); |
679 | } | 763 | } |
680 | '{' fieldlist '}' | 764 | '{' fieldlist '}' |
681 | { | 765 | { |
682 | code_word_at($<vLong>1, $3); | 766 | code_word_at($<vInt>1, $3); |
683 | } | 767 | } |
684 | ; | 768 | ; |
685 | 769 | ||
686 | functioncall : funcvalue funcParams | 770 | functioncall : funcvalue funcParams |
687 | { | 771 | { |
688 | code_byte(CALLFUNC); | 772 | code_opcode(CALLFUNC, -($1+$2+1)); /* ajdust counts results */ |
689 | code_byte($1+$2); | 773 | code_byte($1+$2); |
690 | $$ = currState->pc; | 774 | $$ = currState->pc; |
691 | code_byte(0); /* may be modified by other rules */ | 775 | code_byte(0); /* may be adjusted by other rules */ |
692 | } | 776 | } |
693 | ; | 777 | ; |
694 | 778 | ||
695 | funcvalue : varexp { $$ = 0; } | 779 | funcvalue : varexp { $$ = 0; } |
696 | | varexp ':' NAME | 780 | | varexp ':' NAME |
697 | { | 781 | { |
698 | code_byte(PUSHSELF); | 782 | code_opcode(PUSHSELF, 1); |
699 | code_word(string_constant($3)); | 783 | code_word(string_constant($3)); |
700 | $$ = 1; | 784 | $$ = 1; |
701 | } | 785 | } |
@@ -711,26 +795,26 @@ exprlist : /* empty */ { $$ = 0; } | |||
711 | ; | 795 | ; |
712 | 796 | ||
713 | exprlist1 : expr { if ($1 != 0) $$ = $1; else $$ = -1; } | 797 | exprlist1 : expr { if ($1 != 0) $$ = $1; else $$ = -1; } |
714 | | exprlist1 ',' { $<vLong>$ = adjust_functioncall($1, 1); } expr | 798 | | exprlist1 ',' { $<vLong>$ = adjust_functioncall($1, 1); } expr |
715 | { | 799 | { |
716 | if ($4 == 0) $$ = -($<vLong>3 + 1); /* -length */ | 800 | if ($4 == 0) $$ = -($<vLong>3 + 1); /* -length */ |
717 | else | 801 | else |
718 | { | 802 | { |
719 | adjust_functioncall($4, $<vLong>3); | 803 | currState->f->code[$4] = $<vLong>3; /* store list length */ |
720 | $$ = $4; | 804 | $$ = $4; |
721 | } | 805 | } |
722 | } | 806 | } |
723 | ; | 807 | ; |
724 | 808 | ||
725 | parlist : /* empty */ { $$ = close_parlist(0); } | 809 | parlist : /* empty */ { code_args(0); } |
726 | | parlist1 { $$ = close_parlist($1); } | 810 | | parlist1 { code_args($1); } |
727 | ; | 811 | ; |
728 | 812 | ||
729 | parlist1 : par { $$ = $1; } | 813 | parlist1 : par { $$ = $1; } |
730 | | parlist1 ',' par | 814 | | parlist1 ',' par |
731 | { | 815 | { |
732 | if ($1) | 816 | if ($1) |
733 | lua_error("invalid parameter list"); | 817 | luaY_error("invalid parameter list"); |
734 | $$ = $3; | 818 | $$ = $3; |
735 | } | 819 | } |
736 | ; | 820 | ; |
@@ -740,34 +824,35 @@ par : NAME { add_localvar($1); $$ = 0; } | |||
740 | ; | 824 | ; |
741 | 825 | ||
742 | fieldlist : lfieldlist | 826 | fieldlist : lfieldlist |
743 | { flush_list($1/FIELDS_PER_FLUSH, $1%FIELDS_PER_FLUSH); } | 827 | { flush_list($1/LFIELDS_PER_FLUSH, $1%LFIELDS_PER_FLUSH); } |
744 | semicolonpart | 828 | semicolonpart |
745 | { $$ = $1+$3; } | 829 | { $$ = $1+$3; } |
746 | | ffieldlist1 lastcomma | 830 | | ffieldlist1 lastcomma |
747 | { $$ = $1; flush_record($1%FIELDS_PER_FLUSH); } | 831 | { $$ = $1; flush_record($1%RFIELDS_PER_FLUSH); } |
748 | ; | 832 | ; |
749 | 833 | ||
750 | semicolonpart : /* empty */ | 834 | semicolonpart : /* empty */ |
751 | { $$ = 0; } | 835 | { $$ = 0; } |
752 | | ';' ffieldlist | 836 | | ';' ffieldlist |
753 | { $$ = $2; flush_record($2%FIELDS_PER_FLUSH); } | 837 | { $$ = $2; flush_record($2%RFIELDS_PER_FLUSH); } |
754 | ; | 838 | ; |
755 | 839 | ||
756 | lastcomma : /* empty */ | 840 | lastcomma : /* empty */ |
757 | | ',' | 841 | | ',' |
758 | ; | 842 | ; |
759 | 843 | ||
760 | ffieldlist : /* empty */ { $$ = 0; } | 844 | ffieldlist : /* empty */ { $$ = 0; } |
761 | | ffieldlist1 lastcomma { $$ = $1; } | 845 | | ffieldlist1 lastcomma { $$ = $1; } |
762 | ; | 846 | ; |
763 | 847 | ||
764 | ffieldlist1 : ffield {$$=1;} | 848 | ffieldlist1 : ffield {$$=1;} |
765 | | ffieldlist1 ',' ffield | 849 | | ffieldlist1 ',' ffield |
766 | { | 850 | { |
767 | $$=$1+1; | 851 | $$=$1+1; |
768 | if ($$%FIELDS_PER_FLUSH == 0) flush_record(FIELDS_PER_FLUSH); | 852 | if ($$%RFIELDS_PER_FLUSH == 0) |
853 | flush_record(RFIELDS_PER_FLUSH); | ||
769 | } | 854 | } |
770 | ; | 855 | ; |
771 | 856 | ||
772 | ffield : ffieldkey '=' expr1 | 857 | ffield : ffieldkey '=' expr1 |
773 | ; | 858 | ; |
@@ -784,26 +869,25 @@ lfieldlist1 : expr1 {$$=1;} | |||
784 | | lfieldlist1 ',' expr1 | 869 | | lfieldlist1 ',' expr1 |
785 | { | 870 | { |
786 | $$=$1+1; | 871 | $$=$1+1; |
787 | if ($$%FIELDS_PER_FLUSH == 0) | 872 | if ($$%LFIELDS_PER_FLUSH == 0) |
788 | flush_list($$/FIELDS_PER_FLUSH - 1, FIELDS_PER_FLUSH); | 873 | flush_list($$/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH); |
789 | } | 874 | } |
790 | ; | 875 | ; |
791 | 876 | ||
792 | varlist1 : var | 877 | varlist1 : var |
793 | { | 878 | { |
794 | nvarbuffer = 0; | 879 | $$ = 1; |
795 | add_varbuffer($1); | 880 | add_varbuffer($1, 0); |
796 | $$ = ($1 == 0) ? 1 : 0; | ||
797 | } | 881 | } |
798 | | varlist1 ',' var | 882 | | varlist1 ',' var |
799 | { | 883 | { |
800 | add_varbuffer($3); | 884 | add_varbuffer($3, $1); |
801 | $$ = ($3 == 0) ? $1 + 1 : $1; | 885 | $$ = $1+1; |
802 | } | 886 | } |
803 | ; | 887 | ; |
804 | 888 | ||
805 | var : singlevar { $$ = $1; } | 889 | var : singlevar { $$ = $1; } |
806 | | varexp '[' expr1 ']' | 890 | | varexp '[' expr1 ']' |
807 | { | 891 | { |
808 | $$ = 0; /* indexed variable */ | 892 | $$ = 0; /* indexed variable */ |
809 | } | 893 | } |
@@ -814,22 +898,15 @@ var : singlevar { $$ = $1; } | |||
814 | } | 898 | } |
815 | ; | 899 | ; |
816 | 900 | ||
817 | singlevar : NAME | 901 | singlevar : NAME { $$ = singlevar($1, currState); } |
818 | { | ||
819 | int local = lua_localname($1); | ||
820 | if (local == -1) /* global var */ | ||
821 | $$ = luaI_findsymbol($1)+1; /* return positive value */ | ||
822 | else | ||
823 | $$ = -(local+1); /* return negative value */ | ||
824 | luaI_fixstring($1); /* cannot GC variable names */ | ||
825 | } | ||
826 | ; | 902 | ; |
827 | 903 | ||
828 | varexp : var { lua_pushvar($1); } | 904 | varexp : var { lua_pushvar($1); } |
905 | | '%' NAME { pushupvalue($2); } | ||
829 | ; | 906 | ; |
830 | 907 | ||
831 | localdeclist : NAME {store_localvar($1, 0); $$ = 1;} | 908 | localdeclist : NAME {store_localvar($1, 0); $$ = 1;} |
832 | | localdeclist ',' NAME | 909 | | localdeclist ',' NAME |
833 | { | 910 | { |
834 | store_localvar($3, $1); | 911 | store_localvar($3, $1); |
835 | $$ = $1+1; | 912 | $$ = $1+1; |
@@ -839,5 +916,5 @@ localdeclist : NAME {store_localvar($1, 0); $$ = 1;} | |||
839 | decinit : /* empty */ { $$ = 0; } | 916 | decinit : /* empty */ { $$ = 0; } |
840 | | '=' exprlist1 { $$ = $2; } | 917 | | '=' exprlist1 { $$ = $2; } |
841 | ; | 918 | ; |
842 | 919 | ||
843 | %% | 920 | %% |