disable OM2.3.1 by default, enable with make bertw OM231=1
[nedit-bw.git] / array-next-num-index.patch
blobe824005f15c592d091d1ac4c709515ec24f40745
1 Subject: Helper syntax for arrays with numerical indexes
3 Working with arrays which have only numerical indexes is a little
4 cumbersome. Especially to append/push an element to the end of the array.
6 arr[@]
8 gives an index which is one greater than all used numerical indexes in the
9 array arr. If none numerical index is used, 0 is returned.
11 arr[@] = expr
13 assigns expr to the array at position arr[@].
15 ---
17 source/interpret.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++
18 source/ops.h | 2 +
19 source/parse.y | 6 +++
20 3 files changed, 99 insertions(+)
22 diff --quilt old/source/interpret.c new/source/interpret.c
23 --- old/source/interpret.c
24 +++ new/source/interpret.c
25 @@ -3253,10 +3253,31 @@ SparseArrayEntry *arrayIterateNext(Spars
26 nextPos = NULL;
28 return(nextPos);
31 +static int arrayMaxNumIdx(DataValue *theArray)
33 + int maxKey = -1;
34 + SparseArrayEntry *iter;
36 + iter = arrayIterateFirst(theArray);
37 + while (iter) {
38 + int thisKey;
40 + if (StringToNum(iter->key, &thisKey)) {
41 + /* the rbTree is sorted, but "10" < "2" */
42 + if (thisKey > maxKey)
43 + maxKey = thisKey;
44 + }
46 + iter = arrayIterateNext(iter);
47 + }
49 + return maxKey;
53 ** evaluate an array element and push the result onto the stack
55 ** Before: Prog-> [nDim], next, ...
56 ** TheStack-> indnDim, ... ind1, ArraySym, next, ...
57 @@ -4081,10 +4102,80 @@ static int typeOfOut(void)
59 return STAT_OK;
63 +** assign to the next numerical index array element of a referenced
64 +** array on the stack
65 +**
66 +** Before: Prog-> next, ...
67 +** TheStack-> rhs, ArraySym, next, ...
68 +** After: Prog-> next, ... (unchanged)
69 +** TheStack-> next, ...
70 +*/
71 +static int arrayAssignNext(void)
73 + char *keyString = NULL;
74 + DataValue srcValue, dstArray;
75 + int errNum;
77 + DISASM_RT(PC-1, 1);
78 + STACKDUMP(0, 3);
80 + POP(srcValue);
81 + POP(dstArray);
83 + if (dstArray.tag != ARRAY_TAG && dstArray.tag != NO_TAG) {
84 + return execError("cannot assign array element of non-array", NULL);
85 + }
87 + if (srcValue.tag == ARRAY_TAG) {
88 + DataValue arrayCopyValue;
90 + errNum = ArrayCopy(&arrayCopyValue, &srcValue);
91 + srcValue = arrayCopyValue;
92 + if (errNum != STAT_OK) {
93 + return errNum;
94 + }
95 + }
97 + keyString = AllocStringOfNumber(arrayMaxNumIdx(&dstArray) + 1);
99 + if (!ArrayInsert(&dstArray, keyString, &srcValue)) {
100 + return execError("array member allocation failure", NULL);
103 + return STAT_OK;
107 +** return the free numeric index that is greater than all others
109 +** Before: Prog-> next, ...
110 +** TheStack-> ArraySym, next, ...
111 +** After: Prog-> next, ... (unchanged)
112 +** TheStack-> numIdx, next, ...
114 +static int arrayNextNumIdx(void)
116 + DataValue srcArray;
117 + SparseArrayEntry *iter;
119 + DISASM_RT(PC-1, 1);
120 + STACKDUMP(0, 3);
122 + POP(srcArray);
123 + if (srcArray.tag != ARRAY_TAG) {
124 + return execError("operator [@] on non-array", NULL);
127 + PUSH_INT(arrayMaxNumIdx(&srcArray) + 1);
129 + return STAT_OK;
133 ** checks errno after operations which can set it. If an error occured,
134 ** creates appropriate error messages and returns false
136 static int errCheck(const char *s)
138 diff --quilt old/source/parse.y new/source/parse.y
139 --- old/source/parse.y
140 +++ new/source/parse.y
141 @@ -444,10 +444,13 @@ simpstmt: /* simple variable assignmen
142 | incrdecr blank initarraylv dot field {
143 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
144 ADD_OP($1);
145 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
147 + | initarraylv '[' '@' ']' '=' blank expr {
148 + ADD_OP(OP_ARRAY_ASSIGN_NEXT);
150 | funccall
153 evalsym: SYMBOL {
154 $$ = $1; ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
155 @@ -662,10 +665,13 @@ numexpr: '(' blank expr blank ')'
156 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
158 | numexpr dot field {
159 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
161 + | numexpr '[' '@' ']' {
162 + ADD_OP(OP_ARRAY_NEXT_NUM_IDX);
164 | '-' blank numexpr %prec UNARY_MINUS { ADD_OP(OP_NEGATE); }
165 | NOT blank numexpr { ADD_OP(OP_NOT); }
166 | numexpr '+' blank numexpr { ADD_OP(OP_ADD); }
167 | numexpr '-' blank numexpr { ADD_OP(OP_SUB); }
168 | numexpr '*' blank numexpr { ADD_OP(OP_MUL); }
169 diff --quilt old/source/ops.h new/source/ops.h
170 --- old/source/ops.h
171 +++ new/source/ops.h
172 @@ -37,20 +37,22 @@ OP(BRANCH, branch)
173 OP(BRANCH_TRUE, branchTrue) /* off */ /* pop(v), if v: PC += off */
174 OP(BRANCH_FALSE, branchFalse) /* off */ /* pop(v), if !v: PC += off */
175 OP(BRANCH_NEVER, branchNever) /* off */ /* */
176 OP(ARRAY_REF, arrayRef) /* N */ /* pop(kN..k1,a), push(a[k1..kN]) */
177 OP(ARRAY_ASSIGN, arrayAssign) /* N */ /* pop(v,kN..k1,a), a[k1..kN]=v */
178 +OP(ARRAY_ASSIGN_NEXT, arrayAssignNext) /* pop(v, a), a[a.nextidx] = v */
179 OP(BEGIN_ARRAY_ITER, beginArrayIter) /* it */ /* pop(a), it=a.begin */
180 OP(ARRAY_ITER, arrayIter) /*w,k[,v],it,pc*/ /* it?(k.v=it.k,(w?v.v=it.v:),it++):PC=pc */
181 OP(ARRAY_MULTI_ITER, arrayMultiIter) /*w,N,k1..kN[,v],it,pc*/ /* while it: (if dim(it.k)==N: ([k1..kN].v=it.k,(w?v.v=it.v:),break), it++), if notfound: PC=pc */
182 OP(BEGIN_ARRAY_MULTI_ITER_ARRAY, beginArrayMultiIterArray) /*it*/ /* */
183 OP(ARRAY_MULTI_ITER_ARRAY, arrayMultiIterArray) /*w,k[v],pc*/ /* top(N) */
184 OP(IN_ARRAY, inArray) /* pop(a,k), push(a[k]?1:0) */
185 OP(ARRAY_INDEX, arrayIndex) /* N */ /* pop(kN..k1), push([kN..k1]) */
186 OP(ARRAY_DELETE, deleteArrayElement) /*N*/ /* N>0 ? (pop(kN..k1,a), del(a[k])) : (pop(a), delall(a)) */
187 OP(PUSH_ARRAY_SYM, pushArraySymVal) /*s,i*/ /* if i: s.v=ary()), push(s.v) */
188 OP(ARRAY_REF_ASSIGN_SETUP, arrayRefAndAssignSetup) /*op,N*/ /* pop(v,kN..a), a[k1..kN] op= v */
189 +OP(ARRAY_NEXT_NUM_IDX, arrayNextNumIdx) /* pop(a), push(a.nextidx) */
190 OP(PUSH_ARG, pushArgVal) /* pop(num), push($num) */
191 OP(PUSH_ARG_COUNT, pushArgCount) /* push($n_args) */
192 OP(PUSH_ARG_ARRAY, pushArgArray) /* push($args) */
193 OP(ANONARRAY_OPEN, anonArrayOpen) /* push(0), push(ary()) */
194 OP(ANONARRAY_SKIP, anonArraySkip) /* pop(a,n), push(n+1,a) */