|
The full interpreter performs simplifications and, if it gets an action after simplifying, performs actions. Let's follow a simple evaluation by the interpreter, using the following program.
def main =
printList ['H','o','w',' ',
'm','a','n','y',' ',
's','e','c','o',
'n','d','s','?'];
readInt ~>
(n ->
let m = n/60 in
let h = n/3600 in
let secs = n - 60*m in
let mins = m - 60*h in
printList
[h, ':', mins, ':', secs]
end
end
end
end
)
end
The value of main is the following tree. To help in reading it, I have written the parameter name with each FUNCTION node.
-----~>------
/ \
~> FUN(2)(n)
/ \ |
printList FUN(1) --APPLY--
| | / \
: readInt FUN(3)(m) --(/)--
/ \ | / \
'H' : APPLY PARAM 60
/ \ / \ (2)
'o' … / \
FUN(4)(h) --(/)--
| / \
APPLY PARAM 3600
/ \ (2)
FUN(5)(secs) -
| / \
APPLY / \
/ \ PARAM *
FUN(6)(mins) - (2) / \
| / \ 60 PARAM
| PARAM * (3)
| (3) / \
| 60 PARAM
| (4)
printList
|
:
/ \
PARAM :
(4) / \
':' :
/ \
PARAM :
(6) / \
':' :
/ \
PARAM []
(5)
Simplification of main makes no change, since its root is labeled by ~>. The top-level interpreter gets that tree back. Since the result is an action (because its root is labeled ~>) the top-level interpreter calls performAction on that tree.
PerformAction starts by simplifying the left subtree of the top ~> node, which makes no change to it. So performAction does a recursive call on the left subtree.
Now performAction is passed the following tree.
printList
|
:
/ \
'H' :
/ \
'o' …
It performs the printList, causing the program to write
How many seconds?The result of this printList is [ ], which performAction returns to its caller (as a tree).
Now we are back to the performAction that was called on the lower ~> node. It has received result [ ] from its left subtree, and now it
simplifies its right subtree (the FUN(1) node), which makes no change, and
builds and simplifies tree
APPLY
/ \
FUN(1) []
|
readInt
The result of simplifying the action is just readInt. performAction performs that action by reading an integer.
Imagine that it reads 1000. Now performAction returns 1000 (as a tree) to the copy of performAction that was originally called on the root of the tree.
The top performAction builds and simplifies tree
APPLY
/ \
FUN(2)(n) 1000
|
--APPLY--
/ \
FUN(3)(m) --(/)--
| / \
APPLY PARAM 60
/ \ (2)
/ \
FUN(4)(h) --(/)--
| / \
APPLY PARAM 3600
/ \ (2)
FUN(5)(secs) -
| / \
APPLY / \
/ \ PARAM *
FUN(6)(mins) - (2) / \
| / \ 60 PARAM
| PARAM * (3)
| (3) / \
| 60 PARAM
| (4)
printList
|
:
/ \
PARAM :
(4) / \
':' :
/ \
PARAM :
(6) / \
':' :
/ \
PARAM []
(5)
Simplification yields the following tree (after several steps).
printList
|
:
/ \
0 :
/ \
':' :
/ \
16 :
/ \
':' :
/ \
40 []
performAction continues by simplifiying that list, which replaces each : node by a CONS node, and then prints the members of the list from left to right, which shows
0:16:40Finally, performAction returns [ ] (the answer from printList) to its caller, the top-level interpreter, which stops.
|