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 */ |
