diff options
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 89 |
1 files changed, 63 insertions, 26 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.85 2000/05/10 16:33:20 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.86 2000/05/12 18:12:04 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 | */ |
@@ -205,7 +205,8 @@ static void store_localvar (LexState *ls, TString *name, int n) { | |||
205 | } | 205 | } |
206 | 206 | ||
207 | 207 | ||
208 | static void adjustlocalvars (LexState *ls, int nvars, int line) { | 208 | static void adjustlocalvars (LexState *ls, int nvars) { |
209 | int line = ls->fs->lastsetline; | ||
209 | FuncState *fs = ls->fs; | 210 | FuncState *fs = ls->fs; |
210 | int i; | 211 | int i; |
211 | fs->nlocalvar += nvars; | 212 | fs->nlocalvar += nvars; |
@@ -214,7 +215,8 @@ static void adjustlocalvars (LexState *ls, int nvars, int line) { | |||
214 | } | 215 | } |
215 | 216 | ||
216 | 217 | ||
217 | static void removelocalvars (LexState *ls, int nvars, int line) { | 218 | static void removelocalvars (LexState *ls, int nvars) { |
219 | int line = ls->fs->lastsetline; | ||
218 | ls->fs->nlocalvar -= nvars; | 220 | ls->fs->nlocalvar -= nvars; |
219 | while (nvars--) | 221 | while (nvars--) |
220 | luaI_unregisterlocalvar(ls, line); | 222 | luaI_unregisterlocalvar(ls, line); |
@@ -223,7 +225,7 @@ static void removelocalvars (LexState *ls, int nvars, int line) { | |||
223 | 225 | ||
224 | static void add_localvar (LexState *ls, const char *name) { | 226 | static void add_localvar (LexState *ls, const char *name) { |
225 | store_localvar(ls, luaS_newfixed(ls->L, name), 0); | 227 | store_localvar(ls, luaS_newfixed(ls->L, name), 0); |
226 | adjustlocalvars(ls, 1, 0); | 228 | adjustlocalvars(ls, 1); |
227 | } | 229 | } |
228 | 230 | ||
229 | 231 | ||
@@ -303,7 +305,7 @@ static void adjust_mult_assign (LexState *ls, int nvars, int nexps) { | |||
303 | 305 | ||
304 | static void code_args (LexState *ls, int nparams, int dots) { | 306 | static void code_args (LexState *ls, int nparams, int dots) { |
305 | FuncState *fs = ls->fs; | 307 | FuncState *fs = ls->fs; |
306 | adjustlocalvars(ls, nparams, 0); | 308 | adjustlocalvars(ls, nparams); |
307 | checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters"); | 309 | checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters"); |
308 | nparams = fs->nlocalvar; /* `self' could be there already */ | 310 | nparams = fs->nlocalvar; /* `self' could be there already */ |
309 | fs->f->numparams = nparams; | 311 | fs->f->numparams = nparams; |
@@ -838,7 +840,7 @@ static void block (LexState *ls) { | |||
838 | int nlocalvar = fs->nlocalvar; | 840 | int nlocalvar = fs->nlocalvar; |
839 | chunk(ls); | 841 | chunk(ls); |
840 | luaK_adjuststack(fs, fs->nlocalvar - nlocalvar); /* remove local variables */ | 842 | luaK_adjuststack(fs, fs->nlocalvar - nlocalvar); /* remove local variables */ |
841 | removelocalvars(ls, fs->nlocalvar - nlocalvar, fs->lastsetline); | 843 | removelocalvars(ls, fs->nlocalvar - nlocalvar); |
842 | } | 844 | } |
843 | 845 | ||
844 | 846 | ||
@@ -907,15 +909,20 @@ static void repeatstat (LexState *ls, int line) { | |||
907 | } | 909 | } |
908 | 910 | ||
909 | 911 | ||
910 | static void forstat (LexState *ls, int line) { | 912 | static void forbody (LexState *ls, OpCode prepfor, OpCode loopfor) { |
911 | /* forstat -> FOR NAME '=' expr1 ',' expr1 [',' expr1] DO block END */ | ||
912 | FuncState *fs = ls->fs; | 913 | FuncState *fs = ls->fs; |
913 | int prep; | 914 | int prep = luaK_code0(fs, prepfor); |
914 | int blockinit; | 915 | int blockinit = luaK_getlabel(fs); |
915 | Breaklabel bl; | 916 | check(ls, TK_DO); |
916 | enterbreak(fs, &bl); | 917 | block(ls); |
917 | setline_and_next(ls); /* skip for */ | 918 | luaK_patchlist(fs, prep, luaK_getlabel(fs)); |
918 | store_localvar(ls, str_checkname(ls), 0); /* control variable */ | 919 | luaK_patchlist(fs, luaK_code0(fs, loopfor), blockinit); |
920 | } | ||
921 | |||
922 | |||
923 | static void fornum (LexState *ls, TString *varname) { | ||
924 | FuncState *fs = ls->fs; | ||
925 | store_localvar(ls, varname, 0); | ||
919 | check(ls, '='); | 926 | check(ls, '='); |
920 | exp1(ls); /* initial value */ | 927 | exp1(ls); /* initial value */ |
921 | check(ls, ','); | 928 | check(ls, ','); |
@@ -924,18 +931,49 @@ static void forstat (LexState *ls, int line) { | |||
924 | exp1(ls); /* optional step */ | 931 | exp1(ls); /* optional step */ |
925 | else | 932 | else |
926 | luaK_code1(fs, OP_PUSHINT, 1); /* default step */ | 933 | luaK_code1(fs, OP_PUSHINT, 1); /* default step */ |
927 | adjustlocalvars(ls, 1, 0); /* init scope for control variable */ | 934 | adjustlocalvars(ls, 1); /* scope for control variables */ |
928 | add_localvar(ls, " limit "); | 935 | add_localvar(ls, "*limit*"); |
929 | add_localvar(ls, " step "); | 936 | add_localvar(ls, "*step*"); |
930 | prep = luaK_code0(fs, OP_FORPREP); | 937 | forbody(ls, OP_FORPREP, OP_FORLOOP); |
931 | blockinit = luaK_getlabel(fs); | 938 | removelocalvars(ls, 3); |
932 | check(ls, TK_DO); | 939 | } |
933 | block(ls); | 940 | |
934 | luaK_patchlist(fs, prep, luaK_getlabel(fs)); | 941 | |
935 | luaK_patchlist(fs, luaK_code0(fs, OP_FORLOOP), blockinit); | 942 | static void forlist (LexState *ls, TString *indexname) { |
943 | TString *valname; | ||
944 | check(ls, ','); | ||
945 | valname = str_checkname(ls); | ||
946 | /* next test is dirty, but avoids `in' being a reserved word */ | ||
947 | if (ls->token != TK_NAME || ls->seminfo.ts != luaS_new(ls->L, "in")) | ||
948 | luaK_error(ls, "`in' expected"); | ||
949 | next(ls); /* skip `in' */ | ||
950 | exp1(ls); /* table */ | ||
951 | add_localvar(ls, "*table*"); | ||
952 | add_localvar(ls, "*counter*"); | ||
953 | store_localvar(ls, indexname, 0); | ||
954 | store_localvar(ls, valname, 1); | ||
955 | adjustlocalvars(ls, 2); /* scope for control variable */ | ||
956 | forbody(ls, OP_LFORPREP, OP_LFORLOOP); | ||
957 | removelocalvars(ls, 4); | ||
958 | } | ||
959 | |||
960 | |||
961 | static void forstat (LexState *ls, int line) { | ||
962 | /* forstat -> FOR NAME '=' expr1 ',' expr1 [',' expr1] DO block END */ | ||
963 | /* forstat -> FOR NAME1, NAME2 IN expr1 DO block END */ | ||
964 | FuncState *fs = ls->fs; | ||
965 | TString *varname; | ||
966 | Breaklabel bl; | ||
967 | enterbreak(fs, &bl); | ||
968 | setline_and_next(ls); /* skip `for' */ | ||
969 | varname = str_checkname(ls); /* first variable name */ | ||
970 | switch (ls->token) { | ||
971 | case '=': fornum(ls, varname); break; | ||
972 | case ',': forlist(ls, varname); break; | ||
973 | default: luaK_error(ls, "`=' or `,' expected"); | ||
974 | } | ||
936 | check_END(ls, TK_FOR, line); | 975 | check_END(ls, TK_FOR, line); |
937 | leavebreak(fs, &bl); | 976 | leavebreak(fs, &bl); |
938 | removelocalvars(ls, 3, fs->lastsetline); | ||
939 | } | 977 | } |
940 | 978 | ||
941 | 979 | ||
@@ -999,13 +1037,12 @@ static int decinit (LexState *ls) { | |||
999 | 1037 | ||
1000 | static void localstat (LexState *ls) { | 1038 | static void localstat (LexState *ls) { |
1001 | /* stat -> LOCAL localnamelist decinit */ | 1039 | /* stat -> LOCAL localnamelist decinit */ |
1002 | FuncState *fs = ls->fs; | ||
1003 | int nvars; | 1040 | int nvars; |
1004 | int nexps; | 1041 | int nexps; |
1005 | setline_and_next(ls); /* skip LOCAL */ | 1042 | setline_and_next(ls); /* skip LOCAL */ |
1006 | nvars = localnamelist(ls); | 1043 | nvars = localnamelist(ls); |
1007 | nexps = decinit(ls); | 1044 | nexps = decinit(ls); |
1008 | adjustlocalvars(ls, nvars, fs->lastsetline); | 1045 | adjustlocalvars(ls, nvars); |
1009 | adjust_mult_assign(ls, nvars, nexps); | 1046 | adjust_mult_assign(ls, nvars, nexps); |
1010 | } | 1047 | } |
1011 | 1048 | ||