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.
与元循环求值器一样,特殊形式通过有选择地对表达式的各个片段求值来处理。对于 if 表达式,我们必须对谓词求值,然后根据谓词的值决定对consequent(后件)还是 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.
在对谓词求值之前,我们先保存 if 表达式本身,以便稍后提取consequent或 alternative。我们还保存环境,以便稍后对consequent或 alternative 求值时使用;以及保存 continue,以便稍后在 if 求值完成后能返回到等待该值的表达式求值处。
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.
从谓词求值返回后,我们检测结果是真还是假,根据结果将consequent或 alternative 置入 exp,然后跳转至 eval-dispatch。请注意,在此处恢复 env 和 continue,正是为了使 eval-dispatch 具有正确的环境,并在接收 if 表达式的值时能继续执行正确的位置。
Subheading: Assignments and definitions
小节标题:赋值与定义
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 处理,控制器从 eval-dispatch 以赋值表达式在 exp 中抵达此处。ev-assignment 处的代码首先对表达式的值部分求值,然后将新值安装到环境中。set-variable-value! 被假定为一个可用的机器操作。
Definitions are handled in a similar way:
定义的处理方式与此类似:
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))
; evaluate the predicate:
(goto (label eval-dispatch)) 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)) 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))
; evaluate the assignment value:
(goto (label eval-dispatch))
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-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))
; evaluate the definition value:
(goto (label eval-dispatch))
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))