我们先看看不是 tail recursion 的实现
; no tail recursion
ev-sequence
(test (op no-more-exps?) (reg unev))
(branch (label ev-sequence-end))
(assign exp (op first-exp) (reg unev))
(save unev)
(save env)
(assign continue (label ev-sequence-continue))
(goto (label eval-dispatch))
ev-sequence-continue
(restore env)
(restore unev)
(assign unev (op rest-exps) (reg unev))
(goto (label ev-sequence))
ev-sequence-end
(restore continue)
(goto (reg continue))
对于 sequence,这个 evaluator 首先查看还有没有后续的 expression,如果没有则返回 caller 的位置。如果有(哪怕只有最后一条),也把当前的 env 放到 stack 上,然后执行后续的操作(调用 eval-dispatch)。
而对于 tail recursion 来说,
; tail recursion
ev-sequence
(assign exp (op first-exp) (reg unev))
(test (op last-exp?) (reg unev))
(branch (label ev-sequence-last-exp))
(save unev)
(save env)
(assign continue (label ev-sequence-continue))
(goto (label eval-dispatch))
ev-sequence-continue
(restore env)
(restore unev)
(assign unev (op rest-exps) (reg unev))
(goto (label ev-sequence))
ev-sequence-last-exp
(restore continue)
(goto (label eval-dispatch))
它对最后一个 expression 单独处理。如果它是最后一个,直接调用 eval-dispatch 进行处理。这样设计不会对最后一个 expression 的 env 进行压栈,所以如果可以进行 tail recursion 的话,stack 是不会增加的。