diff options
Diffstat (limited to 'lparser.c')
| -rw-r--r-- | lparser.c | 73 |
1 files changed, 37 insertions, 36 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 1.97 2000/06/19 18:26:23 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.98 2000/06/21 18:13:56 roberto Exp roberto $ |
| 3 | ** LL(1) Parser and code generator for Lua | 3 | ** LL(1) Parser and code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -152,19 +152,19 @@ static int checkname (LexState *ls) { | |||
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | 154 | ||
| 155 | static void luaI_registerlocalvar (LexState *ls, TString *varname, int line) { | 155 | static void luaI_registerlocalvar (LexState *ls, TString *varname, int pc) { |
| 156 | FuncState *fs = ls->fs; | 156 | FuncState *fs = ls->fs; |
| 157 | if (fs->debug) { | 157 | if (fs->f->debug) { |
| 158 | Proto *f = fs->f; | 158 | Proto *f = fs->f; |
| 159 | luaM_growvector(ls->L, f->locvars, fs->nvars, 1, LocVar, "", MAX_INT); | 159 | luaM_growvector(ls->L, f->locvars, fs->nvars, 1, LocVar, "", MAX_INT); |
| 160 | f->locvars[fs->nvars].varname = varname; | 160 | f->locvars[fs->nvars].varname = varname; |
| 161 | f->locvars[fs->nvars].line = line; | 161 | f->locvars[fs->nvars].pc = pc; |
| 162 | fs->nvars++; | 162 | fs->nvars++; |
| 163 | } | 163 | } |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | 166 | ||
| 167 | static void store_localvar (LexState *ls, TString *name, int n) { | 167 | static void new_localvar (LexState *ls, TString *name, int n) { |
| 168 | FuncState *fs = ls->fs; | 168 | FuncState *fs = ls->fs; |
| 169 | luaX_checklimit(ls, fs->nlocalvar+n+1, MAXLOCALS, "local variables"); | 169 | luaX_checklimit(ls, fs->nlocalvar+n+1, MAXLOCALS, "local variables"); |
| 170 | fs->localvar[fs->nlocalvar+n] = name; | 170 | fs->localvar[fs->nlocalvar+n] = name; |
| @@ -172,27 +172,27 @@ static void store_localvar (LexState *ls, TString *name, int n) { | |||
| 172 | 172 | ||
| 173 | 173 | ||
| 174 | static void adjustlocalvars (LexState *ls, int nvars) { | 174 | static void adjustlocalvars (LexState *ls, int nvars) { |
| 175 | int line = ls->fs->lastsetline; | ||
| 176 | FuncState *fs = ls->fs; | 175 | FuncState *fs = ls->fs; |
| 177 | int i; | 176 | int i; |
| 177 | /* `pc' is first opcode where variable is already active */ | ||
| 178 | for (i=fs->nlocalvar; i<fs->nlocalvar+nvars; i++) | 178 | for (i=fs->nlocalvar; i<fs->nlocalvar+nvars; i++) |
| 179 | luaI_registerlocalvar(ls, fs->localvar[i], line); | 179 | luaI_registerlocalvar(ls, fs->localvar[i], fs->pc); |
| 180 | fs->nlocalvar += nvars; | 180 | fs->nlocalvar += nvars; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | 183 | ||
| 184 | static void removelocalvars (LexState *ls, int nvars) { | 184 | static void removelocalvars (LexState *ls, int nvars) { |
| 185 | int line = ls->fs->lastsetline; | 185 | FuncState *fs = ls->fs; |
| 186 | int i; | 186 | int i; |
| 187 | /* `pc' is first opcode where variable is already dead */ | ||
| 187 | for (i=0;i<nvars;i++) | 188 | for (i=0;i<nvars;i++) |
| 188 | luaI_registerlocalvar(ls, NULL, line); | 189 | luaI_registerlocalvar(ls, NULL, fs->pc); |
| 189 | ls->fs->nlocalvar -= nvars; | 190 | fs->nlocalvar -= nvars; |
| 190 | } | 191 | } |
| 191 | 192 | ||
| 192 | 193 | ||
| 193 | static void add_localvar (LexState *ls, const char *name) { | 194 | static void new_localvarstr (LexState *ls, const char *name, int n) { |
| 194 | store_localvar(ls, luaS_newfixed(ls->L, name), 0); | 195 | new_localvar(ls, luaS_newfixed(ls->L, name), n); |
| 195 | adjustlocalvars(ls, 1); | ||
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | 198 | ||
| @@ -277,8 +277,10 @@ static void code_params (LexState *ls, int nparams, int dots) { | |||
| 277 | luaX_checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters"); | 277 | luaX_checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters"); |
| 278 | fs->f->numparams = fs->nlocalvar; /* `self' could be there already */ | 278 | fs->f->numparams = fs->nlocalvar; /* `self' could be there already */ |
| 279 | fs->f->is_vararg = dots; | 279 | fs->f->is_vararg = dots; |
| 280 | if (dots) | 280 | if (dots) { |
| 281 | add_localvar(ls, "arg"); | 281 | new_localvarstr(ls, "arg", 0); |
| 282 | adjustlocalvars(ls, 1); | ||
| 283 | } | ||
| 282 | luaK_deltastack(fs, fs->nlocalvar); /* count parameters in the stack */ | 284 | luaK_deltastack(fs, fs->nlocalvar); /* count parameters in the stack */ |
| 283 | } | 285 | } |
| 284 | 286 | ||
| @@ -320,7 +322,6 @@ static void open_func (LexState *ls, FuncState *fs) { | |||
| 320 | fs->stacklevel = 0; | 322 | fs->stacklevel = 0; |
| 321 | fs->nlocalvar = 0; | 323 | fs->nlocalvar = 0; |
| 322 | fs->nupvalues = 0; | 324 | fs->nupvalues = 0; |
| 323 | fs->lastsetline = 0; | ||
| 324 | fs->bl = NULL; | 325 | fs->bl = NULL; |
| 325 | fs->f = f; | 326 | fs->f = f; |
| 326 | f->source = ls->source; | 327 | f->source = ls->source; |
| @@ -358,7 +359,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z) { | |||
| 358 | luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z))); | 359 | luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z))); |
| 359 | open_func(&lexstate, &funcstate); | 360 | open_func(&lexstate, &funcstate); |
| 360 | next(&lexstate); /* read first token */ | 361 | next(&lexstate); /* read first token */ |
| 361 | funcstate.debug = L->debug; /* previous `next' may scan a pragma */ | 362 | funcstate.f->debug = L->debug; /* previous `next' may scan a pragma */ |
| 362 | chunk(&lexstate); | 363 | chunk(&lexstate); |
| 363 | check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected"); | 364 | check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected"); |
| 364 | close_func(&lexstate); | 365 | close_func(&lexstate); |
| @@ -821,22 +822,23 @@ static void repeatstat (LexState *ls, int line) { | |||
| 821 | } | 822 | } |
| 822 | 823 | ||
| 823 | 824 | ||
| 824 | static void forbody (LexState *ls, OpCode prepfor, OpCode loopfor) { | 825 | static void forbody (LexState *ls, int nvar, OpCode prepfor, OpCode loopfor) { |
| 825 | /* forbody -> DO block END */ | 826 | /* forbody -> DO block END */ |
| 826 | FuncState *fs = ls->fs; | 827 | FuncState *fs = ls->fs; |
| 827 | int prep = luaK_code1(fs, prepfor, NO_JUMP); | 828 | int prep = luaK_code1(fs, prepfor, NO_JUMP); |
| 828 | int blockinit = luaK_getlabel(fs); | 829 | int blockinit = luaK_getlabel(fs); |
| 829 | check(ls, TK_DO); | 830 | check(ls, TK_DO); |
| 831 | adjustlocalvars(ls, nvar); /* scope for control variables */ | ||
| 830 | block(ls); | 832 | block(ls); |
| 831 | luaK_patchlist(fs, prep, luaK_getlabel(fs)); | 833 | luaK_patchlist(fs, prep, luaK_getlabel(fs)); |
| 832 | luaK_patchlist(fs, luaK_code1(fs, loopfor, NO_JUMP), blockinit); | 834 | luaK_patchlist(fs, luaK_code1(fs, loopfor, NO_JUMP), blockinit); |
| 835 | removelocalvars(ls, nvar); | ||
| 833 | } | 836 | } |
| 834 | 837 | ||
| 835 | 838 | ||
| 836 | static void fornum (LexState *ls, TString *varname) { | 839 | static void fornum (LexState *ls, TString *varname) { |
| 837 | /* fornum -> NAME = exp1,exp1[,exp1] forbody */ | 840 | /* fornum -> NAME = exp1,exp1[,exp1] forbody */ |
| 838 | FuncState *fs = ls->fs; | 841 | FuncState *fs = ls->fs; |
| 839 | store_localvar(ls, varname, 0); | ||
| 840 | check(ls, '='); | 842 | check(ls, '='); |
| 841 | exp1(ls); /* initial value */ | 843 | exp1(ls); /* initial value */ |
| 842 | check(ls, ','); | 844 | check(ls, ','); |
| @@ -845,11 +847,10 @@ static void fornum (LexState *ls, TString *varname) { | |||
| 845 | exp1(ls); /* optional step */ | 847 | exp1(ls); /* optional step */ |
| 846 | else | 848 | else |
| 847 | luaK_code1(fs, OP_PUSHINT, 1); /* default step */ | 849 | luaK_code1(fs, OP_PUSHINT, 1); /* default step */ |
| 848 | adjustlocalvars(ls, 1); /* scope for control variables */ | 850 | new_localvar(ls, varname, 0); |
| 849 | add_localvar(ls, "*limit*"); | 851 | new_localvarstr(ls, "*limit*", 1); |
| 850 | add_localvar(ls, "*count*"); | 852 | new_localvarstr(ls, "*step*", 2); |
| 851 | forbody(ls, OP_FORPREP, OP_FORLOOP); | 853 | forbody(ls, 3, OP_FORPREP, OP_FORLOOP); |
| 852 | removelocalvars(ls, 3); | ||
| 853 | } | 854 | } |
| 854 | 855 | ||
| 855 | 856 | ||
| @@ -864,13 +865,11 @@ static void forlist (LexState *ls, TString *indexname) { | |||
| 864 | "`in' expected"); | 865 | "`in' expected"); |
| 865 | next(ls); /* skip `in' */ | 866 | next(ls); /* skip `in' */ |
| 866 | exp1(ls); /* table */ | 867 | exp1(ls); /* table */ |
| 867 | add_localvar(ls, "*table*"); | 868 | new_localvarstr(ls, "*table*", 0); |
| 868 | add_localvar(ls, "*counter*"); | 869 | new_localvarstr(ls, "*counter*", 1); |
| 869 | store_localvar(ls, indexname, 0); | 870 | new_localvar(ls, indexname, 2); |
| 870 | store_localvar(ls, valname, 1); | 871 | new_localvar(ls, valname, 3); |
| 871 | adjustlocalvars(ls, 2); /* scope for control variable */ | 872 | forbody(ls, 4, OP_LFORPREP, OP_LFORLOOP); |
| 872 | forbody(ls, OP_LFORPREP, OP_LFORLOOP); | ||
| 873 | removelocalvars(ls, 4); | ||
| 874 | } | 873 | } |
| 875 | 874 | ||
| 876 | 875 | ||
| @@ -931,7 +930,7 @@ static void localstat (LexState *ls) { | |||
| 931 | int nexps; | 930 | int nexps; |
| 932 | do { | 931 | do { |
| 933 | next(ls); /* skip LOCAL or ',' */ | 932 | next(ls); /* skip LOCAL or ',' */ |
| 934 | store_localvar(ls, str_checkname(ls), nvars++); | 933 | new_localvar(ls, str_checkname(ls), nvars++); |
| 935 | } while (ls->t.token == ','); | 934 | } while (ls->t.token == ','); |
| 936 | if (optional(ls, '=')) | 935 | if (optional(ls, '=')) |
| 937 | nexps = explist1(ls); | 936 | nexps = explist1(ls); |
| @@ -1072,7 +1071,7 @@ static void parlist (LexState *ls) { | |||
| 1072 | do { | 1071 | do { |
| 1073 | switch (ls->t.token) { | 1072 | switch (ls->t.token) { |
| 1074 | case TK_DOTS: next(ls); dots = 1; break; | 1073 | case TK_DOTS: next(ls); dots = 1; break; |
| 1075 | case TK_NAME: store_localvar(ls, str_checkname(ls), nparams++); break; | 1074 | case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break; |
| 1076 | default: luaK_error(ls, "<name> or `...' expected"); | 1075 | default: luaK_error(ls, "<name> or `...' expected"); |
| 1077 | } | 1076 | } |
| 1078 | } while (!dots && optional(ls, ',')); | 1077 | } while (!dots && optional(ls, ',')); |
| @@ -1086,10 +1085,12 @@ static void body (LexState *ls, int needself, int line) { | |||
| 1086 | FuncState new_fs; | 1085 | FuncState new_fs; |
| 1087 | open_func(ls, &new_fs); | 1086 | open_func(ls, &new_fs); |
| 1088 | new_fs.f->lineDefined = line; | 1087 | new_fs.f->lineDefined = line; |
| 1089 | new_fs.debug = ls->L->debug; | 1088 | new_fs.f->debug = ls->L->debug; |
| 1090 | check(ls, '('); | 1089 | check(ls, '('); |
| 1091 | if (needself) | 1090 | if (needself) { |
| 1092 | add_localvar(ls, "self"); | 1091 | new_localvarstr(ls, "self", 0); |
| 1092 | adjustlocalvars(ls, 1); | ||
| 1093 | } | ||
| 1093 | parlist(ls); | 1094 | parlist(ls); |
| 1094 | check(ls, ')'); | 1095 | check(ls, ')'); |
| 1095 | chunk(ls); | 1096 | chunk(ls); |
