diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-02-08 16:54:19 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-02-08 16:54:19 -0200 |
commit | 8b2d97d1871147c730a986656907837458b601f8 (patch) | |
tree | d555c67380642b973a43d04fcfbbfdb3588e12da | |
parent | fb1cf6ab2d12bd61e3d429830ab20d4ff3c39fd9 (diff) | |
download | lua-8b2d97d1871147c730a986656907837458b601f8.tar.gz lua-8b2d97d1871147c730a986656907837458b601f8.tar.bz2 lua-8b2d97d1871147c730a986656907837458b601f8.zip |
assignment expression may be multiple
-rw-r--r-- | lopcodes.h | 4 | ||||
-rw-r--r-- | lparser.c | 45 | ||||
-rw-r--r-- | lvm.c | 33 |
3 files changed, 47 insertions, 35 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.21 1999/02/04 16:36:16 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.22 1999/02/08 17:07:59 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 | */ |
@@ -22,6 +22,7 @@ RETCODE,/* b - - */ | |||
22 | 22 | ||
23 | PUSHNIL,/* b - nil_0...nil_b */ | 23 | PUSHNIL,/* b - nil_0...nil_b */ |
24 | POP,/* b - - TOP-=(b+1) */ | 24 | POP,/* b - - TOP-=(b+1) */ |
25 | POPDUP,/* b v v TOP-=(b+1) */ | ||
25 | 26 | ||
26 | PUSHNUMBERW,/* w - (float)(w-NUMOFFSET) */ | 27 | PUSHNUMBERW,/* w - (float)(w-NUMOFFSET) */ |
27 | PUSHNUMBER,/* b - (float)(b-NUMOFFSET) */ | 28 | PUSHNUMBER,/* b - (float)(b-NUMOFFSET) */ |
@@ -59,6 +60,7 @@ SETTABLEPOP,/* - v i t - t[i]=v */ | |||
59 | SETTABPPDUP,/* - v i t v t[i]=v */ | 60 | SETTABPPDUP,/* - v i t v t[i]=v */ |
60 | 61 | ||
61 | SETTABLE,/* b v a_b...a_1 i t a_b...a_1 i t t[i]=v */ | 62 | SETTABLE,/* b v a_b...a_1 i t a_b...a_1 i t t[i]=v */ |
63 | SETTABLEDUP,/* b v a_b...a_1 i t v a_b...a_1 i t t[i]=v */ | ||
62 | 64 | ||
63 | SETLISTW,/* w c v_c...v_1 t - t[i+w*FPF]=v_i */ | 65 | SETLISTW,/* w c v_c...v_1 t - t[i+w*FPF]=v_i */ |
64 | SETLIST,/* b c v_c...v_1 t - t[i+b*FPF]=v_i */ | 66 | SETLIST,/* b c v_c...v_1 t - t[i+b*FPF]=v_i */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.16 1999/02/04 17:47:59 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.17 1999/02/08 17:07:59 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 | */ |
@@ -102,7 +102,7 @@ typedef struct FuncState { | |||
102 | /* | 102 | /* |
103 | ** prototypes for non-terminal functions | 103 | ** prototypes for non-terminal functions |
104 | */ | 104 | */ |
105 | static int assignment (LexState *ls, vardesc *v, int nvars); | 105 | static int assignment (LexState *ls, vardesc *v, int nvars, OpCode *codes); |
106 | static int cond (LexState *ls); | 106 | static int cond (LexState *ls); |
107 | static int funcname (LexState *ls, vardesc *v); | 107 | static int funcname (LexState *ls, vardesc *v); |
108 | static int funcparams (LexState *ls, int slf); | 108 | static int funcparams (LexState *ls, int slf); |
@@ -387,7 +387,7 @@ static void check_debugline (LexState *ls) { | |||
387 | 387 | ||
388 | static void adjuststack (LexState *ls, int n) { | 388 | static void adjuststack (LexState *ls, int n) { |
389 | if (n > 0) | 389 | if (n > 0) |
390 | code_oparg(ls, POP, n-1, -n); | 390 | code_oparg(ls, POP, n, -n); |
391 | else if (n < 0) | 391 | else if (n < 0) |
392 | code_oparg(ls, PUSHNIL, (-n)-1, -n); | 392 | code_oparg(ls, PUSHNIL, (-n)-1, -n); |
393 | } | 393 | } |
@@ -472,7 +472,13 @@ static void lua_pushvar (LexState *ls, vardesc *var) { | |||
472 | } | 472 | } |
473 | 473 | ||
474 | 474 | ||
475 | static void genstorevar (LexState *ls, vardesc *var, OpCode *codes) { | 475 | /* to be used by "storevar" and assignment */ |
476 | static OpCode set_pop[] = {SETLOCAL, SETGLOBAL, SETTABLEPOP, SETTABLE}; | ||
477 | static OpCode set_dup[] = {SETLOCALDUP, SETGLOBALDUP, SETTABPPDUP, | ||
478 | SETTABLEDUP}; | ||
479 | |||
480 | |||
481 | static void storevar (LexState *ls, vardesc *var, OpCode *codes) { | ||
476 | switch (var->k) { | 482 | switch (var->k) { |
477 | case VLOCAL: | 483 | case VLOCAL: |
478 | code_oparg(ls, codes[0], var->info, -1); | 484 | code_oparg(ls, codes[0], var->info, -1); |
@@ -489,12 +495,6 @@ static void genstorevar (LexState *ls, vardesc *var, OpCode *codes) { | |||
489 | } | 495 | } |
490 | 496 | ||
491 | 497 | ||
492 | static void storevar (LexState *ls, vardesc *var) { | ||
493 | static OpCode codes[] = {SETLOCAL, SETGLOBAL, SETTABLEPOP}; | ||
494 | genstorevar(ls, var, codes); | ||
495 | } | ||
496 | |||
497 | |||
498 | static int fix_jump (LexState *ls, int pc, OpCode op, int n) { | 498 | static int fix_jump (LexState *ls, int pc, OpCode op, int n) { |
499 | /* jump is relative to position following jump instruction */ | 499 | /* jump is relative to position following jump instruction */ |
500 | return fix_opcode(ls, pc, op, n-(pc+JMPSIZE)); | 500 | return fix_opcode(ls, pc, op, n-(pc+JMPSIZE)); |
@@ -748,7 +748,7 @@ static int stat (LexState *ls) { | |||
748 | next(ls); | 748 | next(ls); |
749 | needself = funcname(ls, &v); | 749 | needself = funcname(ls, &v); |
750 | body(ls, needself, line); | 750 | body(ls, needself, line); |
751 | storevar(ls, &v); | 751 | storevar(ls, &v, set_pop); |
752 | return 1; | 752 | return 1; |
753 | } | 753 | } |
754 | 754 | ||
@@ -773,8 +773,8 @@ static int stat (LexState *ls) { | |||
773 | luaX_error(ls, "syntax error"); | 773 | luaX_error(ls, "syntax error"); |
774 | close_exp(ls, v.info, 0); | 774 | close_exp(ls, v.info, 0); |
775 | } | 775 | } |
776 | else { | 776 | else { /* stat -> ['%'] NAME assignment */ |
777 | int left = assignment(ls, &v, 1); /* stat -> ['%'] NAME assignment */ | 777 | int left = assignment(ls, &v, 1, set_pop); |
778 | adjuststack(ls, left); /* remove eventual 'garbage' left on stack */ | 778 | adjuststack(ls, left); /* remove eventual 'garbage' left on stack */ |
779 | } | 779 | } |
780 | return 1; | 780 | return 1; |
@@ -953,14 +953,13 @@ static void exp0 (LexState *ls, vardesc *v) { | |||
953 | 953 | ||
954 | 954 | ||
955 | static void Gexp (LexState *ls, vardesc *v) { | 955 | static void Gexp (LexState *ls, vardesc *v) { |
956 | /* Gexp -> exp0 | var '=' exp1 */ | 956 | /* Gexp -> exp0 | assignment */ |
957 | static OpCode codes[] = {SETLOCALDUP, SETGLOBALDUP, SETTABPPDUP}; | ||
958 | exp0(ls, v); | 957 | exp0(ls, v); |
959 | if (v->k != VEXP && optional(ls, '=')) { /* assignment expression? */ | 958 | if (v->k != VEXP && (ls->token == '=' || ls->token == ',')) { |
960 | unloaddot(ls, v); | 959 | int left = assignment(ls, v, 1, set_dup); |
961 | exp1(ls); | ||
962 | genstorevar(ls, v, codes); | ||
963 | deltastack(ls, 1); /* DUP operations push an extra value */ | 960 | deltastack(ls, 1); /* DUP operations push an extra value */ |
961 | if (left > 0) | ||
962 | code_oparg(ls, POPDUP, left, -left); | ||
964 | v->k = VEXP; v->info = 0; /* this expression is closed now */ | 963 | v->k = VEXP; v->info = 0; /* this expression is closed now */ |
965 | } | 964 | } |
966 | } | 965 | } |
@@ -1244,7 +1243,7 @@ static void decinit (LexState *ls, listdesc *d) { | |||
1244 | } | 1243 | } |
1245 | 1244 | ||
1246 | 1245 | ||
1247 | static int assignment (LexState *ls, vardesc *v, int nvars) { | 1246 | static int assignment (LexState *ls, vardesc *v, int nvars, OpCode *codes) { |
1248 | int left = 0; | 1247 | int left = 0; |
1249 | unloaddot(ls, v); | 1248 | unloaddot(ls, v); |
1250 | if (ls->token == ',') { /* assignment -> ',' NAME assignment */ | 1249 | if (ls->token == ',') { /* assignment -> ',' NAME assignment */ |
@@ -1253,7 +1252,7 @@ static int assignment (LexState *ls, vardesc *v, int nvars) { | |||
1253 | var_or_func(ls, &nv); | 1252 | var_or_func(ls, &nv); |
1254 | if (nv.k == VEXP) | 1253 | if (nv.k == VEXP) |
1255 | luaX_error(ls, "syntax error"); | 1254 | luaX_error(ls, "syntax error"); |
1256 | left = assignment(ls, &nv, nvars+1); | 1255 | left = assignment(ls, &nv, nvars+1, set_pop); |
1257 | } | 1256 | } |
1258 | else { /* assignment -> '=' explist1 */ | 1257 | else { /* assignment -> '=' explist1 */ |
1259 | listdesc d; | 1258 | listdesc d; |
@@ -1263,10 +1262,10 @@ static int assignment (LexState *ls, vardesc *v, int nvars) { | |||
1263 | } | 1262 | } |
1264 | if (v->k != VINDEXED || left+(nvars-1) == 0) { | 1263 | if (v->k != VINDEXED || left+(nvars-1) == 0) { |
1265 | /* global/local var or indexed var without values in between */ | 1264 | /* global/local var or indexed var without values in between */ |
1266 | storevar(ls, v); | 1265 | storevar(ls, v, codes); |
1267 | } | 1266 | } |
1268 | else { /* indexed var with values in between*/ | 1267 | else { /* indexed var with values in between*/ |
1269 | code_oparg(ls, SETTABLE, left+(nvars-1), -1); | 1268 | code_oparg(ls, codes[3], left+(nvars-1), -1); |
1270 | left += 2; /* table/index are not popped, because they aren't on top */ | 1269 | left += 2; /* table/index are not popped, because they aren't on top */ |
1271 | } | 1270 | } |
1272 | return left; | 1271 | return left; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.45 1999/02/04 17:47:59 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.46 1999/02/08 17:07:59 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 | */ |
@@ -344,7 +344,12 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) { | |||
344 | break; | 344 | break; |
345 | 345 | ||
346 | case POP: aux = *pc++; | 346 | case POP: aux = *pc++; |
347 | S->top -= (aux+1); | 347 | S->top -= aux; |
348 | break; | ||
349 | |||
350 | case POPDUP: aux = *pc++; | ||
351 | *(S->top-aux-1) = *(S->top-1); | ||
352 | S->top -= aux; | ||
348 | break; | 353 | break; |
349 | 354 | ||
350 | case PUSHNUMBERW: aux += highbyte(*pc++); | 355 | case PUSHNUMBERW: aux += highbyte(*pc++); |
@@ -420,22 +425,28 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) { | |||
420 | break; | 425 | break; |
421 | 426 | ||
422 | case SETTABLEPOP: | 427 | case SETTABLEPOP: |
423 | luaV_settable(S->top-3); | 428 | luaV_settable(S->top-3); |
424 | S->top -= 2; /* pop table and index */ | 429 | S->top -= 2; /* pop table and index */ |
425 | break; | 430 | break; |
426 | 431 | ||
427 | case SETTABPPDUP: { | 432 | case SETTABPPDUP: { |
428 | TObject temp = *(S->top-1); | 433 | TObject temp = *(S->top-1); |
429 | luaV_settable(S->top-3); | 434 | luaV_settable(S->top-3); |
430 | S->top--; /* pop index (temp goes into "table" position) */ | 435 | S->top--; /* pop index (temp goes into "table" position) */ |
431 | *(S->top-1) = temp; | 436 | *(S->top-1) = temp; |
432 | break; | 437 | break; |
433 | } | 438 | } |
434 | 439 | ||
435 | case SETTABLE: | 440 | case SETTABLE: |
436 | luaV_settable(S->top-3-(*pc++)); | 441 | luaV_settable(S->top-3-(*pc++)); |
437 | break; | 442 | break; |
438 | 443 | ||
444 | case SETTABLEDUP: | ||
445 | *S->top = *(S->top-1); | ||
446 | S->top++; | ||
447 | luaV_settable(S->top-(3+1)-(*pc++)); | ||
448 | break; | ||
449 | |||
439 | case SETLISTW: aux += highbyte(*pc++); | 450 | case SETLISTW: aux += highbyte(*pc++); |
440 | case SETLIST: aux += *pc++; { | 451 | case SETLIST: aux += *pc++; { |
441 | int n = *(pc++); | 452 | int n = *(pc++); |