InterpretDebug-mods: calculate OpName length
[nedit-bw.git] / extend-for-key-in-array-syntax.patch
blob66bdd938a155c56316e734489064f3bf6072a315
1 ---
3 doc/help.etx | 5 +
4 source/interpret.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
5 source/interpret.h | 1
6 source/parse.y | 16 +++++
7 4 files changed, 175 insertions(+), 1 deletion(-)
9 diff --quilt old/source/interpret.c new/source/interpret.c
10 --- old/source/interpret.c
11 +++ new/source/interpret.c
12 @@ -132,10 +132,12 @@ static int branchNever(void);
13 static int arrayRef(void);
14 static int arrayAssign(void);
15 static int arrayRefAndAssignSetup(void);
16 static int beginArrayIter(void);
17 static int arrayIter(void);
18 +static int beginArrayIterKeyVal(void);
19 +static int arrayIterKeyVal(void);
20 static int inArray(void);
21 static int deleteArrayElement(void);
22 static int anonArrayOpen(void);
23 static int anonArraySkip(void);
24 static int anonArrayNextVal(void);
25 @@ -237,10 +239,11 @@ static int (*OpFns[N_OPS])() = {returnNo
26 anonArrayOpen, anonArraySkip, anonArrayNextVal, anonArrayIndexVal,
27 anonArrayClose, namedArg1, namedArgN, swapTop2,
28 callSubroutineStackedN,
29 unpackArrayToArgs,
30 arrayIndex,
31 + beginArrayIterKeyVal, arrayIterKeyVal,
34 /* Stack-> symN-sym0(FP), nArgs, oldFP, retPC, argArray, argN-arg1, next, ... */
35 #define FP_ARG_COUNT_INDEX (-1)
36 #define FP_FUNCTION_NAME (-2) /* !! */
37 @@ -3365,10 +3368,147 @@ static int arrayIter(void)
39 return(STAT_OK);
43 +** setup symbol values for key/value array iteration in interpreter
44 +**
45 +** Before: Prog-> [iter], ARRAY_ITER_KEYVAL, iterVarKey, iterVarVal, iter, endLoopBranch, next, ...
46 +** TheStack-> [arrayVal], next, ...
47 +** After: Prog-> iter, [ARRAY_ITER_KEYVAL], iterVarKey, iterVarVal, iter, endLoopBranch, next, ...
48 +** TheStack-> [next], ...
49 +** Where:
50 +** iter is a symbol which gives the position of the iterator value in
51 +** the stack frame
52 +** arrayVal is the data value holding the array in question
53 +*/
54 +static int beginArrayIterKeyVal(void)
56 + Symbol *iterator;
57 + DataValue *iteratorValPtr;
58 + DataValue arrayVal;
60 + DISASM_RT(PC-1, 2);
61 + STACKDUMP(1, 4);
63 + iterator = PC->sym;
64 + PC++;
66 + POP(arrayVal)
68 + if (iterator->type == LOCAL_SYM) {
69 + iteratorValPtr = &FP_GET_SYM_VAL(FrameP, iterator);
70 + }
71 + else {
72 + return(execError("bad temporary iterator: %s", iterator->name));
73 + }
75 + iteratorValPtr->tag = INT_TAG;
76 + if (arrayVal.tag != ARRAY_TAG) {
77 + return(execError("can't iterate non-array", NULL));
78 + }
80 + iteratorValPtr->val.arrayPtr = (SparseArrayEntry *)arrayIterateFirst(&arrayVal);
81 + return(STAT_OK);
84 +/*
85 +** copy key and value to symbols if node is still valid, marked bad by a color
86 +** of -1 then move iterator to next node
87 +** this allows iterators to progress even if you delete any node in the array
88 +** except the item just after the current key
89 +**
90 +** Before: Prog-> iter, ARRAY_ITER_KEYVAL, [iterVarKey], iterVarVal, iter, endLoopBranch, next, ...
91 +** TheStack-> [next], ...
92 +** After: Prog-> iter, ARRAY_ITER_KEYVAL, iterVarKey, iterVarVal, iter, endLoopBranch, [next], ...
93 +** TheStack-> [next], ... (unchanged)
94 +** Where:
95 +** iter is a symbol which gives the position of the iterator value in
96 +** the stack frame (set up by OP_BEGIN_ARRAY_ITER_KEYVAL); that value refers
97 +** to the array and a position within it
98 +** iterVarKey is the programmer-visible symbol which will take the current
99 +** key value
100 +** iterVarVal is the programmer-visible symbol which will take the current
101 +** entry value
102 +** endLoopBranch is the instruction offset to the instruction following the
103 +** loop (measured from itself)
104 +** arrayVal is the data value holding the array in question
105 +** The return-to-start-of-loop branch (at the end of the loop) should address
106 +** the ARRAY_ITER_KEYVAL instruction
108 +static int arrayIterKeyVal(void)
110 + Symbol *iterator;
111 + Symbol *itemKey;
112 + Symbol *itemVal;
113 + DataValue *iteratorValPtr;
114 + DataValue *itemVarKeyPtr;
115 + DataValue *itemVarValPtr;
116 + SparseArrayEntry *thisEntry;
117 + Inst *branchAddr;
119 + DISASM_RT(PC-1, 4);
120 + STACKDUMP(0, 4);
122 + itemKey = PC->sym;
123 + PC++;
124 + itemVal = PC->sym;
125 + PC++;
126 + iterator = PC->sym;
127 + PC++;
128 + branchAddr = PC + PC->value;
129 + PC++;
131 + if (itemKey->type == LOCAL_SYM) {
132 + itemVarKeyPtr = &FP_GET_SYM_VAL(FrameP, itemKey);
134 + else if (itemKey->type == GLOBAL_SYM) {
135 + itemVarKeyPtr = &(itemKey->value);
137 + else {
138 + return(execError("can't assign to: %s", itemKey->name));
140 + itemVarKeyPtr->tag = NO_TAG;
142 + if (itemVal->type == LOCAL_SYM) {
143 + itemVarValPtr = &FP_GET_SYM_VAL(FrameP, itemVal);
145 + else if (itemVal->type == GLOBAL_SYM) {
146 + itemVarValPtr = &(itemVal->value);
148 + else {
149 + return(execError("can't assign to: %s", itemVal->name));
151 + itemVarValPtr->tag = NO_TAG;
153 + if (iterator->type == LOCAL_SYM) {
154 + iteratorValPtr = &FP_GET_SYM_VAL(FrameP, iterator);
156 + else {
157 + return(execError("bad temporary iterator: %s", iterator->name));
160 + thisEntry = (SparseArrayEntry *)iteratorValPtr->val.arrayPtr;
161 + if (thisEntry && thisEntry->nodePtrs.color != -1) {
162 + /* set key */
163 + itemVarKeyPtr->tag = STRING_TAG;
164 + itemVarKeyPtr->val.str.rep = thisEntry->key;
165 + itemVarKeyPtr->val.str.len = strlen(thisEntry->key);
167 + /* set value */
168 + *itemVarValPtr = thisEntry->value;
170 + /* advance iterator */
171 + iteratorValPtr->val.arrayPtr = (SparseArrayEntry *)arrayIterateNext(thisEntry);
173 + else {
174 + PC = branchAddr;
176 + return(STAT_OK);
180 ** determine if a key or keys exists in an array
181 ** if the left argument is a string or integer a single check is performed
182 ** if the key exists, 1 is pushed onto the stack, otherwise 0
183 ** if the left argument is an array 1 is pushed onto the stack if every key
184 ** in the left array exists in the right array, otherwise 0
185 @@ -3760,10 +3900,12 @@ static void disasmInternal(Inst *inst, i
186 "NAMED_ARGN", /* namedArgN: "fn(..., [...]=...)" */
187 "SWAP_TOP2", /* swapTop2: cf namedArgN */
188 "SUBR_CALL_STACKED_N", /* callSubroutineStackedN */
189 "UNPACKTOARGS", /* unpackArrayToArgs */
190 "ARRAY_INDEX", /* arrayIndex */
191 + "BEGIN_ARRAY_ITER_KEYVAL", /* beginArrayIterKeyVal */
192 + "ARRAY_ITER_KEYVAL", /* arrayIterKeyVal */
194 int i, j;
195 static size_t opLen;
197 if (!opLen) {
198 @@ -3812,11 +3954,12 @@ static void disasmInternal(Inst *inst, i
200 else if (j == OP_SUBR_CALL_STACKED_N) {
201 printd(" %s args[] (?)", inst[i+1].sym->name);
202 ++i;
204 - else if (j == OP_BEGIN_ARRAY_ITER) {
205 + else if (j == OP_BEGIN_ARRAY_ITER ||
206 + j == OP_BEGIN_ARRAY_ITER_KEYVAL) {
207 printd(" %s in", inst[i+1].sym->name);
208 ++i;
210 else if (j == OP_ARRAY_ITER) {
211 printd(" %s = %s++ end-loop=(%+d) %8p",
212 @@ -3824,10 +3967,19 @@ static void disasmInternal(Inst *inst, i
213 inst[i+2].sym->name,
214 inst[i+3].value,
215 &inst[i+3] + inst[i+3].value);
216 i += 3;
218 + else if (j == OP_ARRAY_ITER_KEYVAL) {
219 + printf(" [%s]=%s = %s++ end-loop=(%+d) %p",
220 + inst[i+1].sym->name,
221 + inst[i+2].sym->name,
222 + inst[i+3].sym->name,
223 + inst[i+4].value,
224 + &inst[i+4] + inst[i+4].value);
225 + i += 4;
227 else if (j == OP_ARRAY_REF ||
228 j == OP_ARRAY_DELETE ||
229 j == OP_ARRAY_ASSIGN ||
230 j == OP_ANONARRAY_INDEX_VAL ||
231 j == OP_NAMED_ARG1 ||
232 diff --quilt old/source/interpret.h new/source/interpret.h
233 --- old/source/interpret.h
234 +++ new/source/interpret.h
235 @@ -53,10 +53,11 @@ enum operations {OP_RETURN_NO_VAL, OP_RE
236 OP_ANONARRAY_INDEX_VAL, OP_ANONARRAY_CLOSE,
237 OP_NAMED_ARG1, OP_NAMED_ARGN, OP_SWAP_TOP2,
238 OP_SUBR_CALL_STACKED_N,
239 OP_UNPACKTOARGS,
240 OP_ARRAY_INDEX,
241 + OP_BEGIN_ARRAY_ITER_KEYVAL, OP_ARRAY_ITER_KEYVAL,
242 N_OPS};
244 enum typeTags {NO_TAG, INT_TAG, STRING_TAG, ARRAY_TAG};
246 enum execReturnCodes {MACRO_TIME_LIMIT, MACRO_PREEMPT, MACRO_DONE, MACRO_ERROR};
247 diff --quilt old/source/parse.y new/source/parse.y
248 --- old/source/parse.y
249 +++ new/source/parse.y
250 @@ -153,10 +153,26 @@ stmt: ';' blank
251 blank block {
252 ADD_OP(OP_BRANCH); ADD_BR_OFF($7+2);
253 SET_BR_OFF($7+5, GetPC());
254 FillLoopAddrs(GetPC(), $7+2);
256 + | for '(' blank '[' SYMBOL ']' '=' SYMBOL IN blank arrayexpr blank ')' {
257 + Symbol *iterSym = InstallIteratorSymbol();
258 + ADD_OP(OP_BEGIN_ARRAY_ITER_KEYVAL);
259 + ADD_SYM(iterSym);
260 + ADD_OP(OP_ARRAY_ITER_KEYVAL);
261 + ADD_SYM($5);
262 + ADD_SYM($8);
263 + ADD_SYM(iterSym);
264 + ADD_BR_OFF(0);
266 + blank block {
267 + ADD_OP(OP_BRANCH);
268 + ADD_BR_OFF($11+2);
269 + SET_BR_OFF($11+6, GetPC());
270 + FillLoopAddrs(GetPC(), $11+2);
272 | BREAK stmtend blank {
273 ADD_OP(OP_BRANCH); ADD_BR_OFF(0);
274 if (AddBreakAddr(GetPC()-1)) {
275 yyerror("break outside loop"); YYERROR;
277 diff --quilt old/doc/help.etx new/doc/help.etx
278 --- old/doc/help.etx
279 +++ new/doc/help.etx
280 @@ -2259,10 +2259,15 @@ Macro Language
281 Keys are not guaranteed in any particular order:
283 for (aKey in x)
284 <body>
286 + Or, to get also the corresponding value for the key:
288 + for ([aKey]=theVal in x)
289 + <body>
291 Elements can be removed from an array using the delete command:
293 delete x[3] # deletes element with key 3
294 delete x[] # deletes all elements