aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-04-12 15:57:19 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-04-12 15:57:19 -0300
commitf9cf402fbd1ba2ab00f5aa5f7d0ff5c9c0580dd5 (patch)
tree7bed49a7ff5c730cdfdef7c3a43b71e039d4442b
parent0c3fe2c44be155b11b52230e36f45e688bae5ce2 (diff)
downloadlua-f9cf402fbd1ba2ab00f5aa5f7d0ff5c9c0580dd5.tar.gz
lua-f9cf402fbd1ba2ab00f5aa5f7d0ff5c9c0580dd5.tar.bz2
lua-f9cf402fbd1ba2ab00f5aa5f7d0ff5c9c0580dd5.zip
first implementation of FOR
-rw-r--r--lcode.c8
-rw-r--r--llex.c4
-rw-r--r--llex.h4
-rw-r--r--lopcodes.h5
-rw-r--r--lparser.c47
-rw-r--r--ltests.c4
-rw-r--r--lvm.c30
7 files changed, 87 insertions, 15 deletions
diff --git a/lcode.c b/lcode.c
index c1bcc980..f75ac359 100644
--- a/lcode.c
+++ b/lcode.c
@@ -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;
diff --git a/llex.c b/llex.c
index 7c8ccd22..4efcb873 100644
--- a/llex.c
+++ b/llex.c
@@ -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 */
34static const char *const token2string [] = { 34static 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
diff --git a/llex.h b/llex.h
index 0dac5b8a..fd1daf00 100644
--- a/llex.h
+++ b/llex.h
@@ -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 @@
24enum RESERVED { 24enum 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,
diff --git a/lopcodes.h b/lopcodes.h
index a40fcbde..91c74759 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -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
149OP_PUSHNILJMP,/* - - nil PC++; */ 149OP_PUSHNILJMP,/* - - nil PC++; */
150 150
151OP_FORPREP,/* J */
152OP_FORLOOP,/* J */
153
151OP_CLOSURE,/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ 154OP_CLOSURE,/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */
152 155
153OP_SETLINE/* U - - LINE=u */ 156OP_SETLINE/* U - - LINE=u */
diff --git a/lparser.c b/lparser.c
index 39127e2a..df4aeecf 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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
909static void test_and_bock (LexState *ls, expdesc *v) { 909static 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
941static 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;
diff --git a/ltests.c b/ltests.c
index 596fee2b..75be74c3 100644
--- a/ltests.c
+++ b/ltests.c
@@ -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 }
diff --git a/lvm.c b/lvm.c
index fc8cb262..29819b1e 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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));