aryRepArg redux, operand check, key grammar
[nedit-bw.git] / callMacroFnByName2.diff
blobae61a76c36411bb331597e1421dda1b34e85f9bb
1 From: Tony Balinski <ajbj@free.fr>
2 Subject: Provide a call() macro function which calls another function given its name
4 The function invokes new code in interpret.c which calls the desired, named
5 function with any remaining arguments to call(). In this way, the function
6 is called using the same interpretation environment as call()'s invoker.
8 ---
10 source/interpret.c | 90 ++++++++++++++++++++++++++++++++++++++++++++---------
11 source/interpret.h | 4 ++
12 source/macro.c | 28 ++++++++++++++++
13 3 files changed, 108 insertions(+), 14 deletions(-)
15 diff --quilt old/source/interpret.c new/source/interpret.c
16 --- old/source/interpret.c
17 +++ new/source/interpret.c
18 @@ -89,6 +89,7 @@ static int returnValOrNone(int valOnStac
19 static int branchIf(Boolean trueOrFalse);
20 static int namedArg1orN(Boolean isFirst);
22 +static int callSubroutineFromSymbol(Symbol *sym, int nArgs);
23 static int concatenateNwithSep(int nVals, const char *sep, char **result,
24 int leaveParams);
25 static int makeArrayKeyFromArgs(int nArgs, char **keyString, int leaveParams);
26 @@ -2440,7 +2441,9 @@ static int concat(void)
27 ** arguments and space for local variables are added to the stack, and the
28 ** PC is set to point to the new function. For a built-in routine, the
29 ** arguments are popped off the stack, and the routine is just called.
30 -**
31 +*/
32 +/*
33 +** For callSubroutine:
34 ** Before: Prog-> [subrSym], nArgs, next, ...
35 ** TheStack-> argArray?, argN-arg1, next, ...
36 ** After: Prog-> next, ... -- (built-in called subr)
37 @@ -2448,30 +2451,21 @@ static int concat(void)
38 ** or: Prog-> (in called)next, ... -- (macro code called subr)
39 ** TheStack-> symN-sym1(FP), nArgs, oldFP, retPC, argArray, argN-arg1, next, ...
41 -static int callSubroutine(void)
42 +static int callSubroutineFromSymbol(Symbol *sym, int nArgs)
44 - Symbol *sym, *s;
45 - int i, nArgs;
46 + Symbol *s;
47 + int i;
48 static DataValue noValue = {NO_TAG, {0}};
49 DataValue argArray = noValue;
50 Program *prog;
51 char *errMsg;
52 - int haveNamedArgs;
54 - sym = PC->sym;
55 - PC++;
56 - nArgs = PC->value;
57 - PC++;
58 + int haveNamedArgs = (nArgs < 0);
60 - haveNamedArgs = (nArgs < 0);
61 if (haveNamedArgs) {
62 nArgs = -nArgs - 1;
63 POP(argArray);
66 - DISASM_RT(PC-3, 3);
67 - STACKDUMP(nArgs + haveNamedArgs, 3);
70 ** If the subroutine is built-in, call the built-in routine
72 @@ -2568,6 +2562,74 @@ static int callSubroutine(void)
76 +** Before: Prog-> [subrSym], nArgs, next, ...
77 +** Stack-> argN-arg1, next, ...
78 +**
79 +** After: Prog-> next, ... -- (built-in called subr)
80 +** Stack-> retVal?, next, ...
81 +** or: Prog-> (in called)next, ... -- (macro code called subr)
82 +** Stack-> symN-sym1(FP), argArray, nArgs, oldFP, retPC, argN-arg1, next, ...
83 +*/
84 +static int callSubroutine(void)
86 + Symbol *sym;
87 + int nArgs;
88 + int n;
90 + sym = PC++->sym;
91 + nArgs = PC++->value;
93 + DISASM_RT(PC-3, 3);
94 + STACKDUMP(nArgs, 3);
96 + return callSubroutineFromSymbol(sym, nArgs);
99 +/*
100 +** Assumes a valid symbol. Invokes callSubroutineFromSymbol(), correcting nArgs
101 +** to match that routine's expectations. This allows a callMS() function to be
102 +** written in macro.c. If the caller has already "consumed" stack elements,
103 +** removeArgs must indicate how many.
106 +int OverlayRoutineFromSymbol(Symbol *sym, int nArgs, int removeArgs)
108 + DataValue *stackTop = StackP + nArgs - removeArgs;
110 + if (removeArgs > 0) {
111 + DataValue *from = StackP + removeArgs;
112 + DataValue *to = StackP;
113 + int n = nArgs - removeArgs;
115 + nArgs = n;
116 + while (n--) {
117 + *to++ = *from++;
121 + StackP = stackTop;
122 + return callSubroutineFromSymbol(sym, nArgs);
126 +** Assumes a valid prog. Wraps the program in a dummy symbol then calls
127 +** OverlayRoutineFromSymbol(). In this way a piece of compiled code can be
128 +** executed in the caller's context from a function in macro.c.
131 +int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs)
133 + Symbol sym;
135 + sym.type = MACRO_FUNCTION_SYM;
136 + sym.name = prog->name;
137 + sym.value.val.prog = prog;
138 + sym.next = NULL;
140 + return OverlayRoutineFromSymbol(&sym, nArgs, removeArgs);
144 ** This should never be executed, returnVal checks for the presence of this
145 ** instruction at the PC to decide whether to push the function's return
146 ** value, then skips over it without executing.
147 diff --quilt old/source/interpret.h new/source/interpret.h
148 --- old/source/interpret.h
149 +++ new/source/interpret.h
150 @@ -171,6 +171,10 @@ int ExecuteMacro(WindowInfo *window, Pro
151 int ContinueMacro(RestartData *continuation, DataValue *result, char **msg);
152 void RunMacroAsSubrCall(Program *prog);
153 void PreemptMacro(void);
155 +int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs);
156 +int OverlayRoutineFromSymbol(Symbol *sym, int nArgs, int removeArgs);
158 char *AllocString(int length);
159 char *AllocStringNCpy(const char *s, int length);
160 char *AllocStringCpy(const char *s);
161 diff --quilt old/source/macro.c new/source/macro.c
162 --- old/source/macro.c
163 +++ new/source/macro.c
164 @@ -416,6 +416,8 @@ static int getStyleAtPosMS(WindowInfo *w
165 DataValue *result, char **errMsg);
166 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
167 DataValue* result, char** errMsg);
168 +static int callMS(WindowInfo *window, DataValue *argList,
169 + int nArgs, DataValue *result, char **errMsg);
171 /* Built-in subroutines and variables for the macro language */
172 static const BuiltInSubrName MacroSubrs[] = {
173 @@ -475,6 +477,7 @@ static const BuiltInSubrName MacroSubrs[
174 { "get_style_by_name", getStyleByNameMS },
175 { "get_style_at_pos", getStyleAtPosMS },
176 { "filename_dialog", filenameDialogMS },
177 + { "call", callMS },
178 { NULL, NULL } /* sentinel */
181 @@ -3493,6 +3496,31 @@ static int filenameDialogMS(WindowInfo*
182 return True;
186 + * call(fnname, arg, ...)
187 + */
188 +static int callMS(WindowInfo *window, DataValue *argList,
189 + int nArgs, DataValue *result, char **errMsg)
191 + char stringStorage[TYPE_INT_STR_SIZE(int)];
192 + Symbol *sym;
193 + char *fnname;
195 + if (nArgs < 1) {
196 + *errMsg = "subroutine %s called without arguments";
197 + return False;
199 + if (!readStringArg(argList[0], &fnname, stringStorage, errMsg)) {
200 + return False;
202 + sym = LookupSymbol(fnname);
203 + if (!sym) {
204 + *errMsg = "subroutine name invalid";
205 + return False;
207 + return OverlayRoutineFromSymbol(sym, nArgs, 1);
210 /* T Balinski */
211 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
212 DataValue *result, char **errMsg)