“JRM’s Syntax-rules Primer for the Merely Eccentric” メモ(その7) scheme-eval

続きです。最後の scheme-eval

The obligatory hack.

The following is a small scheme interpreter written as a syntax-rules macro. It is incredibly slow.

いつものやつ、とか、いつものやんなきゃなんないやつ、といったところでしょうか。

(scheme-eval
 ((Y (lambda (fac)
       (lambda (n)
         (if (sero? n)
           '(())
           (mulz n (fac (zub1 n)))))))
  '(() () ())))
;;-> (quote (() () () () () ()))

“The Little Schemer” に出てくる 6. Shadows の章の関数群と Y 関数を使って階乗が動いたところ。すごい動いた、というシンプルすぎる正直な感想です。

initial-environmentsero? 等の関数を置いておきたいので、 lambda form が動くようにしました。

...

(define-syntax meval
  (syntax-rules (if lambda quote)
    ((meval k () env) (return k ()))
    ((meval k (if pred cons alt) env)
     (macro-if (meval pred env)
       (meval k cons env)
       (meval k alt env)))
    ((meval k (lambda names body) env)
     (return k (closure names body env)))
    ((meval k (quote object) env)
     (return k object))
    ((meval k (operator . operands) env)
     (meval-list ((mapply k env)) () (operator . operands) env))
    ((meval k whatever env)
     (macro-if (is-symbol? whatever)
       (mlookup k whatever env)
       (return k whatever)))))

...

(define-syntax mapply
  (syntax-rules (closure lambda)
    ((mapply k _env ((closure names body env) . operands))
     (macro-call k
       (! (meval body (! (extend-environment env names operands))))))
    ((mapply k env ((lambda names body) . operands))
     (macro-call k
       (! (meval body (! (extend-environment env names operands))))))
    ((mapply k _env (operator . operands))
     (macro-if (is-symbol? operator)
       (operator k . operands)
       '(non symbol application: operator)))))

...