fix apply errors
[nedit-bw.git] / MultipleAssignment-redux.patch
blob5d04385e0a381af79f5a245642447749ca366ce5
1 ---
3 source/interpret.c | 47 ++++++++++------
4 source/interpret.h | 1
5 source/ops.h | 1
6 source/parse.y | 153 +++++++++++++++--------------------------------------
7 4 files changed, 77 insertions(+), 125 deletions(-)
9 diff --quilt old/source/interpret.c new/source/interpret.c
10 --- old/source/interpret.c
11 +++ new/source/interpret.c
12 @@ -818,23 +818,6 @@ void SetMacroFocusWindow(WindowInfo *win
16 -** install a list assign (multi-assign) rvalue expression holder into the local
17 -** namespace.
18 -*/
19 -Symbol *InstallMultiAssignExpr(void)
21 - static const char symbolName[] = "list assign expr";
22 - Symbol *sym = LookupSymbol(symbolName);
23 - DataValue value;
24 - value.tag = NO_TAG;
25 - value.val.n = 0;
26 - if (!sym) {
27 - sym = InstallSymbol(symbolName, LOCAL_SYM, value);
28 - }
29 - return sym;
32 -/*
33 ** Lookup a constant string by its value. This allows reuse of string
34 ** constants and fixing a leak in the interpreter.
36 @@ -2059,6 +2042,30 @@ static int dupStack(void)
40 +** copy the value at stack postion index onto the stack
41 +** Before: Prog-> [index], next, ...
42 +** TheStack-> val0, ... valIndex, next, ...
43 +** After: Prog-> index, [next], ...
44 +** TheStack-> valIndex, val0, ... valIndex, next, ...
45 +*/
46 +static int peekPush(void)
48 + DataValue value;
49 + int index;
51 + DISASM_RT();
53 + GET_IMMED(index);
55 + STACKDUMP(index + 1, 3);
57 + PEEK(value, index);
58 + PUSH(value);
60 + return STAT_OK;
63 +/*
64 ** if left and right arguments are arrays, then the result is a new array
65 ** in which all the keys from both the right and left are copied
66 ** the values from the right array are used in the result array when the
67 @@ -4508,6 +4515,12 @@ static void disasmInternal(Inst *inst, i
68 ++i;
69 break;
71 + case OP_PEEK_PUSH:
72 + CHECK_OPERANDS(1, IMMED_INST);
73 + dumpInst(&inst[i+1], "index");
74 + ++i;
75 + break;
77 case OP_BRANCH:
78 case OP_BRANCH_TRUE:
79 case OP_BRANCH_FALSE:
80 diff --quilt old/source/ops.h new/source/ops.h
81 --- old/source/ops.h
82 +++ new/source/ops.h
83 @@ -9,6 +9,7 @@ OP(PUSH_SYM, pushSymVal)
84 OP(PUSH_IMMED, pushImmed) /* immed */ /* push(immed) */
85 OP(POP, popStack) /* pop(v) */
86 OP(DUP, dupStack) /* pop(v), push(v,v) */
87 +OP(PEEK_PUSH, peekPush) /* n */ /* peek(v, n), push(v) */
88 OP(ADD, add) /* pop(v2,v1), push(v1 + v2) */
89 OP(SUB, subtract) /* pop(v2,v1), push(v1 - v2) */
90 OP(MUL, multiply) /* pop(v2,v1), push(v1 * v2) */
91 diff --quilt old/source/parse.y new/source/parse.y
92 --- old/source/parse.y
93 +++ new/source/parse.y
94 @@ -102,15 +102,6 @@ static int nextSymIsField = 0;
95 /* set to 1 when we don't want a full symbol, just a name (string) for a
96 field name following a '.' */
98 -/*
99 -** Positions holder for instruction reordering of code generated for the
100 -** left-hand lvalue list in a multi-assignment statement.
102 -typedef struct LVinst {
103 - Inst *start, *mid, *next;
104 - int nArgs;
105 -} LVinst;
109 %union {
110 @@ -118,7 +109,6 @@ typedef struct LVinst {
111 Inst *inst;
112 int num;
113 enum operations oper;
114 - LVinst lvinst;
115 struct {
116 AccumulatorData *acc;
117 Symbol *sym;
118 @@ -135,7 +125,8 @@ typedef struct LVinst {
119 %type <oper> operassign incrdecr
120 %token <oper> '=' ADDEQ SUBEQ MULEQ DIVEQ MODEQ ANDEQ OREQ
121 %token <oper> INCR DECR
122 -%type <lvinst> lvlist lventry
123 +%type <num> lvlist
124 +%type <inst> lventry
125 %token ARGSEP
127 %nonassoc IF_NO_ELSE
128 @@ -413,113 +404,61 @@ simpstmt: /* simple variable assignmen
130 ** Implementing a multi-assignment to a list of lvalues
132 -** Each accepting lvalue requires a push phase P and an assign phase A.
134 -** For arrays, P includes pushing the indices and the destination array value.
135 -** P always also includes pushing N, the position of the lval in the list, i.e.
136 -** the index into the r.h.s. array expression supplying values.
138 -** The assign phase uses N (on the stack) and the stored result E of the source
139 -** array expression - this gives the indexed r.h.s. value to assign. Then, if
140 -** the destination is an array element, the destination array and indices are
141 -** retrieved from the stack and the assignment performed.
142 +** We do this by executing the rvalue first, and than do the assignment phase
143 +** afterward.
145 -** Given "(a, b, c) = e", we need to end up with the command sequence:
146 -** Pc Pb Pa Ee Aa Ab Ac
147 -** However, we have to generate Px and Ax together in the parse. Hence we
148 -** must reorder, using PC mark positions Mx. For the example, we generate:
149 -** read a: M0[Pa]M1[Aa]Mt here Mt is the current GetPC() value
150 -** read b: M0[Pa]M1[Aa]M2[Pb]M3[Ab]Mt now swap(M0, M2, M3)
151 -** M0[Pb Pa]M1[Aa Ab]Mt
152 -** and c: M0[Pb Pa]M1[Aa Ab]M2[Pc]M3[Ac]Mt swap(M0, M2, M3)
153 -** M0[Pc Pb Pa]M1[Aa Ab Ac]Mt
154 -** then e: M0[Pc Pb Pa]M1[Aa Ab Ac]M2[Ee]Mt swap(M1, M2, Mt)
155 -** [Pc Pb Pa][Ee][Aa Ab Ac]
156 -** which is what we want. At each swap, we must retain intermediate positions.
157 -** Below for lvlist, M0 is $$.start, M1 is $$.mid, M2 is $$.next. lventry's $$
158 -** gives the mid value between the P and A phases (M1).
159 +** The rvalue value is constantly duped on the stack to do the array ref.
161 -lvlistexpr: '(' lvlist ')' blank '=' blank expr {
162 - /* store expression value */
163 - ADD_OP(OP_ASSIGN); ADD_SYM(InstallMultiAssignExpr());
164 - /* swap expression evaluation code into position */
165 - SwapCode($2.mid, $2.next, GetPC());
166 +lvlistexpr: '(' mark lvlist mark ')' blank '=' blank expr {
167 + /* swap expression evaluation code to front */
168 + SwapCode($2, $4, GetPC());
169 + ADD_OP(OP_POP); /* pop expression */
173 -** lvlist: code for pushing the expression's index is generated here, after the code
174 -** for assigning to the lvalue. In other words, the Px portion is split, with
175 -** the assign code in front of the push index code. This needs to be swapped.
176 -** Only then do we have the situation described for overall list assignment.
177 +** lvlist: code for doing the rvalue array ref.
179 +** We need to move this code infront of the actual assignment operation of
180 +** the lvalue, so that the result is ontop od the stack.
181 +** lventry's value will give us the start of this code.
183 -lvlist: lventry {
184 +lvlist: lventry mark {
185 /* start case */
186 - $$.nArgs = $1.nArgs;
187 - /* add code to push the rvalue expression index needed */
188 - ADD_OP(OP_PUSH_IMMED); ADD_IMMED($$.nArgs);
189 - $$.start = $1.start;
190 - $$.next = GetPC();
191 + $$ = 1;
192 + /* add code to push the rvalue expression value */
193 + ADD_OP(OP_PUSH_IMMED); ADD_IMMED($$);
194 + ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
195 /* swap this code in front of the lvalue assignment code */
196 - $$.mid = SwapCode($1.mid, $1.next, $$.next);
197 + SwapCode($1, $2, GetPC());
199 - | lvlist ',' blank lventry {
200 - /* recursive step case - starts similarly */
201 - $$.nArgs = $1.nArgs + $4.nArgs;
202 - /* add code to push the rvalue expression index needed */
203 - ADD_OP(OP_PUSH_IMMED); ADD_IMMED($$.nArgs);
204 - $$.start = $1.start;
205 - $$.next = GetPC();
206 + | lvlist ',' blank lventry mark {
207 + /* the index for this entry into the rvalue array */
208 + $$ = $1 + 1;
209 + /* add code to push the rvalue expression value */
210 + ADD_OP(OP_PUSH_IMMED); ADD_IMMED($$);
211 + ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
212 /* swap this code in front of the lvalue assignment code */
213 - $4.mid = SwapCode($4.mid, $4.next, $$.next);
214 - /*
215 - ** now swap Px code to midpoint and change midpoint
216 - ** $1.start[P...]$1.mid[A...]$1.next[Px]$4.mid[Ax]$$.next --->
217 - ** $1.start[Px][P...]$1.mid[A...]$4.mid[Ax]$$.next
218 - */
219 - SwapCode($1.start, $1.next, $4.mid);
220 - $$.start = $1.start; /* keep start point */
221 - $$.mid = $1.mid + ($4.mid - $1.next); /* adjust mid point */
224 -/* lventry's value is the PC position between the Px and Ax parts */
225 -lventry: mark SYMBOL {
226 - $$.nArgs = 1;
227 - $$.start = $1;
228 - /* Push code: null */
229 - $$.mid = GetPC();
230 - /* Assign code: stack: N, ... */
231 - ADD_OP(OP_PUSH_SYM); ADD_SYM(InstallMultiAssignExpr());
232 - /* stack: E, N, ... */
233 - ADD_OP(OP_SWAP_TOP2); /* stack: N, E, ... */
234 - ADD_OP(OP_ARRAY_REF); ADD_IMMED(1); /* stack: E[N] ... */
235 - ADD_OP(OP_ASSIGN); ADD_SYM($2);
236 - $$.next = GetPC();
238 - | mark initarraylv '[' arglist ']' {
239 - $$.nArgs = 1;
240 - $$.start = $1;
241 - /* Push code dealt with in "initarraylv '[' arglist ']'" */
242 - $$.mid = GetPC();
243 - /* Assign code: stack: N, ... */
244 - ADD_OP(OP_PUSH_SYM); ADD_SYM(InstallMultiAssignExpr());
245 - /* stack: E, N, ... */
246 - ADD_OP(OP_SWAP_TOP2); /* stack: N, E, ... */
247 - ADD_OP(OP_ARRAY_REF); ADD_IMMED(1); /* stack: E[N] ... */
248 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($4);
249 - $$.next = GetPC();
251 - | mark initarraylv dot field {
252 - $$.nArgs = 1;
253 - $$.start = $1;
254 - /* Push code dealt with in "initarraylv dot field" */
255 - $$.mid = GetPC();
256 - /* Assign code: stack: N, ... */
257 - ADD_OP(OP_PUSH_SYM); ADD_SYM(InstallMultiAssignExpr());
258 - /* stack: E, N, ... */
259 - ADD_OP(OP_SWAP_TOP2); /* stack: N, E, ... */
260 - ADD_OP(OP_ARRAY_REF); ADD_IMMED(1); /* stack: E[N] ... */
261 + SwapCode($4, $5, GetPC());
264 +/* lventry's value is the start of the assignment code */
265 +lventry: SYMBOL {
266 + /* the rvalue is right on top, just dup it */
267 + ADD_OP(OP_DUP);
268 + $$ = GetPC();
269 + ADD_OP(OP_ASSIGN); ADD_SYM($1);
271 + | initarraylv '[' arglist ']' {
272 + /* above the rvalue is the array + nDim strings */
273 + ADD_OP(OP_PEEK_PUSH); ADD_IMMED($3 + 1);
274 + $$ = GetPC();
275 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
277 + | initarraylv dot field {
278 + /* above the rvalue is the array + one string */
279 + ADD_OP(OP_PEEK_PUSH); ADD_IMMED(2);
280 + $$ = GetPC();
281 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
282 - $$.next = GetPC();
286 diff --quilt old/source/interpret.h new/source/interpret.h
287 --- old/source/interpret.h
288 +++ new/source/interpret.h
289 @@ -165,7 +165,6 @@ Symbol *LookupStringConstSymbol(const ch
290 Symbol *InstallStringConstSymbol(const char *str);
291 Symbol *LookupSymbol(const char *name);
292 Symbol *InstallSymbol(const char *name, enum symTypes type, DataValue value);
293 -Symbol *InstallMultiAssignExpr(void);
294 Inst *SwapCode(Inst *start, Inst *boundary, Inst *end);
295 int StartLoopAddrList(char **msg);
296 int AddBreakAddr(Inst *addr, char **msg);