Begin with a statically-scoped, eager interpreter for Rip.
You can use any implementation you wish for the environment
(including a list of bindings). Remember, we will care about
the quality of contracts, test suites, etc.
Problem 1
Transform the interpreter into continuation-passing style.
Use it to implement the remaining problems. You will
find it useful to understand what the interpreter's
continuation represents.
Problem 2
Add the following primitive to Rip:
{abort <RP>}
abort
evaluates its sub-expression; the value of
that expression is the value of the
entire program.
(That means, if there's a nested use of
abort
in the sub-expression,
its value is that of the program
and so forth.)
Problem 3
Add the following primitive to Rip (with or without
abort
, as you wish):
{with-continuation <var> <RP>}
with-continuation
binds the variable to a
continuation in the sub-expression, which it then
evaluates. A continuation is a procedure of one argument. If
the programmer never invokes the continuation, the value of
the expression is that of the sub-expression. If the
programmer invokes the continuation, then the value given to
the continuation becomes the value of the entire expression.
(Recall that the programmer can invoke the continuation
outside the expression!)