Просмотр исходного кода

assignment expression may be multiple

Roberto Ierusalimschy 26 лет назад
Родитель
Сommit
8b2d97d187
3 измененных файлов с 47 добавлено и 35 удалено
  1. 3 1
      lopcodes.h
  2. 22 23
      lparser.c
  3. 22 11
      lvm.c

+ 3 - 1
lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.21 1999/02/04 16:36:16 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.22 1999/02/08 17:07:59 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -22,6 +22,7 @@ RETCODE,/*	b	-		-  */
 
 PUSHNIL,/*	b	-		nil_0...nil_b  */
 POP,/*		b	-		-		TOP-=(b+1)  */
+POPDUP,/*	b	v		v		TOP-=(b+1)  */
 
 PUSHNUMBERW,/*	w	-		(float)(w-NUMOFFSET)  */
 PUSHNUMBER,/*	b	-		(float)(b-NUMOFFSET)  */
@@ -59,6 +60,7 @@ SETTABLEPOP,/*	-	v i t		-		t[i]=v  */
 SETTABPPDUP,/*	-	v i t		v		t[i]=v  */
 
 SETTABLE,/*	b	v a_b...a_1 i t	a_b...a_1 i t	t[i]=v  */
+SETTABLEDUP,/*	b	v a_b...a_1 i t	v a_b...a_1 i t	t[i]=v  */
 
 SETLISTW,/*	w c	v_c...v_1 t	-		t[i+w*FPF]=v_i  */
 SETLIST,/*	b c	v_c...v_1 t	-		t[i+b*FPF]=v_i  */

+ 22 - 23
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.16 1999/02/04 17:47:59 roberto Exp roberto $
+** $Id: lparser.c,v 1.17 1999/02/08 17:07:59 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -102,7 +102,7 @@ typedef struct FuncState {
 /*
 ** prototypes for non-terminal functions
 */
-static int assignment (LexState *ls, vardesc *v, int nvars);
+static int assignment (LexState *ls, vardesc *v, int nvars, OpCode *codes);
 static int cond (LexState *ls);
 static int funcname (LexState *ls, vardesc *v);
 static int funcparams (LexState *ls, int slf);
@@ -387,7 +387,7 @@ static void check_debugline (LexState *ls) {
 
 static void adjuststack (LexState *ls, int n) {
   if (n > 0)
-    code_oparg(ls, POP, n-1, -n);
+    code_oparg(ls, POP, n, -n);
   else if (n < 0)
     code_oparg(ls, PUSHNIL, (-n)-1, -n);
 }
@@ -472,7 +472,13 @@ static void lua_pushvar (LexState *ls, vardesc *var) {
 }
 
 
-static void genstorevar (LexState *ls, vardesc *var, OpCode *codes) {
+/* to be used by "storevar" and assignment */
+static OpCode set_pop[] = {SETLOCAL, SETGLOBAL, SETTABLEPOP, SETTABLE};
+static OpCode set_dup[] = {SETLOCALDUP, SETGLOBALDUP, SETTABPPDUP,
+                           SETTABLEDUP};
+
+
+static void storevar (LexState *ls, vardesc *var, OpCode *codes) {
   switch (var->k) {
     case VLOCAL:
       code_oparg(ls, codes[0], var->info, -1);
@@ -489,12 +495,6 @@ static void genstorevar (LexState *ls, vardesc *var, OpCode *codes) {
 }
 
 
-static void storevar (LexState *ls, vardesc *var) {
-  static OpCode codes[] = {SETLOCAL, SETGLOBAL, SETTABLEPOP};
-  genstorevar(ls, var, codes);
-}
-
-
 static int fix_jump (LexState *ls, int pc, OpCode op, int n) {
   /* jump is relative to position following jump instruction */
   return fix_opcode(ls, pc, op, n-(pc+JMPSIZE));
@@ -748,7 +748,7 @@ static int stat (LexState *ls) {
       next(ls);
       needself = funcname(ls, &v);
       body(ls, needself, line);
-      storevar(ls, &v);
+      storevar(ls, &v, set_pop);
       return 1;
     }
 
@@ -773,8 +773,8 @@ static int stat (LexState *ls) {
           luaX_error(ls, "syntax error");
         close_exp(ls, v.info, 0);
       }
-      else {
-        int left = assignment(ls, &v, 1);  /* stat -> ['%'] NAME assignment */
+      else {  /* stat -> ['%'] NAME assignment */
+        int left = assignment(ls, &v, 1, set_pop);
         adjuststack(ls, left);  /* remove eventual 'garbage' left on stack */
       }
       return 1;
@@ -953,14 +953,13 @@ static void exp0 (LexState *ls, vardesc *v) {
 
 
 static void Gexp (LexState *ls, vardesc *v) {
-  /* Gexp -> exp0 | var '=' exp1 */
-  static OpCode codes[] = {SETLOCALDUP, SETGLOBALDUP, SETTABPPDUP};
+  /* Gexp -> exp0 | assignment */
   exp0(ls, v);
-  if (v->k != VEXP && optional(ls, '=')) {  /* assignment expression? */
-    unloaddot(ls, v);
-    exp1(ls);
-    genstorevar(ls, v, codes);
+  if (v->k != VEXP && (ls->token == '=' || ls->token == ',')) {
+    int left = assignment(ls, v, 1, set_dup);
     deltastack(ls, 1);  /* DUP operations push an extra value */
+    if (left > 0)
+      code_oparg(ls, POPDUP, left, -left);
     v->k = VEXP; v->info = 0;  /* this expression is closed now */
   }
 }
@@ -1244,7 +1243,7 @@ static void decinit (LexState *ls, listdesc *d) {
 }
 
 
-static int assignment (LexState *ls, vardesc *v, int nvars) {
+static int assignment (LexState *ls, vardesc *v, int nvars, OpCode *codes) {
   int left = 0;
   unloaddot(ls, v);
   if (ls->token == ',') {  /* assignment -> ',' NAME assignment */
@@ -1253,7 +1252,7 @@ static int assignment (LexState *ls, vardesc *v, int nvars) {
     var_or_func(ls, &nv);
     if (nv.k == VEXP)
       luaX_error(ls, "syntax error");
-    left = assignment(ls, &nv, nvars+1);
+    left = assignment(ls, &nv, nvars+1, set_pop);
   }
   else {  /* assignment -> '=' explist1 */
     listdesc d;
@@ -1263,10 +1262,10 @@ static int assignment (LexState *ls, vardesc *v, int nvars) {
   }
   if (v->k != VINDEXED || left+(nvars-1) == 0) {
     /* global/local var or indexed var without values in between */
-    storevar(ls, v);
+    storevar(ls, v, codes);
   }
   else {  /* indexed var with values in between*/
-    code_oparg(ls, SETTABLE, left+(nvars-1), -1);
+    code_oparg(ls, codes[3], left+(nvars-1), -1);
     left += 2;  /* table/index are not popped, because they aren't on top */
   }
   return left;

+ 22 - 11
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.45 1999/02/04 17:47:59 roberto Exp roberto $
+** $Id: lvm.c,v 1.46 1999/02/08 17:07:59 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -344,7 +344,12 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
         break;
 
       case POP: aux = *pc++;
-        S->top -= (aux+1);
+        S->top -= aux;
+        break;
+
+      case POPDUP: aux = *pc++;
+        *(S->top-aux-1) = *(S->top-1);
+        S->top -= aux;
         break;
 
       case PUSHNUMBERW: aux += highbyte(*pc++);
@@ -420,22 +425,28 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
         break;
 
       case SETTABLEPOP:
-       luaV_settable(S->top-3);
-       S->top -= 2;  /* pop table and index */
-       break;
+        luaV_settable(S->top-3);
+        S->top -= 2;  /* pop table and index */
+        break;
 
       case SETTABPPDUP: {
-       TObject temp = *(S->top-1);
-       luaV_settable(S->top-3);
-       S->top--;  /* pop index (temp goes into "table" position) */
-       *(S->top-1) = temp;
-       break;
-     }
+        TObject temp = *(S->top-1);
+        luaV_settable(S->top-3);
+        S->top--;  /* pop index (temp goes into "table" position) */
+        *(S->top-1) = temp;
+        break;
+      }
 
       case SETTABLE:
         luaV_settable(S->top-3-(*pc++));
         break;
 
+      case SETTABLEDUP:
+        *S->top = *(S->top-1);
+        S->top++;
+        luaV_settable(S->top-(3+1)-(*pc++));
+        break;
+
       case SETLISTW: aux += highbyte(*pc++);
       case SETLIST:  aux += *pc++; {
         int n = *(pc++);