diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-04-12 15:57:19 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-04-12 15:57:19 -0300 |
commit | f9cf402fbd1ba2ab00f5aa5f7d0ff5c9c0580dd5 (patch) | |
tree | 7bed49a7ff5c730cdfdef7c3a43b71e039d4442b | |
parent | 0c3fe2c44be155b11b52230e36f45e688bae5ce2 (diff) | |
download | lua-f9cf402fbd1ba2ab00f5aa5f7d0ff5c9c0580dd5.tar.gz lua-f9cf402fbd1ba2ab00f5aa5f7d0ff5c9c0580dd5.tar.bz2 lua-f9cf402fbd1ba2ab00f5aa5f7d0ff5c9c0580dd5.zip |
first implementation of FOR
-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)); |