final step to context based macro interpreter
[nedit-bw.git] / arrayReplacesArglist-as-last-argument.patch
blob568d79b7d4c23b5b15da151343d5cab360f7ba8d
1 Subject: extend fn(=array) syntax to fn(..., =array)
3 All non-negative one-dimensional numerical keys are appended to the
4 previously arguments, in order. All other entries are merge into the named
5 argument array.
7 ---
9 source/interpret.c | 75 ++++++++++++++++++++++++++++++++++++++++-------------
10 source/parse.y | 28 +++++++++++++++++++
11 2 files changed, 85 insertions(+), 18 deletions(-)
13 diff --quilt old/source/interpret.c new/source/interpret.c
14 --- old/source/interpret.c
15 +++ new/source/interpret.c
16 @@ -2782,34 +2782,63 @@ int OverlayRoutineFromProg(Program *prog
18 static int unpackArrayToArgs(void)
20 - int nArgs, res;
22 - DataValue dvEntry, dvArray;
23 + int nArgs, i, res, haveNamedArgs;
24 + SparseArrayEntry *iter;
25 + DataValue dvEntry, dvArray, argArray;
27 DISASM_RT(PC-1, 1);
28 STACKDUMP(1, 3);
30 - POP(dvEntry);
31 + nArgs = PC++->value;
32 + haveNamedArgs = (nArgs < 0);
34 + POP(argArray);
36 - if (dvEntry.tag != ARRAY_TAG) {
37 + if (argArray.tag != ARRAY_TAG) {
38 return execError("argument array call made with non-array value", NULL);
40 - res = ArrayCopy(&dvArray, &dvEntry);
41 - if (res != STAT_OK) {
42 - return execError("cannot copy array in array call", NULL);
44 + if (haveNamedArgs) {
45 + nArgs = -nArgs - 1;
46 + POP(dvArray);
47 + }
48 + else {
49 + dvArray.tag = ARRAY_TAG;
50 + dvArray.val.arrayPtr = ArrayNew();
53 - /* push positional argument entries in the array on the stack */
54 - for (nArgs = 1; ; ++nArgs) {
55 - char *ind = (char *)longAsStr(nArgs);
56 - if (!ArrayGet(&dvArray, ind, &dvEntry))
57 - break;
58 - /* remove them from remaining array */
59 - ArrayDelete(&dvArray, ind);
60 - PUSH(dvEntry);
61 + iter = arrayIterateFirst(&argArray);
62 + while (iter) {
63 + int thisKey;
65 + if (iter->value.tag == ARRAY_TAG) {
66 + int errNum;
67 + DataValue tmpArray;
69 + errNum = ArrayCopy(&dvEntry, &iter->value);
70 + if (errNum != STAT_OK) {
71 + return(errNum);
72 + }
73 + }
74 + else {
75 + dvEntry = iter->value;
76 + }
78 + if (StringToNum(iter->key, &thisKey) && thisKey >= 0) {
79 + PUSH(dvEntry);
80 + nArgs++;
81 + }
82 + else {
83 + if (!ArrayInsert(&dvArray, iter->key, &dvEntry)) {
84 + return(execError("array copy failed", NULL));
85 + }
86 + }
88 + iter = arrayIterateNext(iter);
91 PUSH(dvArray);
92 - PUSH_INT(-nArgs);
93 + PUSH_INT(-(nArgs + 1));
94 return STAT_OK;
97 @@ -4331,8 +4360,18 @@ static void disasmInternal(Inst *inst, i
99 i += 2;
101 + else if (j == OP_UNPACKTOARGS) {
102 + int args = inst[i+2].value;
103 + if (args < 0) {
104 + printd(" %d+args[] (%d)", -args - 1, args);
106 + else {
107 + printd(" %d args", args);
109 + ++i;
111 else if (j == OP_SUBR_CALL_STACKED_N) {
112 - printd(" %s args[] (?)", inst[i+1].sym->name);
113 + printd(" %s =args[] (?)", inst[i+1].sym->name);
114 ++i;
116 else if (j == OP_BEGIN_ARRAY_ITER ||
117 diff --quilt old/source/parse.y new/source/parse.y
118 --- old/source/parse.y
119 +++ new/source/parse.y
120 @@ -69,6 +69,7 @@ static int follow(char expect, int yes,
121 static int follow2(char expect1, int yes1, char expect2, int yes2, int no);
122 static int follow_non_whitespace(char expect, int yes, int no);
123 static int eq_look_ahead(void);
124 +static int comma_look_ahead(void);
125 static Symbol *matchesActionRoutine(char **inPtr);
126 static int scanString(void);
128 @@ -114,6 +115,7 @@ typedef struct LVinst {
129 %token <oper> '=' ADDEQ SUBEQ MULEQ DIVEQ MODEQ ANDEQ OREQ
130 %token <oper> INCR DECR
131 %type <lvinst> lvlist lventry
132 +%token ARGSEP
134 %nonassoc IF_NO_ELSE
135 %nonassoc ELSE
136 @@ -550,6 +552,14 @@ funccall: TYPEOF '(' {
137 | SYMBOL '(' blank '=' blank expr blank ')' {
138 /* a single array replaces the argument list */
139 ADD_OP(OP_UNPACKTOARGS);
140 + ADD_IMMED(0); /* zero arguments */
141 + ADD_OP(OP_SUBR_CALL_STACKED_N);
142 + ADD_SYM(PromoteToGlobal($1));
144 + | SYMBOL '(' fnarglist ARGSEP blank '=' blank expr blank ')' {
145 + /* a single array replaces the argument list */
146 + ADD_OP(OP_UNPACKTOARGS);
147 + ADD_IMMED($3);
148 ADD_OP(OP_SUBR_CALL_STACKED_N);
149 ADD_SYM(PromoteToGlobal($1));
151 @@ -978,6 +988,7 @@ static int yylex(void)
152 ++InPtr;
153 return result; /* but return what we started with */
155 + case ',': return comma_look_ahead();
156 default: return *(InPtr-1);
159 @@ -1062,6 +1073,23 @@ static int eq_look_ahead(void)
160 return '=';
163 +static int comma_look_ahead(void)
165 + char *savedInPtr = InPtr;
167 + /* skip any whitespace */
168 + skipWhitespace();
170 + /* '=' from array argument */
171 + if (*InPtr == '=') {
172 + InPtr = savedInPtr;
173 + return ARGSEP;
176 + InPtr = savedInPtr;
177 + return ',';
181 ** Look (way) ahead for hyphenated routine names which begin at inPtr. A
182 ** hyphenated name is allowed if it is pre-defined in the global symbol