Conditionals, Assignments and Definitions Blocks, Assignments, and Declarations - SICP Comparison Edition" />
Original | JavaScript | |
As with the metacircular evaluator, special syntactic 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)) (goto (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 true?) (reg val)) (branch (label ev-if-consequent)) ev-if-alternative (assign exp (op if-alternative) (reg exp)) (goto (label eval-dispatch)) ev-if-consequent (assign exp (op if-consequent) (reg exp)) (goto (label eval-dispatch)) |
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, which is ev_assignment, reached from eval-dispatch eval_dispatch with the assignment expression in exp. comp. The code at ev-assignment ev_assignment first evaluates the value part of the expression and then installs the new value in the environment. Set-variable-value! The function assign_symbol_value is assumed to be available as a machine operation.
Original | JavaScript |
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)) (goto (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)) (goto (reg continue)) | "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")), |
Original | JavaScript | |
Definitions are handled in a similar way: | 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. |
Original | JavaScript |
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)) (goto (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)) (goto (reg continue)) | "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")), |
Original | JavaScript | |
Extend the evaluator to handle derived expressions such as
cond,
let, and so on
(section 4.1.2).
You may cheatand assume that the syntax transformers such as cond->if are available as machine operations.[2] |
Extend the evaluator to handle
while loops, by translating them to applications of a function
while_loop, as shown in
exercise 4.11.
You can paste the declaration of the function
while_loop in front of user programs.
You may cheatby assuming that the syntax transformer while_to_application is available as a machine operation. Refer to exercise 4.11 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? |
Original | JavaScript | |
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.
|