On Thu, Apr 10, 2008 at 2:53 PM, Bert Wesarg <[EMAIL PROTECTED]> wrote:
>  Maybe a drastically syntax extension is needed:
>
>  rvalue: [EMAIL PROTECTED]        := return max numeric index + 1
>  lvalue: [EMAIL PROTECTED] = expr := push expr at position max numeric index 
> + 1
For the curious guys out there, here is a patch to play with:

Btw, I really would like to use a '#' instead of the '@', but we all
know this doesn't work.

>
>  Bert
>
---

 source/interpret.c |   98 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 source/interpret.h |    5 +-
 source/parse.y     |    6 +++
 3 files changed, 106 insertions(+), 3 deletions(-)

diff --quilt old/source/interpret.c new/source/interpret.c
--- old/source/interpret.c
+++ new/source/interpret.c
@@ -135,6 +135,8 @@ static int arrayEntryCopyToNode(rbTreeNo
 static int arrayEntryCompare(rbTreeNode *left, rbTreeNode *right);
 static void arrayDisposeNode(rbTreeNode *src);
 static SparseArrayEntry *allocateSparseArrayEntry(void);
+static int arrayAssignNext(void);
+static int arrayNextNumIdx(void);
 
 /*#define DEBUG_ASSEMBLY*/
 /*#define DEBUG_STACK*/
@@ -208,7 +210,8 @@ static int (*OpFns[N_OPS])() = {returnNo
     assign, callSubroutine, fetchRetVal, branch, branchTrue, branchFalse,
     branchNever, arrayRef, arrayAssign, beginArrayIter, arrayIter, inArray,
     deleteArrayElement, pushArraySymVal,
-    arrayRefAndAssignSetup, pushArgVal, pushArgCount, pushArgArray};
+    arrayRefAndAssignSetup, pushArgVal, pushArgCount, pushArgArray,
+    arrayAssignNext, arrayNextNumIdx};
 
 /* Stack-> symN-sym0(FP), argArray, nArgs, oldFP, retPC, argN-arg1, next, ... 
*/
 #define FP_ARG_ARRAY_CACHE_INDEX (-1)
@@ -2446,6 +2449,27 @@ SparseArrayEntry *arrayIterateNext(Spars
     return(nextPos);
 }
 
+static int arrayMaxNumIdx(DataValue *theArray)
+{
+    int maxKey = -1;
+    SparseArrayEntry *iter;
+
+    iter = arrayIterateFirst(theArray);
+    while (iter) {
+        int thisKey;
+
+        if (StringToNum(iter->key, &thisKey)) {
+            /* even if the rbTree is sorted, check it to be sure */
+            if (thisKey > maxKey)
+                maxKey = thisKey;
+        }
+
+        iter = arrayIterateNext(iter);
+    }
+
+    return maxKey;
+}
+
 /*
 ** evaluate an array element and push the result onto the stack
 **
@@ -2811,6 +2835,78 @@ static int deleteArrayElement(void)
 }
 
 /*
+** assign to the next numerical index array element of a referenced
+** array on the stack
+**
+** Before: Prog->  next, ...
+**         TheStack-> rhs, ArraySym, next, ...
+** After:  Prog->  next, ... (unchanged)
+**         TheStack-> next, ...
+*/
+static int arrayAssignNext(void)
+{
+    char *keyString = NULL;
+    DataValue srcValue, dstArray;
+    int errNum;
+
+    DISASM_RT(PC-1, 1);
+    STACKDUMP(0, 3);
+
+    POP(srcValue)
+
+    POP(dstArray)
+    if (dstArray.tag != ARRAY_TAG && dstArray.tag != NO_TAG) {
+        return(execError("cannot assign array element of non-array", NULL));
+    }
+
+    if (srcValue.tag == ARRAY_TAG) {
+        DataValue arrayCopyValue;
+
+        errNum = ArrayCopy(&arrayCopyValue, &srcValue);
+        srcValue = arrayCopyValue;
+        if (errNum != STAT_OK) {
+            return(errNum);
+        }
+    }
+
+    keyString = AllocString(TYPE_INT_STR_SIZE(int));
+    sprintf(keyString, "%d", arrayMaxNumIdx(&dstArray) + 1);
+
+    if (ArrayInsert(&dstArray, keyString, &srcValue)) {
+        return(STAT_OK);
+    }
+    else {
+        return(execError("array member allocation failure", NULL));
+    }
+}
+
+/*
+** return the free numeric index that is greater than all others
+**
+** Before: Prog->  next, ...
+**         TheStack-> ArraySym, next, ...
+** After:  Prog->  next, ... (unchanged)
+**         TheStack-> numIdx, next, ...
+*/
+static int arrayNextNumIdx(void)
+{
+    DataValue srcArray;
+    SparseArrayEntry *iter;
+
+    DISASM_RT(PC-1, 1);
+    STACKDUMP(0, 3);
+
+    POP(srcArray)
+    if (srcArray.tag != ARRAY_TAG) {
+        return execError("operator [EMAIL PROTECTED] on non-array", NULL);
+    }
+
+    PUSH_INT(arrayMaxNumIdx(&srcArray) + 1)
+
+    return STAT_OK;
+}
+
+/*
 ** checks errno after operations which can set it.  If an error occured,
 ** creates appropriate error messages and returns false
 */
diff --quilt old/source/interpret.h new/source/interpret.h
--- old/source/interpret.h
+++ new/source/interpret.h
@@ -40,7 +40,7 @@
 
 enum symTypes {CONST_SYM, GLOBAL_SYM, LOCAL_SYM, ARG_SYM, PROC_VALUE_SYM,
        C_FUNCTION_SYM, MACRO_FUNCTION_SYM, ACTION_ROUTINE_SYM};
-#define N_OPS 43
+#define N_OPS 45
 enum operations {OP_RETURN_NO_VAL, OP_RETURN, OP_PUSH_SYM, OP_DUP, OP_ADD,
     OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_NEGATE, OP_INCR, OP_DECR, OP_GT, OP_LT,
     OP_GE, OP_LE, OP_EQ, OP_NE, OP_BIT_AND, OP_BIT_OR, OP_AND, OP_OR, OP_NOT,
@@ -48,7 +48,8 @@ enum operations {OP_RETURN_NO_VAL, OP_RE
     OP_BRANCH_TRUE, OP_BRANCH_FALSE, OP_BRANCH_NEVER, OP_ARRAY_REF,
     OP_ARRAY_ASSIGN, OP_BEGIN_ARRAY_ITER, OP_ARRAY_ITER, OP_IN_ARRAY,
     OP_ARRAY_DELETE, OP_PUSH_ARRAY_SYM, OP_ARRAY_REF_ASSIGN_SETUP, OP_PUSH_ARG,
-    OP_PUSH_ARG_COUNT, OP_PUSH_ARG_ARRAY};
+    OP_PUSH_ARG_COUNT, OP_PUSH_ARG_ARRAY,
+    OP_ARRAY_ASSIGN_NEXT, OP_ARRAY_NEXT_NUM_IDX};
 
 enum typeTags {NO_TAG, INT_TAG, STRING_TAG, ARRAY_TAG};
 
diff --quilt old/source/parse.y new/source/parse.y
--- old/source/parse.y
+++ new/source/parse.y
@@ -183,6 +183,9 @@ simpstmt:   SYMBOL '=' expr {
             | initarraylv '[' arglist ']' '=' expr {
                 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
             }
+            | initarraylv '[' '@' ']' '=' expr {
+                ADD_OP(OP_ARRAY_ASSIGN_NEXT);
+            }
             | initarraylv '[' arglist ']' ADDEQ expr {
                 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
                 ADD_OP(OP_ADD);
@@ -333,6 +336,9 @@ numexpr:    NUMBER {
             | numexpr '[' arglist ']' {
                 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
             }
+            | numexpr '[' '@' ']' {
+                ADD_OP(OP_ARRAY_NEXT_NUM_IDX);
+            }
             | numexpr '+' numexpr {
                 ADD_OP(OP_ADD);
             }
-- 
NEdit Develop mailing list - [email protected]
http://www.nedit.org/mailman/listinfo/develop

Reply via email to