diff options
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 44 |
1 files changed, 24 insertions, 20 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.207 2003/02/28 17:19:47 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.208 2003/04/03 13:35:34 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -1027,30 +1027,34 @@ static int exp1 (LexState *ls) { | |||
1027 | 1027 | ||
1028 | 1028 | ||
1029 | static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { | 1029 | static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { |
1030 | /* forbody -> DO block */ | ||
1030 | BlockCnt bl; | 1031 | BlockCnt bl; |
1031 | FuncState *fs = ls->fs; | 1032 | FuncState *fs = ls->fs; |
1032 | int prep, endfor; | 1033 | int prep, endfor; |
1033 | adjustlocalvars(ls, nvars); /* scope for all variables */ | 1034 | adjustlocalvars(ls, 3); /* control variables */ |
1034 | check(ls, TK_DO); | 1035 | check(ls, TK_DO); |
1035 | enterblock(fs, &bl, 1); /* loop block */ | 1036 | prep = luaK_codeAsBx(fs, (isnum ? OP_FORPREP : OP_TFORPREP), base, NO_JUMP); |
1036 | prep = luaK_getlabel(fs); | 1037 | enterblock(fs, &bl, 0); /* scope for declared variables */ |
1038 | adjustlocalvars(ls, nvars); | ||
1039 | luaK_reserveregs(fs, nvars); | ||
1037 | block(ls); | 1040 | block(ls); |
1038 | luaK_patchtohere(fs, prep-1); | 1041 | leaveblock(fs); /* end of scope for declared variables */ |
1042 | luaK_patchtohere(fs, prep); | ||
1039 | endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : | 1043 | endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : |
1040 | luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3); | 1044 | luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); |
1041 | luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ | 1045 | luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ |
1042 | luaK_patchlist(fs, (isnum) ? endfor : luaK_jump(fs), prep); | 1046 | luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); |
1043 | leaveblock(fs); | ||
1044 | } | 1047 | } |
1045 | 1048 | ||
1046 | 1049 | ||
1047 | static void fornum (LexState *ls, TString *varname, int line) { | 1050 | static void fornum (LexState *ls, TString *varname, int line) { |
1048 | /* fornum -> NAME = exp1,exp1[,exp1] DO body */ | 1051 | /* fornum -> NAME = exp1,exp1[,exp1] forbody */ |
1049 | FuncState *fs = ls->fs; | 1052 | FuncState *fs = ls->fs; |
1050 | int base = fs->freereg; | 1053 | int base = fs->freereg; |
1051 | new_localvar(ls, varname, 0); | 1054 | new_localvarstr(ls, "(for index)", 0); |
1052 | new_localvarstr(ls, "(for limit)", 1); | 1055 | new_localvarstr(ls, "(for limit)", 1); |
1053 | new_localvarstr(ls, "(for step)", 2); | 1056 | new_localvarstr(ls, "(for step)", 2); |
1057 | new_localvar(ls, varname, 3); | ||
1054 | check(ls, '='); | 1058 | check(ls, '='); |
1055 | exp1(ls); /* initial value */ | 1059 | exp1(ls); /* initial value */ |
1056 | check(ls, ','); | 1060 | check(ls, ','); |
@@ -1061,39 +1065,39 @@ static void fornum (LexState *ls, TString *varname, int line) { | |||
1061 | luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); | 1065 | luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); |
1062 | luaK_reserveregs(fs, 1); | 1066 | luaK_reserveregs(fs, 1); |
1063 | } | 1067 | } |
1064 | luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1); | 1068 | forbody(ls, base, line, 1, 1); |
1065 | luaK_jump(fs); | ||
1066 | forbody(ls, base, line, 3, 1); | ||
1067 | } | 1069 | } |
1068 | 1070 | ||
1069 | 1071 | ||
1070 | static void forlist (LexState *ls, TString *indexname) { | 1072 | static void forlist (LexState *ls, TString *indexname) { |
1071 | /* forlist -> NAME {,NAME} IN explist1 DO body */ | 1073 | /* forlist -> NAME {,NAME} IN explist1 forbody */ |
1072 | FuncState *fs = ls->fs; | 1074 | FuncState *fs = ls->fs; |
1073 | expdesc e; | 1075 | expdesc e; |
1074 | int nvars = 0; | 1076 | int nvars = 0; |
1075 | int line; | 1077 | int line; |
1076 | int base = fs->freereg; | 1078 | int base = fs->freereg; |
1079 | /* create control variables */ | ||
1077 | new_localvarstr(ls, "(for generator)", nvars++); | 1080 | new_localvarstr(ls, "(for generator)", nvars++); |
1078 | new_localvarstr(ls, "(for state)", nvars++); | 1081 | new_localvarstr(ls, "(for state)", nvars++); |
1082 | new_localvarstr(ls, "(for control)", nvars++); | ||
1083 | /* create declared variables */ | ||
1079 | new_localvar(ls, indexname, nvars++); | 1084 | new_localvar(ls, indexname, nvars++); |
1080 | while (testnext(ls, ',')) | 1085 | while (testnext(ls, ',')) |
1081 | new_localvar(ls, str_checkname(ls), nvars++); | 1086 | new_localvar(ls, str_checkname(ls), nvars++); |
1082 | check(ls, TK_IN); | 1087 | check(ls, TK_IN); |
1083 | line = ls->linenumber; | 1088 | line = ls->linenumber; |
1084 | adjust_assign(ls, nvars, explist1(ls, &e), &e); | 1089 | adjust_assign(ls, 3, explist1(ls, &e), &e); |
1085 | luaK_checkstack(fs, 3); /* extra space to call generator */ | 1090 | luaK_checkstack(fs, 3); /* extra space to call generator */ |
1086 | luaK_codeAsBx(fs, OP_TFORPREP, base, NO_JUMP); | 1091 | forbody(ls, base, line, nvars - 3, 0); |
1087 | forbody(ls, base, line, nvars, 0); | ||
1088 | } | 1092 | } |
1089 | 1093 | ||
1090 | 1094 | ||
1091 | static void forstat (LexState *ls, int line) { | 1095 | static void forstat (LexState *ls, int line) { |
1092 | /* forstat -> fornum | forlist */ | 1096 | /* forstat -> FOR (fornum | forlist) END */ |
1093 | FuncState *fs = ls->fs; | 1097 | FuncState *fs = ls->fs; |
1094 | TString *varname; | 1098 | TString *varname; |
1095 | BlockCnt bl; | 1099 | BlockCnt bl; |
1096 | enterblock(fs, &bl, 0); /* block to control variable scope */ | 1100 | enterblock(fs, &bl, 1); /* scope for loop and control variables */ |
1097 | next(ls); /* skip `for' */ | 1101 | next(ls); /* skip `for' */ |
1098 | varname = str_checkname(ls); /* first variable name */ | 1102 | varname = str_checkname(ls); /* first variable name */ |
1099 | switch (ls->t.token) { | 1103 | switch (ls->t.token) { |
@@ -1102,7 +1106,7 @@ static void forstat (LexState *ls, int line) { | |||
1102 | default: luaX_syntaxerror(ls, "`=' or `in' expected"); | 1106 | default: luaX_syntaxerror(ls, "`=' or `in' expected"); |
1103 | } | 1107 | } |
1104 | check_match(ls, TK_END, TK_FOR, line); | 1108 | check_match(ls, TK_END, TK_FOR, line); |
1105 | leaveblock(fs); | 1109 | leaveblock(fs); /* loop scope (`break' jumps to this point) */ |
1106 | } | 1110 | } |
1107 | 1111 | ||
1108 | 1112 | ||