The special function Go is used in the Refal system to put the initial expression in the view field of the Refal machine. When this expression is evaluated, the Refal machine stops and passes control to the operating system of the computer. This is the simplest mode of interaction between the user and the Refal machine. Sometimes we would prefer a different mode. We would like to give a Refal expression to the machine, have it evaluated, and have the control returned to the user without exiting from the Refal system so that another expression could be evaluated, and so any number of times.
If the user is prepared to write the expression he wants evaluated in the metacode, then the solution of this problem is quite simple. We define Go as a call of an interpreting function Job which asks the user to type in an expression, applies Up to it, and when computation is completed prints out the result and asks for the next expression.
However, it would perplex the user to write the desired expressions in the metacode; it is preferable to allow him to write expressions in the same form as they appear in the program. Therefore, instead of the function Input , which inputs object expressions, we use another function -- let it have the name Inp-met -- which reads in an expression and downgrades it in the metacode. Its major difference from Input is that the characters '<' and '>' are taken as activation brackets.
Now we should think of how to tie this definition of Go to the existing Refal modules. If Up were dynamic, there would be no other way than to replace the Go of the main module by the Go calling the interpreting function Job described above. This would mean that the program would be usable only in the evaluator mode.
Our built-in function Up , however, is static. We form the above Go into a separate module which we call E (for `Evaluator') and we modify it by changing Up to UpD and declare UpD as an external function. To use any module, say Prog , with the evaluator we have to add to Prog the standard definition:
$ENTRY UpD { e.X = <Up e.X> }
The beginning of the program E is as follows:
* Evaluator E $ENTRY Go { = <Job>; } Job { = <Prout 'Type expression to evaluate. ' 'To end: empty line.'> <Prout 'To end session: empty expression'> <Prout > <Check-end <Inp-met>>; } Check-end { = <Prout 'End of session'>; '*'Error = <Job>; e.X = <Out <UpD e.X>>; } Out {e.X = <Prout 'The result is:'> <Prout e.X> <Prout> <Job>; } $EXTRN UpD;
Now, if Prog is a main module (i.e., includes a definition of Go ) we can use it in the Go mode as before:
refgo prog ...(where the dots stand for possible auxiliary modules). But whether Prog is main or auxiliary, we can always use it in the evaluator mode:
refgo e+prog ...Now the evaluator module e is, formally, the main module, but we have access through UpD to every function of Prog . The standard definition of UpD can be added to every Refal module in advance: it will not hurt. Only the UpD of the first module following the evaluator e will actually be used. The tracer reftr can be run in the same way.
The evaluator module e.ref
is coming with the Refal system.
NOTE:
There is no interpretation in the use of the evaluator.
The only additional time, as compared with the Go mode,
is spent on the input of the expression to evaluate.
This having been done, Up
creates an active expression
in the view field -- which is executed in exactly the same manner
as always.