|
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.
|