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.
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.
13 assigns expr to the array at position arr[@].
17 source/interpret.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++
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 @@ -3226,6 +3226,27 @@ SparseArrayEntry *arrayIterateNext(Spars
29 +static int arrayMaxNumIdx(DataValue *theArray)
32 + SparseArrayEntry *iter;
34 + iter = arrayIterateFirst(theArray);
38 + if (StringToNum(iter->key, &thisKey)) {
39 + /* the rbTree is sorted, but "10" < "2" */
40 + if (thisKey > maxKey)
44 + iter = arrayIterateNext(iter);
51 ** evaluate an array element and push the result onto the stack
53 @@ -3879,6 +3900,76 @@ static int typeOfOut(void)
57 +** assign to the next numerical index array element of a referenced
58 +** array on the stack
60 +** Before: Prog-> next, ...
61 +** TheStack-> rhs, ArraySym, next, ...
62 +** After: Prog-> next, ... (unchanged)
63 +** TheStack-> next, ...
65 +static int arrayAssignNext(void)
67 + char *keyString = NULL;
68 + DataValue srcValue, dstArray;
77 + if (dstArray.tag != ARRAY_TAG && dstArray.tag != NO_TAG) {
78 + return execError("cannot assign array element of non-array", NULL);
81 + if (srcValue.tag == ARRAY_TAG) {
82 + DataValue arrayCopyValue;
84 + errNum = ArrayCopy(&arrayCopyValue, &srcValue);
85 + srcValue = arrayCopyValue;
86 + if (errNum != STAT_OK) {
91 + keyString = AllocStringOfNumber(arrayMaxNumIdx(&dstArray) + 1);
93 + if (!ArrayInsert(&dstArray, keyString, &srcValue)) {
94 + return execError("array member allocation failure", NULL);
101 +** return the free numeric index that is greater than all others
103 +** Before: Prog-> next, ...
104 +** TheStack-> ArraySym, next, ...
105 +** After: Prog-> next, ... (unchanged)
106 +** TheStack-> numIdx, next, ...
108 +static int arrayNextNumIdx(void)
110 + DataValue srcArray;
111 + SparseArrayEntry *iter;
113 + DISASM_RT(PC-1, 1);
117 + if (srcArray.tag != ARRAY_TAG) {
118 + return execError("operator [@] on non-array", NULL);
121 + PUSH_INT(arrayMaxNumIdx(&srcArray) + 1);
127 ** checks errno after operations which can set it. If an error occured,
128 ** creates appropriate error messages and returns false
130 diff --quilt old/source/parse.y new/source/parse.y
131 --- old/source/parse.y
132 +++ new/source/parse.y
133 @@ -397,6 +397,9 @@ simpstmt: /* simple variable assignmen
135 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
137 + | initarraylv '[' '@' ']' '=' blank expr {
138 + ADD_OP(OP_ARRAY_ASSIGN_NEXT);
143 @@ -711,6 +714,9 @@ numexpr: '(' blank expr blank ')'
144 | numexpr dot field {
145 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
147 + | numexpr '[' '@' ']' {
148 + ADD_OP(OP_ARRAY_NEXT_NUM_IDX);
150 | '-' blank numexpr %prec UNARY_MINUS { ADD_OP(OP_NEGATE); }
151 | NOT blank numexpr { ADD_OP(OP_NOT); }
152 | numexpr '+' blank numexpr { ADD_OP(OP_ADD); }
153 diff --quilt old/source/ops.h new/source/ops.h
156 @@ -39,6 +39,7 @@ OP(BRANCH_FALSE, branchFalse)
157 OP(BRANCH_NEVER, branchNever) /* off */ /* */
158 OP(ARRAY_REF, arrayRef) /* N */ /* pop(kN..k1,a), push(a[k1..kN]) */
159 OP(ARRAY_ASSIGN, arrayAssign) /* N */ /* pop(v,kN..k1,a), a[k1..kN]=v */
160 +OP(ARRAY_ASSIGN_NEXT, arrayAssignNext) /* pop(v, a), a[a.nextidx] = v */
161 OP(BEGIN_ARRAY_ITER, beginArrayIter) /* it */ /* pop(a), it=a.begin */
162 OP(ARRAY_ITER, arrayIter) /*w,k[,v],it,pc*/ /* it?(k.v=it.k,(w?v.v=it.v:),it++):PC=pc */
163 OP(BEGIN_ARRAY_ITER_ARRAY, beginArrayIterArray) /*it*/ /* */
164 @@ -47,6 +48,7 @@ OP(IN_ARRAY, inArray)
165 OP(ARRAY_DELETE, deleteArrayElement) /*N*/ /* N>0 ? (pop(kN..k1,a), del(a[k])) : (pop(a), delall(a)) */
166 OP(PUSH_ARRAY_SYM, pushArraySymVal) /*s,i*/ /* if i: s.v=ary()), push(s.v) */
167 OP(ARRAY_REF_ASSIGN_SETUP, arrayRefAndAssignSetup) /*op,N*/ /* pop(v,kN..a), a[k1..kN] op= v */
168 +OP(ARRAY_NEXT_NUM_IDX, arrayNextNumIdx) /* pop(a), push(a.nextidx) */
169 OP(PUSH_ARG, pushArgVal) /* pop(num), push($num) */
170 OP(PUSH_ARG_COUNT, pushArgCount) /* push($n_args) */
171 OP(PUSH_ARG_ARRAY, pushArgArray) /* push($args) */