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.
10 source/built-ins.h | 1
11 source/interpret.c | 91 ++++++++++++++++++++++++++++++++++++++++++++---------
12 source/interpret.h | 4 ++
13 source/macro.c | 25 ++++++++++++++
14 4 files changed, 107 insertions(+), 14 deletions(-)
16 diff --quilt old/source/interpret.c new/source/interpret.c
17 --- old/source/interpret.c
18 +++ new/source/interpret.c
19 @@ -89,6 +89,7 @@ static int returnValOrNone(int valOnStac
20 static int branchIf(Boolean trueOrFalse);
21 static int namedArg1orN(Boolean isFirst);
23 +static int callSubroutineFromSymbol(Symbol *sym, int nArgs);
24 static int concatenateNwithSep(int nVals, const char *sep, char **result,
26 static int makeArrayKeyFromArgs(int nArgs, char **keyString, int leaveParams);
27 @@ -2440,7 +2441,9 @@ static int concat(void)
28 ** arguments and space for local variables are added to the stack, and the
29 ** PC is set to point to the new function. For a built-in routine, the
30 ** arguments are popped off the stack, and the routine is just called.
34 +** For callSubroutine:
35 ** Before: Prog-> [subrSym], nArgs, next, ...
36 ** TheStack-> argArray?, argN-arg1, next, ...
37 ** After: Prog-> next, ... -- (built-in called subr)
38 @@ -2448,30 +2451,21 @@ static int concat(void)
39 ** or: Prog-> (in called)next, ... -- (macro code called subr)
40 ** TheStack-> symN-sym1(FP), nArgs, oldFP, retPC, argArray, argN-arg1, next, ...
42 -static int callSubroutine(void)
43 +static int callSubroutineFromSymbol(Symbol *sym, int nArgs)
49 static DataValue noValue = {NO_TAG, {0}};
50 DataValue argArray = noValue;
59 + int haveNamedArgs = (nArgs < 0);
61 - haveNamedArgs = (nArgs < 0);
68 - STACKDUMP(nArgs + haveNamedArgs, 3);
71 ** If the subroutine is built-in, call the built-in routine
73 @@ -2568,6 +2562,75 @@ static int callSubroutine(void)
77 +** Before: Prog-> [subrSym], nArgs, next, ...
78 +** Stack-> argN-arg1, next, ...
80 +** After: Prog-> next, ... -- (built-in called subr)
81 +** Stack-> retVal?, next, ...
82 +** or: Prog-> (in called)next, ... -- (macro code called subr)
83 +** Stack-> symN-sym1(FP), argArray, nArgs, oldFP, retPC, argN-arg1, next, ...
85 +static int callSubroutine(void)
92 + nArgs = PC++->value;
95 + STACKDUMP(nArgs, 3);
97 + return callSubroutineFromSymbol(sym, nArgs);
101 +** Assumes a valid symbol. Invokes callSubroutineFromSymbol(), correcting nArgs
102 +** to match that routine's expectations. This allows a callMS() function to be
103 +** written in macro.c. If the caller has already "consumed" stack elements,
104 +** removeArgs must indicate how many.
107 +int OverlayRoutineFromSymbol(Symbol *sym, int nArgs, int removeArgs)
109 + DataValue *stackTop = StackP + nArgs - removeArgs;
111 + if (removeArgs > 0) {
112 + DataValue *from = StackP + removeArgs;
113 + DataValue *to = StackP;
114 + int n = nArgs - removeArgs;
123 + return callSubroutineFromSymbol(sym, nArgs);
127 +** Assumes a valid prog. Wraps the program in a dummy symbol then calls
128 +** OverlayRoutineFromSymbol(). In this way a piece of compiled code can be
129 +** executed in the caller's context from a function in macro.c.
132 +int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs)
136 + sym.type = MACRO_FUNCTION_SYM;
137 + sym.name = prog->name;
138 + sym.value.tag = NO_TAG;
139 + sym.value.val.prog = prog;
142 + return OverlayRoutineFromSymbol(&sym, nArgs, removeArgs);
146 ** This should never be executed, returnVal checks for the presence of this
147 ** instruction at the PC to decide whether to push the function's return
148 ** value, then skips over it without executing.
149 diff --quilt old/source/interpret.h new/source/interpret.h
150 --- old/source/interpret.h
151 +++ new/source/interpret.h
152 @@ -171,6 +171,10 @@ int ExecuteMacro(WindowInfo *window, Pro
153 int ContinueMacro(RestartData *continuation, DataValue *result, char **msg);
154 void RunMacroAsSubrCall(Program *prog);
155 void PreemptMacro(void);
157 +int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs);
158 +int OverlayRoutineFromSymbol(Symbol *sym, int nArgs, int removeArgs);
160 char *AllocString(int length);
161 char *AllocStringNCpy(const char *s, int length);
162 char *AllocStringCpy(const char *s);
163 diff --quilt old/source/macro.c new/source/macro.c
164 --- old/source/macro.c
165 +++ new/source/macro.c
166 @@ -3197,6 +3197,31 @@ static int filenameDialogMS(WindowInfo*
171 + * call(fnname, arg, ...)
173 +static int callMS(WindowInfo *window, DataValue *argList,
174 + int nArgs, DataValue *result, char **errMsg)
176 + char stringStorage[TYPE_INT_STR_SIZE(int)];
181 + *errMsg = "subroutine %s called without arguments";
184 + if (!readStringArg(argList[0], &fnname, stringStorage, errMsg)) {
187 + sym = LookupSymbol(fnname);
189 + *errMsg = "subroutine name invalid";
192 + return OverlayRoutineFromSymbol(sym, nArgs, 1);
196 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
197 DataValue *result, char **errMsg)
198 diff --quilt old/source/built-ins.h new/source/built-ins.h
199 --- old/source/built-ins.h
200 +++ new/source/built-ins.h
201 @@ -58,6 +58,7 @@ MS(get_pattern_at_pos, getPatternAtPos)
202 MS(get_style_by_name, getStyleByName)
203 MS(get_style_at_pos, getStyleAtPos)
204 MS(filename_dialog, filenameDialog)