diff options
Diffstat (limited to 'lparser.c')
| -rw-r--r-- | lparser.c | 147 |
1 files changed, 69 insertions, 78 deletions
| @@ -41,6 +41,7 @@ typedef struct Constdesc { | |||
| 41 | typedef struct Breaklabel { | 41 | typedef struct Breaklabel { |
| 42 | struct Breaklabel *previous; /* chain */ | 42 | struct Breaklabel *previous; /* chain */ |
| 43 | int breaklist; /* list of jumps out of this loop */ | 43 | int breaklist; /* list of jumps out of this loop */ |
| 44 | int nactloc; /* # of active local variables outside the breakable structure */ | ||
| 44 | } Breaklabel; | 45 | } Breaklabel; |
| 45 | 46 | ||
| 46 | 47 | ||
| @@ -163,13 +164,29 @@ static void new_localvar (LexState *ls, TString *name, int n) { | |||
| 163 | 164 | ||
| 164 | static void adjustlocalvars (LexState *ls, int nvars) { | 165 | static void adjustlocalvars (LexState *ls, int nvars) { |
| 165 | FuncState *fs = ls->fs; | 166 | FuncState *fs = ls->fs; |
| 166 | while (nvars--) | 167 | while (nvars--) { |
| 167 | fs->f->locvars[fs->actloc[fs->nactloc++]].startpc = fs->pc; | 168 | fs->f->locvars[fs->actloc[fs->nactloc]].startpc = fs->pc; |
| 169 | resetbit(fs->wasup, fs->nactloc); | ||
| 170 | fs->nactloc++; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | |||
| 175 | static void closelevel (LexState *ls, int level) { | ||
| 176 | FuncState *fs = ls->fs; | ||
| 177 | int i; | ||
| 178 | for (i=level; i<fs->nactloc; i++) | ||
| 179 | if (testbit(fs->wasup, i)) { | ||
| 180 | luaK_codeABC(fs, OP_CLOSE, level, 0, 0); | ||
| 181 | return; | ||
| 182 | } | ||
| 183 | return; /* nothing to close */ | ||
| 168 | } | 184 | } |
| 169 | 185 | ||
| 170 | 186 | ||
| 171 | static void removelocalvars (LexState *ls, int nvars) { | 187 | static void removelocalvars (LexState *ls, int nvars) { |
| 172 | FuncState *fs = ls->fs; | 188 | FuncState *fs = ls->fs; |
| 189 | closelevel(ls, fs->nactloc - nvars); | ||
| 173 | while (nvars--) | 190 | while (nvars--) |
| 174 | fs->f->locvars[fs->actloc[--fs->nactloc]].endpc = fs->pc; | 191 | fs->f->locvars[fs->actloc[--fs->nactloc]].endpc = fs->pc; |
| 175 | } | 192 | } |
| @@ -180,68 +197,47 @@ static void new_localvarstr (LexState *ls, const l_char *name, int n) { | |||
| 180 | } | 197 | } |
| 181 | 198 | ||
| 182 | 199 | ||
| 183 | static int search_local (LexState *ls, TString *n, expdesc *var) { | 200 | static int indexupvalue (FuncState *fs, expdesc *v) { |
| 184 | FuncState *fs; | ||
| 185 | int level = 0; | ||
| 186 | for (fs=ls->fs; fs; fs=fs->prev) { | ||
| 187 | int i; | ||
| 188 | for (i=fs->nactloc-1; i >= 0; i--) { | ||
| 189 | if (n == fs->f->locvars[fs->actloc[i]].varname) { | ||
| 190 | init_exp(var, VLOCAL, i); | ||
| 191 | return level; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | level++; /* `var' not found; check outer level */ | ||
| 195 | } | ||
| 196 | init_exp(var, VGLOBAL, 0); /* not found in any level; must be global */ | ||
| 197 | return -1; | ||
| 198 | } | ||
| 199 | |||
| 200 | |||
| 201 | static void singlevar (LexState *ls, TString *n, expdesc *var) { | ||
| 202 | int level = search_local(ls, n, var); | ||
| 203 | if (level >= 1) /* neither local (0) nor global (-1)? */ | ||
| 204 | luaX_syntaxerror(ls, l_s("cannot access a variable in outer function"), | ||
| 205 | getstr(n)); | ||
| 206 | else if (level == -1) /* global? */ | ||
| 207 | var->u.i.info = luaK_stringk(ls->fs, n); | ||
| 208 | } | ||
| 209 | |||
| 210 | |||
| 211 | static int indexupvalue (LexState *ls, expdesc *v) { | ||
| 212 | FuncState *fs = ls->fs; | ||
| 213 | int i; | 201 | int i; |
| 214 | for (i=0; i<fs->f->nupvalues; i++) { | 202 | for (i=0; i<fs->f->nupvalues; i++) { |
| 215 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.i.info == v->u.i.info) | 203 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.i.info == v->u.i.info) |
| 216 | return i; | 204 | return i; |
| 217 | } | 205 | } |
| 218 | /* new one */ | 206 | /* new one */ |
| 219 | luaX_checklimit(ls, fs->f->nupvalues+1, MAXUPVALUES, l_s("upvalues")); | 207 | luaX_checklimit(fs->ls, fs->f->nupvalues+1, MAXUPVALUES, l_s("upvalues")); |
| 220 | fs->upvalues[fs->f->nupvalues] = *v; | 208 | fs->upvalues[fs->f->nupvalues] = *v; |
| 221 | return fs->f->nupvalues++; | 209 | return fs->f->nupvalues++; |
| 222 | } | 210 | } |
| 223 | 211 | ||
| 224 | 212 | ||
| 225 | static void codeupvalue (LexState *ls, expdesc *v, TString *n) { | 213 | static void singlevar (FuncState *fs, TString *n, expdesc *var, int baselevel) { |
| 226 | FuncState *fs = ls->fs; | 214 | if (fs == NULL) |
| 227 | int level; | 215 | init_exp(var, VGLOBAL, 0); /* not local in any level; global variable */ |
| 228 | level = search_local(ls, n, v); | 216 | else { /* look up at current level */ |
| 229 | if (level == -1) { /* global? */ | 217 | int i; |
| 230 | if (fs->prev == NULL) | 218 | for (i=fs->nactloc-1; i >= 0; i--) { |
| 231 | luaX_syntaxerror(ls, l_s("cannot access an upvalue at top level"), | 219 | if (n == fs->f->locvars[fs->actloc[i]].varname) { |
| 232 | getstr(n)); | 220 | if (!baselevel) |
| 233 | v->u.i.info = luaK_stringk(fs->prev, n); | 221 | setbit(fs->wasup, i); /* will be upvalue in some other level */ |
| 234 | } | 222 | init_exp(var, VLOCAL, i); |
| 235 | else if (level != 1) { | 223 | return; |
| 236 | luaX_syntaxerror(ls, | 224 | } |
| 237 | l_s("upvalue must be global or local to immediately outer function"), | 225 | } |
| 238 | getstr(n)); | 226 | /* not found at current level; try upper one */ |
| 227 | singlevar(fs->prev, n, var, 0); | ||
| 228 | if (var->k == VGLOBAL) { | ||
| 229 | if (baselevel) | ||
| 230 | var->u.i.info = luaK_stringk(fs, n); /* info points to global name */ | ||
| 231 | } | ||
| 232 | else { /* local variable in some upper level? */ | ||
| 233 | var->u.i.info = indexupvalue(fs, var); | ||
| 234 | var->k = VUPVAL; /* upvalue in this level */ | ||
| 235 | } | ||
| 239 | } | 236 | } |
| 240 | init_exp(v, VRELOCABLE, | ||
| 241 | luaK_codeABc(fs, OP_LOADUPVAL, 0, indexupvalue(ls, v))); | ||
| 242 | } | 237 | } |
| 243 | 238 | ||
| 244 | 239 | ||
| 240 | |||
| 245 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | 241 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { |
| 246 | FuncState *fs = ls->fs; | 242 | FuncState *fs = ls->fs; |
| 247 | int extra = nvars - nexps; | 243 | int extra = nvars - nexps; |
| @@ -278,6 +274,7 @@ static void code_params (LexState *ls, int nparams, short dots) { | |||
| 278 | 274 | ||
| 279 | static void enterbreak (FuncState *fs, Breaklabel *bl) { | 275 | static void enterbreak (FuncState *fs, Breaklabel *bl) { |
| 280 | bl->breaklist = NO_JUMP; | 276 | bl->breaklist = NO_JUMP; |
| 277 | bl->nactloc = fs->nactloc; | ||
| 281 | bl->previous = fs->bl; | 278 | bl->previous = fs->bl; |
| 282 | fs->bl = bl; | 279 | fs->bl = bl; |
| 283 | } | 280 | } |
| @@ -286,6 +283,7 @@ static void enterbreak (FuncState *fs, Breaklabel *bl) { | |||
| 286 | static void leavebreak (FuncState *fs, Breaklabel *bl) { | 283 | static void leavebreak (FuncState *fs, Breaklabel *bl) { |
| 287 | fs->bl = bl->previous; | 284 | fs->bl = bl->previous; |
| 288 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); | 285 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); |
| 286 | lua_assert(bl->nactloc == fs->nactloc); | ||
| 289 | } | 287 | } |
| 290 | 288 | ||
| 291 | 289 | ||
| @@ -293,16 +291,14 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { | |||
| 293 | FuncState *fs = ls->fs; | 291 | FuncState *fs = ls->fs; |
| 294 | Proto *f = fs->f; | 292 | Proto *f = fs->f; |
| 295 | int i; | 293 | int i; |
| 296 | int reg = fs->freereg; | ||
| 297 | for (i=0; i<func->f->nupvalues; i++) | ||
| 298 | luaK_exp2nextreg(fs, &func->upvalues[i]); | ||
| 299 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, | 294 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, |
| 300 | MAXARG_Bc, l_s("constant table overflow")); | 295 | MAXARG_Bc, l_s("constant table overflow")); |
| 301 | f->p[fs->np++] = func->f; | 296 | f->p[fs->np++] = func->f; |
| 302 | fs->freereg = reg; /* CLOSURE will consume those values */ | 297 | init_exp(v, VRELOCABLE, luaK_codeABc(fs, OP_CLOSURE, 0, fs->np-1)); |
| 303 | init_exp(v, VNONRELOC, reg); | 298 | for (i=0; i<func->f->nupvalues; i++) { |
| 304 | luaK_reserveregs(fs, 1); | 299 | luaK_exp2nextreg(fs, &func->upvalues[i]); |
| 305 | luaK_codeABc(fs, OP_CLOSURE, v->u.i.info, fs->np-1); | 300 | fs->freereg--; /* CLOSURE will use these values */ |
| 301 | } | ||
| 306 | } | 302 | } |
| 307 | 303 | ||
| 308 | 304 | ||
| @@ -337,9 +333,9 @@ static void close_func (LexState *ls) { | |||
| 337 | lua_State *L = ls->L; | 333 | lua_State *L = ls->L; |
| 338 | FuncState *fs = ls->fs; | 334 | FuncState *fs = ls->fs; |
| 339 | Proto *f = fs->f; | 335 | Proto *f = fs->f; |
| 336 | removelocalvars(ls, fs->nactloc); | ||
| 340 | luaK_codeABC(fs, OP_RETURN, 0, 0, 0); /* final return */ | 337 | luaK_codeABC(fs, OP_RETURN, 0, 0, 0); /* final return */ |
| 341 | luaK_getlabel(fs); /* close eventual list of pending jumps */ | 338 | luaK_getlabel(fs); /* close eventual list of pending jumps */ |
| 342 | removelocalvars(ls, fs->nactloc); | ||
| 343 | lua_assert(G(L)->roottable == fs->h); | 339 | lua_assert(G(L)->roottable == fs->h); |
| 344 | G(L)->roottable = fs->h->next; | 340 | G(L)->roottable = fs->h->next; |
| 345 | luaH_free(L, fs->h); | 341 | luaH_free(L, fs->h); |
| @@ -644,16 +640,18 @@ static void primaryexp (LexState *ls, expdesc *v) { | |||
| 644 | return; | 640 | return; |
| 645 | } | 641 | } |
| 646 | case TK_NAME: { | 642 | case TK_NAME: { |
| 647 | singlevar(ls, str_checkname(ls), v); | 643 | singlevar(ls->fs, str_checkname(ls), v, 1); |
| 648 | next(ls); | 644 | next(ls); |
| 649 | return; | 645 | return; |
| 650 | } | 646 | } |
| 651 | case l_c('%'): { | 647 | case l_c('%'): { /* for compatibility only */ |
| 652 | next(ls); /* skip `%' */ | 648 | next(ls); /* skip `%' */ |
| 653 | codeupvalue(ls, v, str_checkname(ls)); | 649 | singlevar(ls->fs, str_checkname(ls), v, 1); |
| 650 | check_condition(ls, v->k == VUPVAL, l_s("global upvalues are deprecated")); | ||
| 654 | next(ls); | 651 | next(ls); |
| 655 | break; | 652 | return; |
| 656 | } | 653 | } |
| 654 | |||
| 657 | default: { | 655 | default: { |
| 658 | luaK_error(ls, l_s("unexpected symbol")); | 656 | luaK_error(ls, l_s("unexpected symbol")); |
| 659 | return; | 657 | return; |
| @@ -812,7 +810,7 @@ static void block (LexState *ls) { | |||
| 812 | */ | 810 | */ |
| 813 | struct LHS_assign { | 811 | struct LHS_assign { |
| 814 | struct LHS_assign *prev; | 812 | struct LHS_assign *prev; |
| 815 | expdesc v; /* variable (global, local, or indexed) */ | 813 | expdesc v; /* variable (global, local, upvalue, or indexed) */ |
| 816 | }; | 814 | }; |
| 817 | 815 | ||
| 818 | 816 | ||
| @@ -847,9 +845,8 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | |||
| 847 | 845 | ||
| 848 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | 846 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { |
| 849 | expdesc e; | 847 | expdesc e; |
| 850 | check_condition(ls, lh->v.k == VLOCAL || lh->v.k == VGLOBAL || | 848 | check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, |
| 851 | lh->v.k == VINDEXED, | 849 | l_s("syntax error!!")); |
| 852 | l_s("syntax error")); | ||
| 853 | if (ls->t.token == l_c(',')) { /* assignment -> `,' simpleexp assignment */ | 850 | if (ls->t.token == l_c(',')) { /* assignment -> `,' simpleexp assignment */ |
| 854 | struct LHS_assign nv; | 851 | struct LHS_assign nv; |
| 855 | nv.prev = lh; | 852 | nv.prev = lh; |
| @@ -1054,7 +1051,7 @@ static void localstat (LexState *ls) { | |||
| 1054 | static int funcname (LexState *ls, expdesc *v) { | 1051 | static int funcname (LexState *ls, expdesc *v) { |
| 1055 | /* funcname -> NAME {field} [`:' NAME] */ | 1052 | /* funcname -> NAME {field} [`:' NAME] */ |
| 1056 | int needself = 0; | 1053 | int needself = 0; |
| 1057 | singlevar(ls, str_checkname(ls), v); | 1054 | singlevar(ls->fs, str_checkname(ls), v, 1); |
| 1058 | next(ls); /* skip var name */ | 1055 | next(ls); /* skip var name */ |
| 1059 | while (ls->t.token == l_c('.')) { | 1056 | while (ls->t.token == l_c('.')) { |
| 1060 | luaY_field(ls, v); | 1057 | luaY_field(ls, v); |
| @@ -1102,25 +1099,19 @@ static void retstat (LexState *ls) { | |||
| 1102 | if (block_follow(ls->t.token) || ls->t.token == l_c(';')) | 1099 | if (block_follow(ls->t.token) || ls->t.token == l_c(';')) |
| 1103 | first = nret = 0; /* return no values */ | 1100 | first = nret = 0; /* return no values */ |
| 1104 | else { | 1101 | else { |
| 1105 | int n = explist1(ls, &e); /* optional return values */ | 1102 | explist1(ls, &e); /* optional return values */ |
| 1106 | if (e.k == VCALL) { | 1103 | if (e.k == VCALL) { |
| 1107 | luaK_setcallreturns(fs, &e, LUA_MULTRET); | 1104 | luaK_setcallreturns(fs, &e, LUA_MULTRET); |
| 1108 | first = fs->nactloc; | 1105 | first = fs->nactloc; |
| 1109 | nret = NO_REG; /* return all values */ | 1106 | nret = NO_REG; /* return all values */ |
| 1110 | } | 1107 | } |
| 1111 | else { | 1108 | else { |
| 1112 | if (n == 1) { /* only one value? */ | 1109 | luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ |
| 1113 | luaK_exp2anyreg(fs, &e); | 1110 | first = fs->nactloc; |
| 1114 | first = e.u.i.info; | 1111 | nret = fs->freereg - first; /* return all `active' values */ |
| 1115 | nret = 1; /* return only this value */ | ||
| 1116 | } | ||
| 1117 | else { | ||
| 1118 | luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ | ||
| 1119 | first = fs->nactloc; | ||
| 1120 | nret = fs->freereg - first; /* return all `active' values */ | ||
| 1121 | } | ||
| 1122 | } | 1112 | } |
| 1123 | } | 1113 | } |
| 1114 | closelevel(ls, 0); | ||
| 1124 | luaK_codeABC(fs, OP_RETURN, first, nret, 0); | 1115 | luaK_codeABC(fs, OP_RETURN, first, nret, 0); |
| 1125 | fs->freereg = fs->nactloc; /* removes all temp values */ | 1116 | fs->freereg = fs->nactloc; /* removes all temp values */ |
| 1126 | } | 1117 | } |
| @@ -1133,8 +1124,8 @@ static void breakstat (LexState *ls) { | |||
| 1133 | if (!bl) | 1124 | if (!bl) |
| 1134 | luaK_error(ls, l_s("no loop to break")); | 1125 | luaK_error(ls, l_s("no loop to break")); |
| 1135 | next(ls); /* skip BREAK */ | 1126 | next(ls); /* skip BREAK */ |
| 1127 | closelevel(ls, bl->nactloc); | ||
| 1136 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); | 1128 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); |
| 1137 | /* correct stack for compiler and symbolic execution */ | ||
| 1138 | } | 1129 | } |
| 1139 | 1130 | ||
| 1140 | 1131 | ||
