aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-05-15 16:48:04 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-05-15 16:48:04 -0300
commit93d93a0bfbc30f1176e973e1238b51e560eeb233 (patch)
treee2865f4a4e8f10fc8db6edd1b26020b292392be9
parent9e1f94fc1c3e8d4a8e68185223d03dafc1ee8050 (diff)
downloadlua-93d93a0bfbc30f1176e973e1238b51e560eeb233.tar.gz
lua-93d93a0bfbc30f1176e973e1238b51e560eeb233.tar.bz2
lua-93d93a0bfbc30f1176e973e1238b51e560eeb233.zip
first implementation of `for' over tables
-rw-r--r--lcode.c14
-rw-r--r--lopcodes.h5
-rw-r--r--lparser.c89
-rw-r--r--ltests.c8
-rw-r--r--lvm.c37
5 files changed, 118 insertions, 35 deletions
diff --git a/lcode.c b/lcode.c
index b5ef968e..138ee78a 100644
--- a/lcode.c
+++ b/lcode.c
@@ -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:
diff --git a/lopcodes.h b/lopcodes.h
index 4dcec5aa..283dcdb6 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -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++; */
143OP_FORPREP,/* J */ 143OP_FORPREP,/* J */
144OP_FORLOOP,/* J */ 144OP_FORLOOP,/* J */
145 145
146OP_LFORPREP,/* J */
147OP_LFORLOOP,/* J */
148
146OP_CLOSURE,/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ 149OP_CLOSURE,/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */
147 150
148OP_SETLINE/* U - - LINE=u */ 151OP_SETLINE/* U - - LINE=u */
diff --git a/lparser.c b/lparser.c
index 9691f4d2..3fae5419 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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
208static void adjustlocalvars (LexState *ls, int nvars, int line) { 208static 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
217static void removelocalvars (LexState *ls, int nvars, int line) { 218static 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
224static void add_localvar (LexState *ls, const char *name) { 226static 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
304static void code_args (LexState *ls, int nparams, int dots) { 306static 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
910static void forstat (LexState *ls, int line) { 912static 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
923static 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); 942static 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
961static 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
1000static void localstat (LexState *ls) { 1038static 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
diff --git a/ltests.c b/ltests.c
index 4646c5c9..8502c95a 100644
--- a/ltests.c
+++ b/ltests.c
@@ -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 }
diff --git a/lvm.c b/lvm.c
index 9b0ea0c8..ecf2a49c 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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