SPROGS Note 9 set out several addressing schemes for index variables assuming that local workspace and formal arguments were desirable. The method described here suggests another alternative. Addresses for globals and locals are as per Note 9.
The argument passing scheme is to pass both addresses and values to the called routine. Arguments are then referenced like locals. On exit from the called routine, argument values are copied back into the addresses passed at call time. It is necessary to know the number of arguments in the called routine. For example (names omitted):
STDF (FOO) STDF(TWOSIT) LOCARG(X) LOCARG(ARG1) LOCAL(TWO) LOCARG(ARG2) LOAD (TWO, 2.0) LOCARG(ARG3) LOAD(GLOBA,3.0) LOCAL(LOC1) LOAD(LOC1,7.0) ARG(X) LOAD (ARG1,ARG2) ARG(TWO) LOAD (ARG3,ARG2) ARG(GLOBA) SETXY(PR(ARGl),1.0) DRAW (TWOSIT) SETXY(PR(GLOBA),1.0) FIDF FIDF
The number of arguments in TWOSIT is stored in the file. Now,
LOAD(BAR,6.0) ARG (BAR) DRAW(FOO)
generates a stack looking like:
Level of Routine Address Stack Value FOO BAR X 6.0 TWO 2.0 BAR X ARG1 6.0 TWO ARG2 2.0 GLOBA ARG3 3.0 LOC1 7.0
Thus, ARG has the job of planting both the address of its index variable argument and its value in the next two free stack positions. FIDF must examine the file header to find out how many arguments the called routine expects, then copy these back using the addresses stored in the stack.
This scheme has the following advantages :-
(1) locals and arguments look the same so there are no addressing distinctions between the two;
(2) there is no extra overhead in using arguments as opposed to locals or globals;
(3) indirect addressing is possible. There is no distinction between PR(LOCAL) and PR(argument);
(4) call by value is obtained by setting a flag telling FIDF not to copy back values;
(5) only one extra stack word per argument is required.
There are two problems, the first one rather serious:-
(a) Because actual arguments are not updated until exit, a global may be referenced with an old value. In the example, TOSIT does a SETXY at (2.0,1.0) and (3.0,1.0) even though GLOBA has been set to 2.0. This sort of problem is usually avoidable but easy to forget.
(b) To call a routine with arguments, it is necessary to put the constant in an index variable. That is, to call FOO with an argument of 6.0, one must :-
LOAD(BAR, 6.0) ARG(BAR) DRAW (FOO)
This is cumbersome if most arguments are simple constants. The problem can be avoided by defining a new argument passing routine,
CARG (<constant>)
CARG places a known spurious global address in the stack as the address of <constant>. It then places the constant in the usual stack position for the argument value. On copy back, the argument value is written into a spurious index variable.