As with the metacircular evaluator, special forms are handled by
selectively evaluating fragments of the expression. For an `if`
expression, we must evaluate the predicate and decide, based on the
value of predicate, whether to evaluate the consequent or the
alternative.

Before evaluating the predicate, we save the `if` expression
itself so that we can later extract the consequent or alternative. We
also save the environment, which we will need later in order to
evaluate the consequent or the alternative, and we save `continue`, which we will need later in order to return to the
evaluation of the expression that is waiting for the value of the `if`.

"ev_if", save("exp"), // save expression for later save("env"), save("continue"), assign("continue", label("ev_if_decide")), assign("exp", op("if_predicate"), reg("exp")), go_to(label("eval_dispatch")), // evaluate the predicate

When we return from evaluating the predicate, we test whether it was
true or false and, depending on the result, place either the
consequent or the alternative in `exp` before going to `eval_dispatch`. Notice that restoring `env` and `continue`
here sets up `eval_dispatch` to have the correct environment and
to continue at the right place to receive the value of the `if`
expression.

"ev_if_decide", restore("continue"), restore("env"), restore("exp"), test(op("is_true"), reg("val")), branch(label("ev_if_consequent")), "ev_if_alternative", assign("exp", op("if_alternative"), reg("exp")), go_to(label("eval_dispatch")), "ev_if_consequent", assign("exp", op("if_consequent"), reg("exp")), go_to(label("eval_dispatch")),

Assignments are handled by `ev_assignment`, which is reached from
`eval_dispatch` with the assignment expression in `exp`. The code at `ev_assignment` first evaluates the value part of the expression and
then installs the new value in the environment. `Set_variable_value` is assumed to be available as a machine
operation.

"ev_assignment", assign("unev", op("assignment_variable"), reg("exp")), save("unev"), // save variable for later assign("exp", op("assignment_value"), reg("exp")), save("env"), save("continue"), assign("continue", label("ev_assignment_1")), go_to(label("eval_dispatch")), // evaluate the assignment value "ev_assignment_1", restore("continue"), restore("env"), restore("unev"), perform(op("set_variable_value"), reg("unev"), reg("val"), reg("env")), assign("val", const("ok")), go_to(reg("continue")),

Definitions are handled in a similar way:

"ev-definition", assign("unev", op("definition-variable"), reg("exp")), save("unev"), // save variable for later assign("exp", op("definition-value"), reg("exp")), save("env"), save("continue"), assign("continue", label("ev-definition-1")), go_to(label("eval-dispatch")), // evaluate the definition value "ev-definition-1", restore("continue"), restore("env"), restore("unev"), perform(op("define-variable"), reg("unev"), reg("val"), reg("env")), assign("val", const("ok")), go_to(reg("continue")),

cheatand assume that the syntax transformers such as

There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in Github.

[1] This isn't really cheating. In an actual
implementation built from scratch, we would use our explicit-control
evaluator to interpret a JavaScript program that performs source-level
transformations in a syntax phase that runs before
execution.

5.4.3
Conditionals, Assignments, and Definitions