diff options
| -rw-r--r-- | lcode.c | 8 | ||||
| -rw-r--r-- | llex.c | 4 | ||||
| -rw-r--r-- | llex.h | 4 | ||||
| -rw-r--r-- | lopcodes.h | 5 | ||||
| -rw-r--r-- | lparser.c | 47 | ||||
| -rw-r--r-- | ltests.c | 4 | ||||
| -rw-r--r-- | lvm.c | 30 |
7 files changed, 87 insertions, 15 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 1.22 2000/04/07 13:13:11 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.23 2000/04/07 19:35:20 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 | */ |
| @@ -53,7 +53,6 @@ static void luaK_fixjump (FuncState *fs, int pc, int dest) { | |||
| 53 | SETARG_S(*jmp, NO_JUMP); /* point to itself to represent end of list */ | 53 | SETARG_S(*jmp, NO_JUMP); /* point to itself to represent end of list */ |
| 54 | else { /* jump is relative to position following jump instruction */ | 54 | else { /* jump is relative to position following jump instruction */ |
| 55 | int offset = dest-(pc+1); | 55 | int offset = dest-(pc+1); |
| 56 | LUA_ASSERT(L, offset != NO_JUMP, "cannot link to itself"); | ||
| 57 | if (abs(offset) > MAXARG_S) | 56 | if (abs(offset) > MAXARG_S) |
| 58 | luaK_error(fs->ls, "control structure too long"); | 57 | luaK_error(fs->ls, "control structure too long"); |
| 59 | SETARG_S(*jmp, offset); | 58 | SETARG_S(*jmp, offset); |
| @@ -434,7 +433,6 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |||
| 434 | mode = iP; | 433 | mode = iP; |
| 435 | switch (o) { | 434 | switch (o) { |
| 436 | 435 | ||
| 437 | case OP_JMP: delta = 0; mode = iS; break; | ||
| 438 | case OP_CLOSURE: delta = -arg2+1; mode = iAB; break; | 436 | case OP_CLOSURE: delta = -arg2+1; mode = iAB; break; |
| 439 | case OP_SETLINE: mode = iU; break; | 437 | case OP_SETLINE: mode = iU; break; |
| 440 | case OP_CALL: mode = iAB; break; | 438 | case OP_CALL: mode = iAB; break; |
| @@ -443,6 +441,10 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |||
| 443 | case OP_SETTABLE: delta = -arg2; mode = iAB; break; | 441 | case OP_SETTABLE: delta = -arg2; mode = iAB; break; |
| 444 | case OP_SETLIST: delta = -(arg2+1); mode = iAB; break; | 442 | case OP_SETLIST: delta = -(arg2+1); mode = iAB; break; |
| 445 | case OP_SETMAP: delta = -2*(arg1+1); mode = iU; break; | 443 | case OP_SETMAP: delta = -2*(arg1+1); mode = iU; break; |
| 444 | case OP_FORLOOP: delta = -3; arg1 = NO_JUMP; mode = iS; break; | ||
| 445 | |||
| 446 | case OP_FORPREP: arg1 = NO_JUMP; /* go through */ | ||
| 447 | case OP_JMP: mode = iS; break; | ||
| 446 | 448 | ||
| 447 | case OP_END: case OP_PUSHNILJMP: case OP_NOT: | 449 | case OP_END: case OP_PUSHNILJMP: case OP_NOT: |
| 448 | mode = iO; break; | 450 | mode = iO; break; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: llex.c,v 1.55 2000/04/05 17:51:58 roberto Exp roberto $ | 2 | ** $Id: llex.c,v 1.56 2000/04/07 13:11:49 roberto Exp roberto $ |
| 3 | ** Lexical Analyzer | 3 | ** Lexical Analyzer |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -32,7 +32,7 @@ | |||
| 32 | 32 | ||
| 33 | /* ORDER RESERVED */ | 33 | /* ORDER RESERVED */ |
| 34 | static const char *const token2string [] = { | 34 | static const char *const token2string [] = { |
| 35 | "and", "break", "do", "else", "elseif", "end", | 35 | "and", "break", "do", "else", "elseif", "end", "for", |
| 36 | "function", "if", "local", "nil", "not", "or", "repeat", "return", "then", | 36 | "function", "if", "local", "nil", "not", "or", "repeat", "return", "then", |
| 37 | "until", "while", "", "..", "...", "==", ">=", "<=", "~=", "", "", "<eof>"}; | 37 | "until", "while", "", "..", "...", "==", ">=", "<=", "~=", "", "", "<eof>"}; |
| 38 | 38 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: llex.h,v 1.22 2000/04/05 17:51:58 roberto Exp roberto $ | 2 | ** $Id: llex.h,v 1.23 2000/04/07 13:11:49 roberto Exp roberto $ |
| 3 | ** Lexical Analyzer | 3 | ** Lexical Analyzer |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -24,7 +24,7 @@ | |||
| 24 | enum RESERVED { | 24 | enum RESERVED { |
| 25 | /* terminal symbols denoted by reserved words */ | 25 | /* terminal symbols denoted by reserved words */ |
| 26 | TK_AND = FIRST_RESERVED, TK_BREAK, | 26 | TK_AND = FIRST_RESERVED, TK_BREAK, |
| 27 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FUNCTION, TK_IF, TK_LOCAL, | 27 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FOR, TK_FUNCTION, TK_IF, TK_LOCAL, |
| 28 | TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, TK_UNTIL, TK_WHILE, | 28 | TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, TK_UNTIL, TK_WHILE, |
| 29 | /* other terminal symbols */ | 29 | /* other terminal symbols */ |
| 30 | TK_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, | 30 | TK_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lopcodes.h,v 1.55 2000/04/07 13:12:50 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.56 2000/04/07 19:35:31 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 | */ |
| @@ -148,6 +148,9 @@ OP_JMP,/* J - - PC+=s */ | |||
| 148 | 148 | ||
| 149 | OP_PUSHNILJMP,/* - - nil PC++; */ | 149 | OP_PUSHNILJMP,/* - - nil PC++; */ |
| 150 | 150 | ||
| 151 | OP_FORPREP,/* J */ | ||
| 152 | OP_FORLOOP,/* J */ | ||
| 153 | |||
| 151 | OP_CLOSURE,/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ | 154 | OP_CLOSURE,/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ |
| 152 | 155 | ||
| 153 | OP_SETLINE/* U - - LINE=u */ | 156 | OP_SETLINE/* U - - LINE=u */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 1.80 2000/04/10 19:21:14 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.81 2000/04/11 18:37:18 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 | */ |
| @@ -884,7 +884,7 @@ static void whilestat (LexState *ls, int line) { | |||
| 884 | block(ls); | 884 | block(ls); |
| 885 | luaK_patchlist(fs, luaK_jump(fs), while_init); | 885 | luaK_patchlist(fs, luaK_jump(fs), while_init); |
| 886 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); | 886 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); |
| 887 | check_END(ls, TK_WHILE, line); | 887 | check_END(ls, TK_WHILE, line); /* trace END when loop ends */ |
| 888 | leavebreak(fs, &bl); | 888 | leavebreak(fs, &bl); |
| 889 | } | 889 | } |
| 890 | 890 | ||
| @@ -906,7 +906,40 @@ static void repeatstat (LexState *ls, int line) { | |||
| 906 | } | 906 | } |
| 907 | 907 | ||
| 908 | 908 | ||
| 909 | static void test_and_bock (LexState *ls, expdesc *v) { | 909 | static void forstat (LexState *ls, int line) { |
| 910 | /* forstat -> FOR NAME '=' expr1 ',' expr1 [',' expr1] DO block END */ | ||
| 911 | FuncState *fs = ls->fs; | ||
| 912 | int prep; | ||
| 913 | int blockinit; | ||
| 914 | Breaklabel bl; | ||
| 915 | enterbreak(fs, &bl); | ||
| 916 | setline_and_next(ls); /* skip for */ | ||
| 917 | store_localvar(ls, str_checkname(ls), 0); /* control variable */ | ||
| 918 | check(ls, '='); | ||
| 919 | exp1(ls); /* initial value */ | ||
| 920 | check(ls, ','); | ||
| 921 | exp1(ls); /* limit */ | ||
| 922 | if (optional(ls, ',')) | ||
| 923 | exp1(ls); /* optional step */ | ||
| 924 | else | ||
| 925 | luaK_code1(fs, OP_PUSHINT, 1); /* default step */ | ||
| 926 | adjustlocalvars(ls, 1, 0); /* init scope for control variable */ | ||
| 927 | add_localvar(ls, " limit "); | ||
| 928 | add_localvar(ls, " step "); | ||
| 929 | prep = luaK_code0(fs, OP_FORPREP); | ||
| 930 | blockinit = luaK_getlabel(fs); | ||
| 931 | check(ls, TK_DO); | ||
| 932 | block(ls); | ||
| 933 | luaK_patchlist(fs, prep, luaK_getlabel(fs)); | ||
| 934 | luaK_patchlist(fs, luaK_code0(fs, OP_FORLOOP), blockinit); | ||
| 935 | check_END(ls, TK_WHILE, line); | ||
| 936 | leavebreak(fs, &bl); | ||
| 937 | removelocalvars(ls, 3, fs->lastsetline); | ||
| 938 | } | ||
| 939 | |||
| 940 | |||
| 941 | static void test_and_block (LexState *ls, expdesc *v) { | ||
| 942 | /* test_and_block -> [IF | ELSEIF] cond THEN block */ | ||
| 910 | setline_and_next(ls); /* skip IF or ELSEIF */ | 943 | setline_and_next(ls); /* skip IF or ELSEIF */ |
| 911 | expr(ls, v); /* cond */ | 944 | expr(ls, v); /* cond */ |
| 912 | luaK_goiftrue(ls->fs, v, 0); | 945 | luaK_goiftrue(ls->fs, v, 0); |
| @@ -921,11 +954,11 @@ static void ifstat (LexState *ls, int line) { | |||
| 921 | FuncState *fs = ls->fs; | 954 | FuncState *fs = ls->fs; |
| 922 | expdesc v; | 955 | expdesc v; |
| 923 | int escapelist = NO_JUMP; | 956 | int escapelist = NO_JUMP; |
| 924 | test_and_bock(ls, &v); /* IF cond THEN block */ | 957 | test_and_block(ls, &v); /* IF cond THEN block */ |
| 925 | while (ls->token == TK_ELSEIF) { | 958 | while (ls->token == TK_ELSEIF) { |
| 926 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | 959 | luaK_concat(fs, &escapelist, luaK_jump(fs)); |
| 927 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); | 960 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); |
| 928 | test_and_bock(ls, &v); /* ELSEIF cond THEN block */ | 961 | test_and_block(ls, &v); /* ELSEIF cond THEN block */ |
| 929 | } | 962 | } |
| 930 | if (ls->token == TK_ELSE) { | 963 | if (ls->token == TK_ELSE) { |
| 931 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | 964 | luaK_concat(fs, &escapelist, luaK_jump(fs)); |
| @@ -1062,6 +1095,10 @@ static int stat (LexState *ls) { | |||
| 1062 | check_END(ls, TK_DO, line); | 1095 | check_END(ls, TK_DO, line); |
| 1063 | return 1; | 1096 | return 1; |
| 1064 | 1097 | ||
| 1098 | case TK_FOR: /* stat -> forstat */ | ||
| 1099 | forstat(ls, line); | ||
| 1100 | return 1; | ||
| 1101 | |||
| 1065 | case TK_REPEAT: /* stat -> repeatstat */ | 1102 | case TK_REPEAT: /* stat -> repeatstat */ |
| 1066 | repeatstat(ls, line); | 1103 | repeatstat(ls, line); |
| 1067 | return 1; | 1104 | return 1; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 1.11 2000/04/06 17:35:23 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 1.12 2000/04/07 13:12:50 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 | */ |
| @@ -104,6 +104,8 @@ static int printop (lua_State *L, Instruction i) { | |||
| 104 | case OP_PUSHNILJMP: O("PUSHNILJMP"); break; | 104 | case OP_PUSHNILJMP: O("PUSHNILJMP"); break; |
| 105 | case OP_JMPT: S("JMPT"); break; | 105 | case OP_JMPT: S("JMPT"); break; |
| 106 | case OP_JMPF: S("JMPF"); break; | 106 | case OP_JMPF: S("JMPF"); break; |
| 107 | case OP_FORPREP: S("OP_FORPREP"); break; | ||
| 108 | case OP_FORLOOP: S("OP_FORLOOP"); break; | ||
| 107 | case OP_CLOSURE: AB("CLOSURE"); break; | 109 | case OP_CLOSURE: AB("CLOSURE"); break; |
| 108 | case OP_SETLINE: U("SETLINE"); break; | 110 | case OP_SETLINE: U("SETLINE"); break; |
| 109 | } | 111 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 1.99 2000/04/04 20:48:44 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.100 2000/04/07 13:13:11 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 | */ |
| @@ -630,6 +630,34 @@ StkId luaV_execute (lua_State *L, const Closure *cl, register StkId base) { | |||
| 630 | pc++; | 630 | pc++; |
| 631 | break; | 631 | break; |
| 632 | 632 | ||
| 633 | case OP_FORPREP: | ||
| 634 | if (tonumber(top-1)) | ||
| 635 | lua_error(L, "`for' step must be a number"); | ||
| 636 | if (tonumber(top-2)) | ||
| 637 | lua_error(L, "`for' limit must be a number"); | ||
| 638 | if (tonumber(top-3)) | ||
| 639 | lua_error(L, "`for' initial value must be a number"); | ||
| 640 | nvalue(top-3) -= nvalue(top-1); /* to be undone by first FORLOOP */ | ||
| 641 | pc += GETARG_S(i); | ||
| 642 | break; | ||
| 643 | |||
| 644 | case OP_FORLOOP: { | ||
| 645 | Number step = nvalue(top-1); | ||
| 646 | Number limit = nvalue(top-2); | ||
| 647 | Number index; | ||
| 648 | LUA_ASSERT(L, ttype(top-1) == TAG_NUMBER, "invalid step"); | ||
| 649 | LUA_ASSERT(L, ttype(top-2) == TAG_NUMBER, "invalid limit"); | ||
| 650 | if (tonumber(top-3)) lua_error(L, "`for' index must be a number"); | ||
| 651 | index = nvalue(top-3)+step; | ||
| 652 | if ((step>0) ? index<=limit : index>=limit) { | ||
| 653 | nvalue(top-3) = index; | ||
| 654 | pc += GETARG_S(i); | ||
| 655 | } | ||
| 656 | else /* end of `for': remove control variables */ | ||
| 657 | top -= 3; | ||
| 658 | break; | ||
| 659 | } | ||
| 660 | |||
| 633 | case OP_CLOSURE: | 661 | case OP_CLOSURE: |
| 634 | L->top = top; | 662 | L->top = top; |
| 635 | luaV_Lclosure(L, tf->kproto[GETARG_A(i)], GETARG_B(i)); | 663 | luaV_Lclosure(L, tf->kproto[GETARG_A(i)], GETARG_B(i)); |
