2.12 Implementing Laziness (extra credit)
You must complete this assignment by yourself.
You must submit this in an archive named "lazyimpl.zip".
2.12.1 Lazy Extended Interpreter
You must submit this in a file named "xinterp-lazy.ss".
Copy your extended interpreter into a file named "xinterp-lazy.ss" and modify it so that it has lazy application semantics. (You should not do this until you’ve gotten your extended interpreter tested and debugged!)
2.12.1.1 Template
Change CFWAE-Value:
| (define-type CFWAE-Value |
| [numV (n number?)] |
| [closureV (params (listof symbol?)) |
| (body CFWAE?) |
| (env Env?)] |
| [exprV (expr CFWAE?) |
| (env Env?)]) |
Use exprV to implement expression closures. You will also find it helpful to define strict.
2.12.1.2 Tests
You should be able to run all the tests from "xinterp.ss". It is considered a “special” test case to show that your code is lazy. There are two good ways to do this. You will get points for both.
2.12.2 Strictness Points
You must submit this in a file named "lazyimpl.pdf".
In our lazy interpreter, we identified four points in the language where we need to force evaluation of expression closures (by invoking strict): the function position of an application, the test expression of a conditional, arithmetic primitive arguments, and the interpreter’s final output. Doug Oord, a fairly sedentary student, is rather taken with the idea of laziness. He suggests that we can reduce the amount of code we need to write by replacing all invocations of strict with just one. In the lazy interpreter, he removes all instances of strict and replaces
[id (v) (lookup v env)]
with
[id (v) (strict (lookup v env))]
Doug’s reasoning is that the only time the interpreter returns an expression closure is on looking up an identifier in the environment. If we force its evaluation right away, we can be sure no other part of the interpreter will get an expression closure, so removing those other invocations of strict will do no harm. Being lazy himself, however, Doug fails to reason in the other direction, namely whether this will result in an overly eager interpreter.
Is it possible to write a program that will produce different results under the original interpreter and Doug’s? Let the interpreted language feature arithmetic, first-class functions, with, and if0.
If so, turn in a test case and the result under each interpreter, and clearly identify which interpreter will produce each result. Be sure to compare this behavior against that of the lazy interpreter of the sort we’ve written in class.
If it’s not possible, defend why one cannot exist.