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
Diffstat (limited to '')
| -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 | %% |
