4 source/interpret.c | 102 +++++++++++++++++++++++++++++++++++++----------------
5 source/parse.y | 31 ++++++++++++++--
6 3 files changed, 105 insertions(+), 33 deletions(-)
8 diff --quilt old/source/interpret.c new/source/interpret.c
9 --- old/source/interpret.c
10 +++ new/source/interpret.c
11 @@ -3245,13 +3245,13 @@ static int arrayRefAndAssignSetup(void)
15 ** setup symbol values for array iteration in interpreter
17 -** Before: Prog-> [iter], ARRAY_ITER, iterVar, iter, endLoopBranch, next, ...
18 +** Before: Prog-> [iter], ARRAY_ITER, withVal, iterVarKey(, iterVarVal), iter, endLoopBranch, next, ...
19 ** TheStack-> [arrayVal], next, ...
20 -** After: Prog-> iter, [ARRAY_ITER], iterVar, iter, endLoopBranch, next, ...
21 +** After: Prog-> iter, [ARRAY_ITER], withVal, iterVarKey(, iterVarVal), iter, endLoopBranch, next, ...
22 ** TheStack-> [next], ...
24 ** iter is a symbol which gives the position of the iterator value in
26 ** arrayVal is the data value holding the array in question
27 @@ -3285,74 +3285,105 @@ static int beginArrayIter(void)
28 iteratorValPtr->val.arrayPtr = arrayIterateFirst(&arrayVal);
33 -** copy key to symbol if node is still valid, marked bad by a color of -1
34 -** then move iterator to next node
35 +** copy key and value to symbols if node is still valid, marked bad by a color
36 +** of -1 then move iterator to next node
37 ** this allows iterators to progress even if you delete any node in the array
38 ** except the item just after the current key
40 -** Before: Prog-> iter, ARRAY_ITER, [iterVar], iter, endLoopBranch, next, ...
41 +** Before: Prog-> iter, ARRAY_ITER, [withVal], iterVarKey(, iterVarVal), iter, endLoopBranch, next, ...
42 ** TheStack-> [next], ...
43 -** After: Prog-> iter, ARRAY_ITER, iterVar, iter, endLoopBranch, [next], ...
44 +** After: Prog-> iter, ARRAY_ITER, withVal, iterVarKey(, iterVarVal), iter, endLoopBranch, [next], ...
45 ** TheStack-> [next], ... (unchanged)
48 ** iter is a symbol which gives the position of the iterator value in
49 -** the stack frame (set up by BEGIN_ARRAY_ITER); that value refers
50 +** the stack frame (set up by OP_BEGIN_ARRAY_ITER); that value refers
51 ** to the array and a position within it
52 -** iterVal is the programmer-visible symbol which will take the current
53 +** iterVarKey is the programmer-visible symbol which will take the current
55 +** iterVarVal is the programmer-visible symbol which will take the current
56 +** entry value (only if withVal is true)
57 ** endLoopBranch is the instruction offset to the instruction following the
58 ** loop (measured from itself)
59 ** arrayVal is the data value holding the array in question
60 ** The return-to-start-of-loop branch (at the end of the loop) should address
61 ** the ARRAY_ITER instruction
63 static int arrayIter(void)
69 DataValue *iteratorValPtr;
70 - DataValue *itemValPtr;
71 + DataValue *itemVarKeyPtr;
72 + DataValue *itemVarValPtr;
73 SparseArrayEntry *thisEntry;
82 + withVal = PC->value;
92 branchAddr = PC + PC->value;
95 - if (item->type == LOCAL_SYM) {
96 - itemValPtr = &FP_GET_SYM_VAL(FrameP, item);
97 + if (itemKey->type == LOCAL_SYM) {
98 + itemVarKeyPtr = &FP_GET_SYM_VAL(FrameP, itemKey);
100 - else if (item->type == GLOBAL_SYM) {
101 - itemValPtr = &(item->value);
102 + else if (itemKey->type == GLOBAL_SYM) {
103 + itemVarKeyPtr = &(itemKey->value);
106 - return(execError("can't assign to: %s", item->name));
107 + return(execError("can't assign to: %s", itemKey->name));
109 + itemVarKeyPtr->tag = NO_TAG;
112 + if (itemVal->type == LOCAL_SYM) {
113 + itemVarValPtr = &FP_GET_SYM_VAL(FrameP, itemVal);
115 + else if (itemVal->type == GLOBAL_SYM) {
116 + itemVarValPtr = &(itemVal->value);
119 + return(execError("can't assign to: %s", itemVal->name));
121 + itemVarValPtr->tag = NO_TAG;
123 - itemValPtr->tag = NO_TAG;
125 if (iterator->type == LOCAL_SYM) {
126 iteratorValPtr = &FP_GET_SYM_VAL(FrameP, iterator);
129 return(execError("bad temporary iterator: %s", iterator->name));
132 thisEntry = iteratorValPtr->val.arrayPtr;
133 if (thisEntry && thisEntry->nodePtrs.color != -1) {
134 - itemValPtr->tag = STRING_TAG;
135 - itemValPtr->val.str.rep = thisEntry->key;
136 - itemValPtr->val.str.len = strlen(thisEntry->key);
139 + itemVarKeyPtr->tag = STRING_TAG;
140 + itemVarKeyPtr->val.str.rep = thisEntry->key;
141 + itemVarKeyPtr->val.str.len = strlen(thisEntry->key);
145 + *itemVarValPtr = thisEntry->value;
148 + /* advance iterator */
149 iteratorValPtr->val.arrayPtr = arrayIterateNext(thisEntry);
154 @@ -3860,16 +3891,29 @@ static void disasmInternal(Inst *inst, i
155 else if (j == OP_BEGIN_ARRAY_ITER) {
156 printd(" %s in", inst[i+1].sym->name);
159 else if (j == OP_ARRAY_ITER) {
160 - printd(" %s = %s++ end-loop=(%+d) %8p",
161 - inst[i+1].sym->name,
162 - inst[i+2].sym->name,
164 - &inst[i+3] + inst[i+3].value);
166 + if (!inst[i+1].value) {
168 + printd(" %s = %s++ end-loop=(%+d) %8p",
169 + inst[i+2].sym->name,
170 + inst[i+3].sym->name,
172 + &inst[i+4] + inst[i+4].value);
177 + printd(" %s=%s = %s++ end-loop=(%+d) %8p",
178 + inst[i+2].sym->name,
179 + inst[i+3].sym->name,
180 + inst[i+4].sym->name,
182 + &inst[i+5] + inst[i+5].value);
186 else if (j == OP_ARRAY_REF ||
187 j == OP_ARRAY_DELETE ||
188 j == OP_ARRAY_ASSIGN ||
189 j == OP_ANONARRAY_INDEX_VAL ||
190 diff --quilt old/source/parse.y new/source/parse.y
191 --- old/source/parse.y
192 +++ new/source/parse.y
193 @@ -145,18 +145,41 @@ stmt: ';' blank
194 SwapCode($5+1, $7, GetPC());
195 ADD_OP(OP_BRANCH); ADD_BR_OFF($3); SET_BR_OFF($5, GetPC());
197 | for '(' blank SYMBOL IN blank arrayexpr blank ')' {
198 Symbol *iterSym = InstallIteratorSymbol();
199 - ADD_OP(OP_BEGIN_ARRAY_ITER); ADD_SYM(iterSym);
200 - ADD_OP(OP_ARRAY_ITER); ADD_SYM($4); ADD_SYM(iterSym); ADD_BR_OFF(0);
201 + ADD_OP(OP_BEGIN_ARRAY_ITER);
203 + ADD_OP(OP_ARRAY_ITER);
204 + ADD_IMMED(0); /* without val symbol */
210 - ADD_OP(OP_BRANCH); ADD_BR_OFF($7+2);
211 - SET_BR_OFF($7+5, GetPC());
214 + SET_BR_OFF($7+6, GetPC());
215 FillLoopAddrs(GetPC(), $7+2);
217 + | for '(' blank SYMBOL ':' SYMBOL IN blank arrayexpr blank ')' {
218 + Symbol *iterSym = InstallIteratorSymbol();
219 + ADD_OP(OP_BEGIN_ARRAY_ITER);
221 + ADD_OP(OP_ARRAY_ITER);
222 + ADD_IMMED(1); /* with val symbol */
231 + SET_BR_OFF($9+7, GetPC());
232 + FillLoopAddrs(GetPC(), $9+2);
234 | BREAK stmtend blank {
235 ADD_OP(OP_BRANCH); ADD_BR_OFF(0);
236 if (AddBreakAddr(GetPC()-1)) {
237 yyerror("break outside loop"); YYERROR;
239 diff --quilt old/doc/help.etx new/doc/help.etx
242 @@ -2256,10 +2256,15 @@ Macro Language
243 Keys are not guaranteed in any particular order:
248 + Or, to get also the corresponding value for the key:
250 + for (aKey : theVal in x)
253 Elements can be removed from an array using the delete command:
255 delete x[3] # deletes element with key 3
256 delete x[] # deletes all elements