SICP 全笔记

我们先看看不是 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 进行处理。这样设计不会对最后一个 expressionenv 进行压栈,所以如果可以进行 tail recursion 的话,stack 是不会增加的。