From f9e5c1f4bc9ccf8f57970311dcd97694a4c5edb0 Mon Sep 17 00:00:00 2001 From: Bert Wesarg Date: Tue, 14 Oct 2008 20:46:52 +0200 Subject: [PATCH] comment reduxed MultipleAssignment B.W. --- Patch: !MultipleAssignment-redux.patch --- MultipleAssignment-redux.patch | 87 ++++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/MultipleAssignment-redux.patch b/MultipleAssignment-redux.patch index 8938573..6b3d09e 100644 --- a/MultipleAssignment-redux.patch +++ b/MultipleAssignment-redux.patch @@ -1,9 +1,9 @@ --- - source/interpret.c | 29 +++++++++++++ + source/interpret.c | 29 ++++++++++ source/ops.h | 1 - source/parse.y | 110 ++++++++++++++++------------------------------------- - 3 files changed, 65 insertions(+), 75 deletions(-) + source/parse.y | 151 +++++++++++++++-------------------------------------- + 3 files changed, 74 insertions(+), 107 deletions(-) diff --quilt old/source/interpret.c new/source/interpret.c --- old/source/interpret.c @@ -99,39 +99,74 @@ diff --quilt old/source/parse.y new/source/parse.y %token ARGSEP %nonassoc IF_NO_ELSE -@@ -438,12 +429,10 @@ simpstmt: /* simple variable assignmen - ** Below for lvlist, M0 is $$.start, M1 is $$.mid, M2 is $$.next. lventry's $$ - ** gives the mid value between the P and A phases (M1). +@@ -412,117 +403,63 @@ simpstmt: /* simple variable assignmen + /* + ** Implementing a multi-assignment to a list of lvalues + ** +-** Each accepting lvalue requires a push phase P and an assign phase A. +-** +-** For arrays, P includes pushing the indices and the destination array value. +-** P always also includes pushing N, the position of the lval in the list, i.e. +-** the index into the r.h.s. array expression supplying values. ++** We do this by executing the rvalue first, and than do the assignment phase ++** afterward. + ** +-** The assign phase uses N (on the stack) and the stored result E of the source +-** array expression - this gives the indexed r.h.s. value to assign. Then, if +-** the destination is an array element, the destination array and indices are +-** retrieved from the stack and the assignment performed. +-** +-** Given "(a, b, c) = e", we need to end up with the command sequence: +-** Pc Pb Pa Ee Aa Ab Ac +-** However, we have to generate Px and Ax together in the parse. Hence we +-** must reorder, using PC mark positions Mx. For the example, we generate: +-** read a: M0[Pa]M1[Aa]Mt here Mt is the current GetPC() value +-** read b: M0[Pa]M1[Aa]M2[Pb]M3[Ab]Mt now swap(M0, M2, M3) +-** M0[Pb Pa]M1[Aa Ab]Mt +-** and c: M0[Pb Pa]M1[Aa Ab]M2[Pc]M3[Ac]Mt swap(M0, M2, M3) +-** M0[Pc Pb Pa]M1[Aa Ab Ac]Mt +-** then e: M0[Pc Pb Pa]M1[Aa Ab Ac]M2[Ee]Mt swap(M1, M2, Mt) +-** [Pc Pb Pa][Ee][Aa Ab Ac] +-** which is what we want. At each swap, we must retain intermediate positions. +-** Below for lvlist, M0 is $$.start, M1 is $$.mid, M2 is $$.next. lventry's $$ +-** gives the mid value between the P and A phases (M1). ++** The rvalue value is constantly duped on the stack to do the array ref. */ -lvlistexpr: '(' lvlist ')' blank '=' blank expr { - /* store expression value */ - ADD_OP(OP_ASSIGN); - ADD_SYM(LookupString("list assign expr", True)); -+lvlistexpr: '(' mark lvlist mark ')' blank '=' blank expr { - /* swap expression evaluation code into position */ +- /* swap expression evaluation code into position */ - SwapCode($2.mid, $2.next, GetPC()); ++lvlistexpr: '(' mark lvlist mark ')' blank '=' blank expr { ++ /* swap expression evaluation code to front */ + SwapCode($2, $4, GetPC()); + ADD_OP(OP_POP); /* pop expression */ } ; /* -@@ -453,76 +442,47 @@ lvlistexpr: '(' lvlist ')' blank '=' bla - ** Only then do we have the situation described for overall list assignment. +-** lvlist: code for pushing the expression's index is generated here, after the code +-** for assigning to the lvalue. In other words, the Px portion is split, with +-** the assign code in front of the push index code. This needs to be swapped. +-** Only then do we have the situation described for overall list assignment. ++** lvlist: code for doing the rvalue array ref. ++** ++** We need to move this code infront of the actual assignment operation of ++** the lvalue, so that the result is ontop od the stack. ++** lventry's value will give us the start of this code. */ lvlist: lventry { + Inst *this = GetPC(); -+ /* start case */ - $$.nArgs = $1.nArgs; -+ $$ = 1; -+ - /* add code to push the rvalue expression index needed */ +- /* add code to push the rvalue expression index needed */ - ADD_OP(OP_PUSH_IMMED); ADD_IMMED($$.nArgs); - $$.start = $1.start; - $$.next = GetPC(); ++ $$ = 1; ++ /* add code to push the rvalue expression value */ + ADD_OP(OP_PUSH_IMMED); ADD_IMMED($$); + ADD_OP(OP_ARRAY_REF); ADD_IMMED(1); -+ /* swap this code in front of the lvalue assignment code */ - $$.mid = SwapCode($1.mid, $1.next, $$.next); + SwapCode($1, this, GetPC()); @@ -139,18 +174,16 @@ diff --quilt old/source/parse.y new/source/parse.y | lvlist ',' blank lventry { - /* recursive step case - starts similarly */ - $$.nArgs = $1.nArgs + $4.nArgs; -+ Inst *this = GetPC(); -+ -+ /* the index for this entry into the rvalue array */ -+ $$ = $1 + 1; -+ - /* add code to push the rvalue expression index needed */ +- /* add code to push the rvalue expression index needed */ - ADD_OP(OP_PUSH_IMMED); ADD_IMMED($$.nArgs); - $$.start = $1.start; - $$.next = GetPC(); ++ Inst *this = GetPC(); ++ /* the index for this entry into the rvalue array */ ++ $$ = $1 + 1; ++ /* add code to push the rvalue expression value */ + ADD_OP(OP_PUSH_IMMED); ADD_IMMED($$); + ADD_OP(OP_ARRAY_REF); ADD_IMMED(1); -+ /* swap this code in front of the lvalue assignment code */ - $4.mid = SwapCode($4.mid, $4.next, $$.next); - /* @@ -164,7 +197,7 @@ diff --quilt old/source/parse.y new/source/parse.y + SwapCode($4, this, GetPC()); } ; - /* lventry's value is the PC position between the Px and Ax parts */ +-/* lventry's value is the PC position between the Px and Ax parts */ -lventry: mark SYMBOL { - $$.nArgs = 1; - $$.start = $1; @@ -204,17 +237,21 @@ diff --quilt old/source/parse.y new/source/parse.y - /* stack: E, N, ... */ - ADD_OP(OP_SWAP_TOP2); /* stack: N, E, ... */ - ADD_OP(OP_ARRAY_REF); ADD_IMMED(1); /* stack: E[N] ... */ ++/* lventry's value is the start of the assignment code */ +lventry: SYMBOL { -+ ADD_OP(OP_DUP); /* duplicate expression array */ -+ $$ = GetPC(); /* need to move the next op */ ++ /* the rvalue is right on top, just dup it */ ++ ADD_OP(OP_DUP); ++ $$ = GetPC(); + ADD_OP(OP_ASSIGN); ADD_SYM($1); + } + | initarraylv '[' arglist ']' { ++ /* above the rvalue is the array + nDim strings */ + ADD_OP(OP_PEEK_PUSH); ADD_IMMED($3 + 1); + $$ = GetPC(); + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3); + } + | initarraylv dot field { ++ /* above the rvalue is the array + one string */ + ADD_OP(OP_PEEK_PUSH); ADD_IMMED(2); + $$ = GetPC(); ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1); -- 2.11.4.GIT