diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-03-08 16:10:32 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-03-08 16:10:32 -0300 |
commit | bd8b9c94b38ddaa3cd7324cbca98571633e03f91 (patch) | |
tree | 599551d4713dc039c2603e1830cc13acc9552779 /lparser.c | |
parent | 4db04555f06b90f3b2cda96c2f4aaeb78266ea86 (diff) | |
download | lua-bd8b9c94b38ddaa3cd7324cbca98571633e03f91.tar.gz lua-bd8b9c94b38ddaa3cd7324cbca98571633e03f91.tar.bz2 lua-bd8b9c94b38ddaa3cd7324cbca98571633e03f91.zip |
generic for (with any number of control variables)
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 84 |
1 files changed, 44 insertions, 40 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ | 2 | ** $Id: lparser.c,v 1.167 2002/02/14 21:46:58 roberto Exp $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -247,12 +247,12 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | |||
247 | } | 247 | } |
248 | 248 | ||
249 | 249 | ||
250 | static void code_params (LexState *ls, int nparams, short dots) { | 250 | static void code_params (LexState *ls, int nparams, int dots) { |
251 | FuncState *fs = ls->fs; | 251 | FuncState *fs = ls->fs; |
252 | adjustlocalvars(ls, nparams); | 252 | adjustlocalvars(ls, nparams); |
253 | luaX_checklimit(ls, fs->nactloc, MAXPARAMS, "parameters"); | 253 | luaX_checklimit(ls, fs->nactloc, MAXPARAMS, "parameters"); |
254 | fs->f->numparams = cast(short, fs->nactloc); /* `self' could be there already */ | 254 | fs->f->numparams = cast(lu_byte, fs->nactloc); |
255 | fs->f->is_vararg = dots; | 255 | fs->f->is_vararg = cast(lu_byte, dots); |
256 | if (dots) { | 256 | if (dots) { |
257 | new_localvarstr(ls, "arg", 0); | 257 | new_localvarstr(ls, "arg", 0); |
258 | adjustlocalvars(ls, 1); | 258 | adjustlocalvars(ls, 1); |
@@ -271,7 +271,7 @@ static void enterbreak (FuncState *fs, Breaklabel *bl) { | |||
271 | 271 | ||
272 | static void leavebreak (FuncState *fs, Breaklabel *bl) { | 272 | static void leavebreak (FuncState *fs, Breaklabel *bl) { |
273 | fs->bl = bl->previous; | 273 | fs->bl = bl->previous; |
274 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); | 274 | luaK_patchtohere(fs, bl->breaklist); |
275 | lua_assert(bl->nactloc == fs->nactloc); | 275 | lua_assert(bl->nactloc == fs->nactloc); |
276 | } | 276 | } |
277 | 277 | ||
@@ -471,8 +471,11 @@ static void recfield (LexState *ls, struct ConsControl *cc) { | |||
471 | FuncState *fs = ls->fs; | 471 | FuncState *fs = ls->fs; |
472 | int reg = ls->fs->freereg; | 472 | int reg = ls->fs->freereg; |
473 | expdesc key, val; | 473 | expdesc key, val; |
474 | if (ls->t.token == TK_NAME) | 474 | if (ls->t.token == TK_NAME) { |
475 | luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor"); | ||
476 | cc->nh++; | ||
475 | checkname(ls, &key); | 477 | checkname(ls, &key); |
478 | } | ||
476 | else /* ls->t.token == '[' */ | 479 | else /* ls->t.token == '[' */ |
477 | luaY_index(ls, &key); | 480 | luaY_index(ls, &key); |
478 | check(ls, '='); | 481 | check(ls, '='); |
@@ -481,8 +484,6 @@ static void recfield (LexState *ls, struct ConsControl *cc) { | |||
481 | luaK_exp2anyreg(fs, &val); | 484 | luaK_exp2anyreg(fs, &val); |
482 | luaK_codeABC(fs, OP_SETTABLE, val.info, cc->t->info, luaK_exp2RK(fs, &key)); | 485 | luaK_codeABC(fs, OP_SETTABLE, val.info, cc->t->info, luaK_exp2RK(fs, &key)); |
483 | fs->freereg = reg; /* free registers */ | 486 | fs->freereg = reg; /* free registers */ |
484 | luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor"); | ||
485 | cc->nh++; | ||
486 | } | 487 | } |
487 | 488 | ||
488 | 489 | ||
@@ -893,7 +894,7 @@ static void whilestat (LexState *ls, int line) { | |||
893 | check(ls, TK_DO); | 894 | check(ls, TK_DO); |
894 | block(ls); | 895 | block(ls); |
895 | luaK_patchlist(fs, luaK_jump(fs), while_init); | 896 | luaK_patchlist(fs, luaK_jump(fs), while_init); |
896 | luaK_patchlist(fs, v.f, luaK_getlabel(fs)); | 897 | luaK_patchtohere(fs, v.f); |
897 | check_match(ls, TK_END, TK_WHILE, line); | 898 | check_match(ls, TK_END, TK_WHILE, line); |
898 | leavebreak(fs, &bl); | 899 | leavebreak(fs, &bl); |
899 | } | 900 | } |
@@ -922,24 +923,11 @@ static void exp1 (LexState *ls) { | |||
922 | } | 923 | } |
923 | 924 | ||
924 | 925 | ||
925 | static void forbody (LexState *ls, OpCode loopfor) { | ||
926 | /* forbody -> DO block END */ | ||
927 | FuncState *fs = ls->fs; | ||
928 | int basereg = fs->freereg - 3; | ||
929 | int prep = luaK_jump(fs); | ||
930 | int blockinit = luaK_getlabel(fs); | ||
931 | check(ls, TK_DO); | ||
932 | adjustlocalvars(ls, 3); /* scope for control variables */ | ||
933 | block(ls); | ||
934 | luaK_patchlist(fs, prep, luaK_getlabel(fs)); | ||
935 | luaK_patchlist(fs, luaK_codeAsBc(fs, loopfor, basereg, NO_JUMP), blockinit); | ||
936 | removelocalvars(ls, 3, 1); | ||
937 | } | ||
938 | |||
939 | |||
940 | static void fornum (LexState *ls, TString *varname) { | 926 | static void fornum (LexState *ls, TString *varname) { |
941 | /* fornum -> NAME = exp1,exp1[,exp1] forbody */ | 927 | /* fornum -> NAME = exp1,exp1[,exp1] DO body */ |
942 | FuncState *fs = ls->fs; | 928 | FuncState *fs = ls->fs; |
929 | int prep; | ||
930 | int base = fs->freereg; | ||
943 | new_localvar(ls, varname, 0); | 931 | new_localvar(ls, varname, 0); |
944 | new_localvarstr(ls, "(limit)", 1); | 932 | new_localvarstr(ls, "(limit)", 1); |
945 | new_localvarstr(ls, "(step)", 2); | 933 | new_localvarstr(ls, "(step)", 2); |
@@ -954,26 +942,42 @@ static void fornum (LexState *ls, TString *varname) { | |||
954 | luaK_reserveregs(fs, 1); | 942 | luaK_reserveregs(fs, 1); |
955 | } | 943 | } |
956 | luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1); | 944 | luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1); |
957 | forbody(ls, OP_FORLOOP); | 945 | luaK_jump(fs); |
946 | prep = luaK_getlabel(fs); | ||
947 | check(ls, TK_DO); | ||
948 | adjustlocalvars(ls, 3); /* scope for control variables */ | ||
949 | block(ls); | ||
950 | luaK_patchtohere(fs, prep-1); | ||
951 | luaK_patchlist(fs, luaK_codeAsBc(fs, OP_FORLOOP, base, NO_JUMP), prep); | ||
952 | removelocalvars(ls, 3, 1); | ||
958 | } | 953 | } |
959 | 954 | ||
960 | 955 | ||
961 | static void forlist (LexState *ls, TString *indexname) { | 956 | static void forlist (LexState *ls, TString *indexname) { |
962 | /* forlist -> NAME,NAME IN exp1 forbody */ | 957 | /* forlist -> NAME {,NAME} IN exp1 DO body */ |
963 | FuncState *fs = ls->fs; | 958 | FuncState *fs = ls->fs; |
959 | int nvars = 0; | ||
960 | int prep; | ||
961 | int base = fs->freereg; | ||
964 | new_localvarstr(ls, "(table)", 0); | 962 | new_localvarstr(ls, "(table)", 0); |
965 | new_localvar(ls, indexname, 1); | 963 | new_localvar(ls, indexname, ++nvars); |
966 | if (optional(ls, ',')) { | 964 | while (optional(ls, ',')) { |
967 | new_localvar(ls, str_checkname(ls), 2); | 965 | new_localvar(ls, str_checkname(ls), ++nvars); |
968 | next(ls); /* skip var name */ | 966 | next(ls); |
969 | } | 967 | } |
970 | else | ||
971 | new_localvarstr(ls, "(val)", 2); | ||
972 | check(ls, TK_IN); | 968 | check(ls, TK_IN); |
973 | exp1(ls); /* table */ | 969 | exp1(ls); /* table */ |
974 | luaK_reserveregs(fs, 2); /* registers for index and val */ | 970 | luaK_checkstack(fs, 2); /* at least two slots, to traverse tables */ |
975 | luaK_codeABC(fs, OP_LOADNIL, fs->freereg - 2, fs->freereg - 1, 0); | 971 | luaK_reserveregs(fs, nvars); /* registers for vars */ |
976 | forbody(ls, OP_TFORLOOP); | 972 | luaK_codeABC(fs, OP_LOADNIL, base+1, base+nvars, 0); |
973 | adjustlocalvars(ls, nvars+1); /* scope for control variables */ | ||
974 | luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); | ||
975 | prep = luaK_jump(fs); | ||
976 | check(ls, TK_DO); | ||
977 | block(ls); | ||
978 | luaK_patchlist(fs, luaK_jump(fs), prep-1); | ||
979 | luaK_patchtohere(fs, prep); | ||
980 | removelocalvars(ls, nvars+1, 1); | ||
977 | } | 981 | } |
978 | 982 | ||
979 | 983 | ||
@@ -1013,18 +1017,18 @@ static void ifstat (LexState *ls, int line) { | |||
1013 | test_then_block(ls, &v); /* IF cond THEN block */ | 1017 | test_then_block(ls, &v); /* IF cond THEN block */ |
1014 | while (ls->t.token == TK_ELSEIF) { | 1018 | while (ls->t.token == TK_ELSEIF) { |
1015 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | 1019 | luaK_concat(fs, &escapelist, luaK_jump(fs)); |
1016 | luaK_patchlist(fs, v.f, luaK_getlabel(fs)); | 1020 | luaK_patchtohere(fs, v.f); |
1017 | test_then_block(ls, &v); /* ELSEIF cond THEN block */ | 1021 | test_then_block(ls, &v); /* ELSEIF cond THEN block */ |
1018 | } | 1022 | } |
1019 | if (ls->t.token == TK_ELSE) { | 1023 | if (ls->t.token == TK_ELSE) { |
1020 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | 1024 | luaK_concat(fs, &escapelist, luaK_jump(fs)); |
1021 | luaK_patchlist(fs, v.f, luaK_getlabel(fs)); | 1025 | luaK_patchtohere(fs, v.f); |
1022 | next(ls); /* skip ELSE */ | 1026 | next(ls); /* skip ELSE */ |
1023 | block(ls); /* `else' part */ | 1027 | block(ls); /* `else' part */ |
1024 | } | 1028 | } |
1025 | else | 1029 | else |
1026 | luaK_concat(fs, &escapelist, v.f); | 1030 | luaK_concat(fs, &escapelist, v.f); |
1027 | luaK_patchlist(fs, escapelist, luaK_getlabel(fs)); | 1031 | luaK_patchtohere(fs, escapelist); |
1028 | check_match(ls, TK_END, TK_IF, line); | 1032 | check_match(ls, TK_END, TK_IF, line); |
1029 | } | 1033 | } |
1030 | 1034 | ||
@@ -1182,7 +1186,7 @@ static int statement (LexState *ls) { | |||
1182 | static void parlist (LexState *ls) { | 1186 | static void parlist (LexState *ls) { |
1183 | /* parlist -> [ param { `,' param } ] */ | 1187 | /* parlist -> [ param { `,' param } ] */ |
1184 | int nparams = 0; | 1188 | int nparams = 0; |
1185 | short dots = 0; | 1189 | int dots = 0; |
1186 | if (ls->t.token != ')') { /* is `parlist' not empty? */ | 1190 | if (ls->t.token != ')') { /* is `parlist' not empty? */ |
1187 | do { | 1191 | do { |
1188 | switch (ls->t.token) { | 1192 | switch (ls->t.token) { |