next up previous
Next: 4. Compound Macro Statements Up: A Tutorial on the Previous: 2. Macro Command Language Summary

3. Hierarchical Macro Calls

 

For implementing complex procedures, it is sometimes useful to encapsulate individual subtasks into separate macros, which can be developed and tested independently, and which might sometimes be used as stand-alone macros for performing just the corresponding subtask. The macro which performs the complete procedure can now perform these subtasks by using ``call macro'' commands of the form ~<subtask p1 p2 p3 ... .

When a ``call macro'' command is encountered, the processing of the current macro is temporarily suspended and the called macro is executed as a subroutine of the calling macro. Once the execution of the called macro is terminated, the calling macro resumes operation at the line following the ``call macro'' command. The calling of sub-macros is not restricted to a single level, but it can be applied to as many levels as are required, thus allowing the implementation of an arbitrary hierarchy of macro calls. Even recursive invocations of the same macro are allowed.

While the principle of hierarchical macro invocation is straight forward, it is important to look at what exactly happens to the register and parameter values when one macro calls another macro. Since each macro uses the registers differently, it is important to avoid conflicts, e.g. as would result if a called macro would modify register values that the calling macro still needs for its continuation. Also a calling macro needs to pass argument values to the called macro, and, upon termination, the latter may need to pass back return values. In the remaining part of this section, we will look at these questions in detail.

In the implementation of hierarchical macro calls, registers are implemented in such a way that each macro is provided with its own, private set of registers. This implies that a macro does not need to worry about the register usage of the macros that it calls. Even if an invoked macro uses the same registers for storing its own information, the calling macro will still find its own register values unchanged upon the return of the called macro. This way, conflicting register usage between different macros is impossible.

When a macro is called by another macro, its (private) register values are initialized to the current register values of the calling macro. This allows that parameters can be passed from the calling to the called macro via the registers (in addition to the parameters that are specified on the call macro command itself). On the other hand, this also implies that a macro should never assume that the registers are initialized to zero (or blank for text registers), but always initialize the used registers explicitly.

When macro needs to pass a return value back to the calling macro, it can do so by storing the return value into the text register t9. As an exception to the rule explained above, the t9 register is implemented as a global register. Therefore, all macros share the same value of t9, and a change to this register made in a lower level macro, is visible to the macros at the upper levels. If more than one return value are to be passed back, these can be assembled into the text register (which can hold up to 124 characters) and be disassembled back into its parts in the calling macro.



Exercise 3.1:
Assume that you are writing a macro which needs to invoke existing macros which you do not know in detail and you suspect that they might not explicitly initialize the registers before using them, but (wrongly!) rely on them being already initialized to zero (resp. blank). Write a general purpose ``wrapper'' macro which can be used to invoke such macros.



Exercise 3.2:
Write a recursive macro factor to compute the factorial n!, where n is given as macro parameter and the result is stored in t9.


next up previous
Next: 4. Compound Macro Statements Up: A Tutorial on the Previous: 2. Macro Command Language Summary

Heinz Spiess, EMME/2 Support Center
Fri Sep 27 13:04:28 MET DST 1996