The body of a block is evaluated with respect to the current environment extended by a frame that binds all local names to the value "*unassigned*". We temporarily make use of the val register to hold the list of all variables declared in the block, which is obtained by scan_out_declarations from section 4.1.1. The functions scan_out_declarations and list_of_unassigned are assumed to be available as machine operations.[1] "ev_block", assign("comp", list(op("block_body"), reg("comp"))), assign("val", list(op("scan_out_declarations"), reg("comp"))), save("comp"), // so we can use it to temporarily hold $\texttt{*unassigned*}$ values assign("comp", list(op("list_of_unassigned"), reg("val"))), assign("env", list(op("extend_environment"), reg("val"), reg("comp"), reg("env"))), restore("comp"), // the block body go_to(label("eval_dispatch")),
Assignments are handled by ev_assignment, reached from eval_dispatch with the assignment expression in comp. The code at ev_assignment first evaluates the value part of the expression and then installs the new value in the environment. The function assign_symbol_value is assumed to be available as a machine operation.
"ev_assignment",
assign("unev", list(op("assignment_symbol"), reg("comp"))),
save("unev"), // save variable for later
assign("comp", list(op("assignment_value_expression"), reg("comp"))),
save("env"),
save("continue"),
assign("continue", label("ev_assignment_install")),
go_to(label("eval_dispatch")), // evaluate assignment value
"ev_assignment_install",
restore("continue"),
restore("env"),
restore("unev"),
perform(list(op("assign_symbol_value"),
reg("unev"), reg("val"), reg("env"))),
go_to(reg("continue")),Declarations of variables and constants are handled in a similar way. Note that whereas the value of an assignment is the value that was assigned, the value of a declaration is undefined. This is handled by setting val to undefined before continuing. As in the metacircular evaluator, we transform a function declaration into a constant declaration whose value expression is a lambda expression. This happens at ev_function_declaration, which makes the transformation in place in comp and falls through to ev_declaration.
"ev_function_declaration",
assign("comp",
list(op("function_decl_to_constant_decl"), reg("comp"))),
"ev_declaration",
assign("unev", list(op("declaration_symbol"), reg("comp"))),
save("unev"), // save declared name
assign("comp",
list(op("declaration_value_expression"), reg("comp"))),
save("env"),
save("continue"),
assign("continue", label("ev_declaration_assign")),
go_to(label("eval_dispatch")), // evaluate declaration value
"ev_declaration_assign",
restore("continue"),
restore("env"),
restore("unev"),
perform(list(op("assign_symbol_value"),
reg("unev"), reg("val"), reg("env"))),
assign("val", constant(undefined)),
go_to(reg("continue")),cheatby assuming that the syntax transformer while_to_application is available as a machine operation. Refer to exercise 4.7 to discuss whether this approach works if return, break, and continue statements are allowed inside the while loop. If not, how can you modify the explicit-control evaluator to run programs with while loops that include these statements?