diff options
-rw-r--r-- | ldebug.c | 5 | ||||
-rw-r--r-- | lopcodes.c | 4 | ||||
-rw-r--r-- | lopcodes.h | 4 | ||||
-rw-r--r-- | lparser.c | 44 | ||||
-rw-r--r-- | lvm.c | 52 |
5 files changed, 59 insertions, 50 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 1.150 2003/03/19 21:24:04 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 1.151 2003/04/28 13:31:06 roberto Exp roberto $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -374,10 +374,11 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { | |||
374 | break; | 374 | break; |
375 | } | 375 | } |
376 | case OP_TFORLOOP: | 376 | case OP_TFORLOOP: |
377 | checkreg(pt, a+c+5); | 377 | checkreg(pt, a+5); |
378 | if (reg >= a) last = pc; /* affect all registers above base */ | 378 | if (reg >= a) last = pc; /* affect all registers above base */ |
379 | /* go through */ | 379 | /* go through */ |
380 | case OP_FORLOOP: | 380 | case OP_FORLOOP: |
381 | case OP_FORPREP: | ||
381 | checkreg(pt, a+2); | 382 | checkreg(pt, a+2); |
382 | /* go through */ | 383 | /* go through */ |
383 | case OP_JMP: { | 384 | case OP_JMP: { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.c,v 1.21 2002/08/20 20:03:05 roberto Exp roberto $ | 2 | ** $Id: lopcodes.c,v 1.22 2002/12/04 17:38:31 roberto Exp roberto $ |
3 | ** extracted automatically from lopcodes.h by mkprint.lua | 3 | ** extracted automatically from lopcodes.h by mkprint.lua |
4 | ** DO NOT EDIT | 4 | ** DO NOT EDIT |
5 | ** See Copyright Notice in lua.h | 5 | ** See Copyright Notice in lua.h |
@@ -46,6 +46,7 @@ const char *const luaP_opnames[] = { | |||
46 | "TAILCALL", | 46 | "TAILCALL", |
47 | "RETURN", | 47 | "RETURN", |
48 | "FORLOOP", | 48 | "FORLOOP", |
49 | "FORPREP", | ||
49 | "TFORLOOP", | 50 | "TFORLOOP", |
50 | "TFORPREP", | 51 | "TFORPREP", |
51 | "SETLIST", | 52 | "SETLIST", |
@@ -92,6 +93,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
92 | ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_TAILCALL */ | 93 | ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_TAILCALL */ |
93 | ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_RETURN */ | 94 | ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_RETURN */ |
94 | ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_FORLOOP */ | 95 | ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_FORLOOP */ |
96 | ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_FORPREP */ | ||
95 | ,opmode(1, 0, 0, 0, 0, 0, iABC) /* OP_TFORLOOP */ | 97 | ,opmode(1, 0, 0, 0, 0, 0, iABC) /* OP_TFORLOOP */ |
96 | ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_TFORPREP */ | 98 | ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_TFORPREP */ |
97 | ,opmode(0, 0, 0, 0, 0, 0, iABx) /* OP_SETLIST */ | 99 | ,opmode(0, 0, 0, 0, 0, 0, iABx) /* OP_SETLIST */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.101 2002/08/20 20:03:05 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.102 2002/08/21 18:56:09 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -172,6 +172,7 @@ OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ | |||
172 | OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ | 172 | OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ |
173 | 173 | ||
174 | OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) <?= R(A+1) then PC+= sBx */ | 174 | OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) <?= R(A+1) then PC+= sBx */ |
175 | OP_FORPREP,/* A sBx R(A)-=R(A+2); PC += sBx */ | ||
175 | 176 | ||
176 | OP_TFORLOOP,/* A C R(A+2), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); | 177 | OP_TFORLOOP,/* A C R(A+2), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); |
177 | if R(A+2) ~= nil then pc++ */ | 178 | if R(A+2) ~= nil then pc++ */ |
@@ -214,7 +215,6 @@ enum OpModeMask { | |||
214 | OpModesetA, /* instruction set register A */ | 215 | OpModesetA, /* instruction set register A */ |
215 | OpModeK, /* Bx is a constant */ | 216 | OpModeK, /* Bx is a constant */ |
216 | OpModeT /* operator is a test */ | 217 | OpModeT /* operator is a test */ |
217 | |||
218 | }; | 218 | }; |
219 | 219 | ||
220 | 220 | ||
@@ -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 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.284 2003/04/03 13:35:34 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.285 2003/05/05 18:39:57 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -639,43 +639,45 @@ StkId luaV_execute (lua_State *L) { | |||
639 | } | 639 | } |
640 | } | 640 | } |
641 | case OP_FORLOOP: { | 641 | case OP_FORLOOP: { |
642 | lua_Number step, idx, limit; | 642 | lua_Number step = nvalue(ra+2); |
643 | lua_Number idx = nvalue(ra) + step; /* increment index */ | ||
644 | lua_Number limit = nvalue(ra+1); | ||
645 | if (step > 0 ? idx <= limit : idx >= limit) { | ||
646 | dojump(pc, GETARG_sBx(i)); /* jump back */ | ||
647 | setnvalue(ra, idx); /* update internal index... */ | ||
648 | setnvalue(ra+3, idx); /* ...and external index */ | ||
649 | } | ||
650 | break; | ||
651 | } | ||
652 | case OP_FORPREP: { | ||
653 | const TObject *init = ra; | ||
643 | const TObject *plimit = ra+1; | 654 | const TObject *plimit = ra+1; |
644 | const TObject *pstep = ra+2; | 655 | const TObject *pstep = ra+2; |
645 | if (!ttisnumber(ra)) | 656 | if (!tonumber(init, ra)) |
646 | luaG_runerror(L, "`for' initial value must be a number"); | 657 | luaG_runerror(L, "`for' initial value must be a number"); |
647 | if (!tonumber(plimit, ra+1)) | 658 | else if (!tonumber(plimit, ra+1)) |
648 | luaG_runerror(L, "`for' limit must be a number"); | 659 | luaG_runerror(L, "`for' limit must be a number"); |
649 | if (!tonumber(pstep, ra+2)) | 660 | else if (!tonumber(pstep, ra+2)) |
650 | luaG_runerror(L, "`for' step must be a number"); | 661 | luaG_runerror(L, "`for' step must be a number"); |
651 | step = nvalue(pstep); | 662 | setnvalue(ra, nvalue(ra) - nvalue(pstep)); |
652 | idx = nvalue(ra) + step; /* increment index */ | 663 | dojump(pc, GETARG_sBx(i)); |
653 | limit = nvalue(plimit); | ||
654 | if (step > 0 ? idx <= limit : idx >= limit) { | ||
655 | dojump(pc, GETARG_sBx(i)); /* jump back */ | ||
656 | chgnvalue(ra, idx); /* update index */ | ||
657 | } | ||
658 | break; | 664 | break; |
659 | } | 665 | } |
660 | case OP_TFORLOOP: { | 666 | case OP_TFORLOOP: { |
661 | int nvar = GETARG_C(i) + 1; | 667 | StkId cb = ra + 3; /* call base */ |
662 | StkId cb = ra + nvar + 2; /* call base */ | ||
663 | setobjs2s(cb, ra); | ||
664 | setobjs2s(cb+1, ra+1); | ||
665 | setobjs2s(cb+2, ra+2); | 668 | setobjs2s(cb+2, ra+2); |
669 | setobjs2s(cb+1, ra+1); | ||
670 | setobjs2s(cb, ra); | ||
666 | L->top = cb+3; /* func. + 2 args (state and index) */ | 671 | L->top = cb+3; /* func. + 2 args (state and index) */ |
667 | luaD_call(L, cb, nvar); | 672 | luaD_call(L, cb, GETARG_C(i)); |
668 | L->top = L->ci->top; | 673 | L->top = L->ci->top; |
669 | ra = XRA(i) + 2; /* final position of first result */ | 674 | cb = XRA(i) + 3; /* previous call may change the stack */ |
670 | cb = ra + nvar; | 675 | if (ttisnil(cb)) /* break loop? */ |
671 | do { /* move results to proper positions */ | ||
672 | nvar--; | ||
673 | setobjs2s(ra+nvar, cb+nvar); | ||
674 | } while (nvar > 0); | ||
675 | if (ttisnil(ra)) /* break loop? */ | ||
676 | pc++; /* skip jump (break loop) */ | 676 | pc++; /* skip jump (break loop) */ |
677 | else | 677 | else { |
678 | setobjs2s(cb-1, cb); /* save control variable */ | ||
678 | dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */ | 679 | dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */ |
680 | } | ||
679 | break; | 681 | break; |
680 | } | 682 | } |
681 | case OP_TFORPREP: { /* for compatibility only */ | 683 | case OP_TFORPREP: { /* for compatibility only */ |