内部defineを作る
俺Lispを内部defineに対応させてみた。
repl> (letrec () (define x 1) (define y 2) (cons x y))
http://kar.s206.xrea.com/lisp/?e=(letrec%20()%20(define%20x%201)%20(define%20y%202)%20(cons%20x%20y))
(1 . 2)
以下のような展開処理をしてる。
(letrec () (define x 1) (define y 2) (cons x y)) ↓ (letrec ((x 1)) (define y 2) (cons x y)) ↓ (letrec ((y 2) (x 1)) (cons x y)) ↓ (let ((y #f) (x #f)) (set! y 2) (set! x 1) (cons x y)) ↓ ((lambda (y x) (set! y 2) (set! x 1) (cons x y)) #f #f)
letrecとlambdaのコード
(define (eq-car? xs val) (and (pair? xs) (eq? (car xs) val))) (define-macro (letrec arg . body) (if (eq-car? (car body) 'define) `(letrec ,(cons (cdr (macroexpand (car body))) arg) ,@(cdr body)) `(let ,(map (lambda (x) (list (car x) #f)) arg) ,@(map (lambda (x) (list 'set! (car x) (cadr x))) arg) ,@body))) (define-macro (lambda arg . body) (if (eq-car? (car body) 'define) `(new Closure ,arg (letrec () ,@body)) `(new Closure ,arg ,@body)))
lambdaがマクロになったために,プリミティブの(lambda ...)の機能は(new Closure ...)で呼び出すようにした。
ちなみに,(new Macro ...)が従来の(macro ...)相当。