4 source/interpret.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
6 source/parse.y | 35 +++++++
7 4 files changed, 281 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 @@ -157,10 +157,13 @@ static int arrayEntryCompare(rbTreeNode
13 static void arrayDisposeNode(rbTreeNode *src);
14 static SparseArrayEntry *allocateSparseArrayEntry(void);
15 static int typeOfIn(void);
16 static int typeOfOut(void);
17 static int arrayMultiIter(void);
18 +static int beginArrayMultiIterArray(void);
19 +static int arrayMultiIterArray(void);
20 +static int pop(void);
22 /* is the intepreter in the special typeof() mode? */
23 static int inTypeOfMode;
25 static const char *tagToStr(enum typeTags tag);
26 @@ -247,10 +250,11 @@ static int (*OpFns[N_OPS])() = {returnNo
27 callSubroutineStackedN,
32 + beginArrayMultiIterArray, arrayMultiIterArray, pop,
35 /* Stack-> symN-sym0(FP), nArgs, oldFP, retPC, argArray, argN-arg1, next, ... */
36 #define FP_ARG_COUNT_INDEX (-1)
37 #define FP_FUNCTION_NAME (-2) /* !! */
38 @@ -3667,10 +3671,217 @@ static int arrayMultiIter(void)
44 +** Before: Prog-> [iter], ARRAY_MULTI_ITER_ARRAY, withVal, iterVarKeyArray(, iterVarVal), iter, endLoopBranch, next, ...
45 +** TheStack-> [arrayVal], nDims, next, ...
46 +** After: Prog-> iter, [ARRAY_MULTI_ITER_ARRAY], withVal, iterVarKeyArray(, iterVarVal), iter, endLoopBranch, next, ...
47 +** TheStack-> [nDims], next, ...
49 +static int beginArrayMultiIterArray(void)
52 + DataValue *iteratorValPtr;
65 + if (iterator->type == LOCAL_SYM) {
66 + iteratorValPtr = &FP_GET_SYM_VAL(FrameP, iterator);
69 + return(execError("bad temporary iterator: %s", iterator->name));
73 + return(execError("bad multi dimension", NULL));
76 + iteratorValPtr->tag = INT_TAG;
77 + if (arrayVal.tag != ARRAY_TAG) {
78 + return(execError("can't iterate non-array", NULL));
81 + iteratorValPtr->val.arrayPtr = arrayIterateFirst(&arrayVal);
86 +static Boolean splitKeyArr(const char *key, DataValue *keyArr)
89 + size_t seplen = strlen(ARRAY_DIM_SEP);
91 + const char *sep = key;
92 + const char *nextsep = key;
96 + nextsep = strstr(sep, ARRAY_DIM_SEP);
98 + keylen = nextsep - sep;
100 + keylen = strlen(sep);
103 + keyVal.tag = STRING_TAG;
104 + if (!AllocNStringNCpy(&keyVal.val.str, sep, keylen)) {
108 + if (!ArrayInsert(keyArr, AllocStringOfNumber(nDims), &keyVal)) {
123 +** Before: Prog-> iter, ARRAY_MULTI_ITER_ARRAY, [withVal], iterVarKeyArray, (, iterVarVal), iter, endLoopBranch, next, ...
124 +** TheStack-> [nDims], next, ...
125 +** After: Prog-> iter, ARRAY_MULTI_ITER_ARRAY, withVal, iterVarKeyArray, (, iterVarVal), iter, endLoopBranch, [next], ...
126 +** TheStack-> [nDims], next, ... (unchanged)
128 +static int arrayMultiIterArray(void)
131 + Symbol *itemArrKey;
133 + DataValue *iteratorValPtr;
134 + DataValue *itemVarArrKeyPtr;
135 + DataValue *itemVarValPtr;
136 + SparseArrayEntry *thisEntry;
140 + Boolean keyFound = False;
142 + DISASM_RT(PC-1, 4);
145 + withVal = PC->value;
148 + PEEK_INT(nDims, 0);
150 + itemArrKey = PC->sym;
158 + iterator = PC->sym;
160 + branchAddr = PC + PC->value;
163 + if (itemArrKey->type == LOCAL_SYM) {
164 + itemVarArrKeyPtr = &FP_GET_SYM_VAL(FrameP, itemArrKey);
166 + else if (itemArrKey->type == GLOBAL_SYM) {
167 + itemVarArrKeyPtr = &(itemArrKey->value);
170 + return(execError("can't assign to: %s", itemArrKey->name));
172 + itemVarArrKeyPtr->tag = ARRAY_TAG;
173 + itemVarArrKeyPtr->val.arrayPtr = NULL;
176 + if (itemVal->type == LOCAL_SYM) {
177 + itemVarValPtr = &FP_GET_SYM_VAL(FrameP, itemVal);
179 + else if (itemVal->type == GLOBAL_SYM) {
180 + itemVarValPtr = &(itemVal->value);
183 + return(execError("can't assign to: %s", itemVal->name));
185 + itemVarValPtr->tag = NO_TAG;
188 + if (iterator->type == LOCAL_SYM) {
189 + iteratorValPtr = &FP_GET_SYM_VAL(FrameP, iterator);
192 + return(execError("bad temporary iterator: %s", iterator->name));
195 + thisEntry = iteratorValPtr->val.arrayPtr;
196 + while (thisEntry && thisEntry->nodePtrs.color != -1) {
197 + /* check if this is a nDims key */
198 + int thisDim = countDim(thisEntry->key);
200 + if (nDims != thisDim) {
202 + thisEntry = arrayIterateNext(thisEntry);
209 + if (!splitKeyArr(thisEntry->key, itemVarArrKeyPtr)) {
210 + return(execError("can't split key: %s", thisEntry->key));
215 + *itemVarValPtr = thisEntry->value;
218 + /* advance iterator */
219 + thisEntry = arrayIterateNext(thisEntry);
222 + iteratorValPtr->val.arrayPtr = thisEntry;
224 + if (!keyFound && (!thisEntry || thisEntry->nodePtrs.color == -1)) {
233 +** Before: Prog-> next, ...
234 +** TheStack-> [val], next, ...
235 +** After: Prog-> next, ... (unchanged)
236 +** TheStack-> [next], ...
238 +static int pop(void)
242 + DISASM_RT(PC-1, 1);
251 ** determine if a key or keys exists in an array
252 ** if the left argument is a string or integer a single check is performed
253 ** if the key exists, 1 is pushed onto the stack, otherwise 0
254 ** if the left argument is an array 1 is pushed onto the stack if every key
255 ** in the left array exists in the right array, otherwise 0
256 @@ -4129,10 +4340,13 @@ static void disasmInternal(Inst *inst, i
257 "UNPACKTOARGS", /* unpackArrayToArgs */
258 "TYPEOF_IN", /* typeOfIn */
259 "TYPEOF_OUT", /* typeOfOut */
260 "ARRAY_INDEX", /* arrayIndex */
261 "ARRAY_MULTI_ITER", /* arrayMultiIter */
262 + "BEGIN_ARRAY_MULTI_ITER_ARRAY", /* beginArrayMultiIterArray */
263 + "ARRAY_MULTI_ITER_ARRAY", /* arrayMultiIterArray */
270 @@ -4181,11 +4395,12 @@ static void disasmInternal(Inst *inst, i
272 else if (j == OP_SUBR_CALL_STACKED_N) {
273 printd(" %s args[] (?)", inst[i+1].sym->name);
276 - else if (j == OP_BEGIN_ARRAY_ITER) {
277 + else if (j == OP_BEGIN_ARRAY_ITER ||
278 + j == OP_BEGIN_ARRAY_MULTI_ITER_ARRAY) {
279 printd(" %s in", inst[i+1].sym->name);
282 else if (j == OP_ARRAY_ITER) {
283 if (!inst[i+1].value) {
284 @@ -4238,10 +4453,31 @@ static void disasmInternal(Inst *inst, i
285 inst[i+nDim+5].value,
286 &inst[i+nDim+5] + inst[i+nDim+5].value);
290 + else if (j == OP_ARRAY_MULTI_ITER_ARRAY) {
291 + if (!inst[i+1].value) {
293 + printd(" %s[] = %s++ end-loop=(%+d) %8p",
294 + inst[i+2].sym->name,
295 + inst[i+3].sym->name,
297 + &inst[i+4] + inst[i+4].value);
302 + printd(" %s[]=%s = %s++ end-loop=(%+d) %8p",
303 + inst[i+2].sym->name,
304 + inst[i+3].sym->name,
305 + inst[i+4].sym->name,
307 + &inst[i+5] + inst[i+5].value);
311 else if (j == OP_ARRAY_REF ||
312 j == OP_ARRAY_DELETE ||
313 j == OP_ARRAY_ASSIGN ||
314 j == OP_ANONARRAY_INDEX_VAL ||
315 j == OP_NAMED_ARG1 ||
316 diff --quilt old/source/interpret.h new/source/interpret.h
317 --- old/source/interpret.h
318 +++ new/source/interpret.h
319 @@ -55,10 +55,11 @@ enum operations {OP_RETURN_NO_VAL, OP_RE
320 OP_SUBR_CALL_STACKED_N,
322 OP_TYPEOF_IN, OP_TYPEOF_OUT,
325 + OP_BEGIN_ARRAY_MULTI_ITER_ARRAY, OP_ARRAY_MULTI_ITER_ARRAY, OP_POP,
328 enum typeTags {NO_TAG, INT_TAG, STRING_TAG, ARRAY_TAG};
330 enum execReturnCodes {MACRO_TIME_LIMIT, MACRO_PREEMPT, MACRO_DONE, MACRO_ERROR};
331 diff --quilt old/source/parse.y new/source/parse.y
332 --- old/source/parse.y
333 +++ new/source/parse.y
334 @@ -269,10 +269,45 @@ stmt: ';' blank
337 SET_BR_OFF($11+7+$5.nSyms, GetPC());
338 FillLoopAddrs(GetPC(), $11+2);
340 + | for '(' blank SYMBOL '[' numexpr ']' IN blank arrayexpr blank ')' {
341 + Symbol *iterSym = InstallIteratorSymbol();
342 + ADD_OP(OP_BEGIN_ARRAY_MULTI_ITER_ARRAY);
344 + ADD_OP(OP_ARRAY_MULTI_ITER_ARRAY);
345 + ADD_IMMED(0); /* without val symbol */
353 + SET_BR_OFF($10+6, GetPC());
354 + FillLoopAddrs(GetPC(), $10+2);
357 + | for '(' blank SYMBOL '[' numexpr ']' KEYVAL SYMBOL IN blank arrayexpr blank ')' {
358 + Symbol *iterSym = InstallIteratorSymbol();
359 + ADD_OP(OP_BEGIN_ARRAY_MULTI_ITER_ARRAY);
361 + ADD_OP(OP_ARRAY_MULTI_ITER_ARRAY);
362 + ADD_IMMED(1); /* with val symbol */
371 + SET_BR_OFF($12+7, GetPC());
372 + FillLoopAddrs(GetPC(), $12+2);
375 | BREAK stmtend blank {
376 ADD_OP(OP_BRANCH); ADD_BR_OFF(0);
377 if (AddBreakAddr(GetPC()-1)) {
378 yyerror("break outside loop"); YYERROR;
380 diff --quilt old/doc/help.etx new/doc/help.etx
383 @@ -2349,10 +2349,18 @@ Macro Language
384 Also with the associated value for the multi-dimensional key:
386 for ([dim1Key, ..., dimNKey] = theVal in myArray)
389 + As a last iterator variant, you can use this syntax:
391 + for (keyArray[nDim] in myArray)
394 + where this loop iterates over all keys with dimension nDim and puts the
395 + dimension keys into the array keyArray (starting with 0).
397 Note that if an array contains a value that is itself an array, you can
398 apply the index operator more than once. For example
400 subarray["a"] = "value"
401 mainarray[1] = subarray