diff options
| -rw-r--r-- | lcode.c | 14 | ||||
| -rw-r--r-- | lopcodes.h | 5 | ||||
| -rw-r--r-- | lparser.c | 89 | ||||
| -rw-r--r-- | ltests.c | 8 | ||||
| -rw-r--r-- | lvm.c | 37 |
5 files changed, 118 insertions, 35 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 1.28 2000/04/19 13:41:37 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.29 2000/05/08 19:32:53 roberto Exp roberto $ |
| 3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -475,6 +475,18 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |||
| 475 | mode = iS; | 475 | mode = iS; |
| 476 | break; | 476 | break; |
| 477 | 477 | ||
| 478 | case OP_LFORPREP: | ||
| 479 | delta = 3; | ||
| 480 | arg1 = NO_JUMP; | ||
| 481 | mode = iS; | ||
| 482 | break; | ||
| 483 | |||
| 484 | case OP_LFORLOOP: | ||
| 485 | delta = -4; | ||
| 486 | arg1 = NO_JUMP; | ||
| 487 | mode = iS; | ||
| 488 | break; | ||
| 489 | |||
| 478 | case OP_END: | 490 | case OP_END: |
| 479 | case OP_PUSHNILJMP: | 491 | case OP_PUSHNILJMP: |
| 480 | case OP_NOT: | 492 | case OP_NOT: |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lopcodes.h,v 1.59 2000/04/14 17:45:25 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.60 2000/04/27 17:39:15 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 | */ |
| @@ -143,6 +143,9 @@ OP_PUSHNILJMP,/* - - nil PC++; */ | |||
| 143 | OP_FORPREP,/* J */ | 143 | OP_FORPREP,/* J */ |
| 144 | OP_FORLOOP,/* J */ | 144 | OP_FORLOOP,/* J */ |
| 145 | 145 | ||
| 146 | OP_LFORPREP,/* J */ | ||
| 147 | OP_LFORLOOP,/* J */ | ||
| 148 | |||
| 146 | OP_CLOSURE,/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ | 149 | OP_CLOSURE,/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ |
| 147 | 150 | ||
| 148 | OP_SETLINE/* U - - LINE=u */ | 151 | OP_SETLINE/* U - - LINE=u */ |
| @@ -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 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 1.17 2000/05/08 19:32:53 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 1.18 2000/05/10 16:33:20 roberto Exp roberto $ |
| 3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -103,8 +103,10 @@ static int pushop (lua_State *L, Instruction i) { | |||
| 103 | case OP_JMPONF: S("JMPONF"); break; | 103 | case OP_JMPONF: S("JMPONF"); break; |
| 104 | case OP_JMP: S("JMP"); break; | 104 | case OP_JMP: S("JMP"); break; |
| 105 | case OP_PUSHNILJMP: O("PUSHNILJMP"); break; | 105 | case OP_PUSHNILJMP: O("PUSHNILJMP"); break; |
| 106 | case OP_FORPREP: S("OP_FORPREP"); break; | 106 | case OP_FORPREP: S("FORPREP"); break; |
| 107 | case OP_FORLOOP: S("OP_FORLOOP"); break; | 107 | case OP_FORLOOP: S("FORLOOP"); break; |
| 108 | case OP_LFORPREP: S("LFORPREP"); break; | ||
| 109 | case OP_LFORLOOP: S("LFORLOOP"); break; | ||
| 108 | case OP_CLOSURE: AB("CLOSURE"); break; | 110 | case OP_CLOSURE: AB("CLOSURE"); break; |
| 109 | case OP_SETLINE: U("SETLINE"); break; | 111 | case OP_SETLINE: U("SETLINE"); break; |
| 110 | } | 112 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 1.104 2000/04/19 13:36:25 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.105 2000/05/08 19:32:53 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 | */ |
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #define LUA_REENTRANT | 12 | #define LUA_REENTRANT |
| 13 | 13 | ||
| 14 | #include "lapi.h" | ||
| 14 | #include "lauxlib.h" | 15 | #include "lauxlib.h" |
| 15 | #include "ldebug.h" | 16 | #include "ldebug.h" |
| 16 | #include "ldo.h" | 17 | #include "ldo.h" |
| @@ -634,12 +635,40 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
| 634 | if (ttype(top-3) != TAG_NUMBER) | 635 | if (ttype(top-3) != TAG_NUMBER) |
| 635 | lua_error(L, "`for' index must be a number"); | 636 | lua_error(L, "`for' index must be a number"); |
| 636 | index = nvalue(top-3)+step; | 637 | index = nvalue(top-3)+step; |
| 637 | if ((step>0) ? index<=limit : index>=limit) { | 638 | if ((step>0) ? index>limit : index<limit) |
| 639 | top -= 3; /* end loop: remove control variables */ | ||
| 640 | else { | ||
| 638 | nvalue(top-3) = index; | 641 | nvalue(top-3) = index; |
| 639 | pc += GETARG_S(i); | 642 | pc += GETARG_S(i); |
| 640 | } | 643 | } |
| 641 | else /* end of `for': remove control variables */ | 644 | break; |
| 642 | top -= 3; | 645 | } |
| 646 | |||
| 647 | case OP_LFORPREP: { | ||
| 648 | if (ttype(top-1) != TAG_TABLE) | ||
| 649 | lua_error(L, "`for' table must be a table"); | ||
| 650 | top += 3; /* counter + index,value */ | ||
| 651 | ttype(top-3) = TAG_NUMBER; | ||
| 652 | nvalue(top-3) = 0.0; /* counter */ | ||
| 653 | ttype(top-2) = ttype(top-1) = TAG_NIL; | ||
| 654 | pc += GETARG_S(i); | ||
| 655 | break; | ||
| 656 | } | ||
| 657 | |||
| 658 | case OP_LFORLOOP: { | ||
| 659 | int n; | ||
| 660 | top -= 2; /* remove old index,value */ | ||
| 661 | LUA_ASSERT(L, ttype(top-2) == TAG_TABLE, "invalid table"); | ||
| 662 | LUA_ASSERT(L, ttype(top-1) == TAG_NUMBER, "invalid counter"); | ||
| 663 | L->top = top; | ||
| 664 | n = luaA_next(L, avalue(top-2), (int)nvalue(top-1)); | ||
| 665 | if (n == 0) /* end loop? */ | ||
| 666 | top -= 2; /* remove table and counter */ | ||
| 667 | else { | ||
| 668 | nvalue(top-1) = (Number)n; | ||
| 669 | top += 2; /* new index,value */ | ||
| 670 | pc += GETARG_S(i); /* repeat loop */ | ||
| 671 | } | ||
| 643 | break; | 672 | break; |
| 644 | } | 673 | } |
| 645 | 674 | ||
