私は少し前に独自のScheme metacircular インタプリタを書き、特別な形式の=>
構文をサポートしました。cond
本質的に、これは私がしなければならなかったことです:
(define (expand-actions clause)
(let ((exp (sequence->exp (cond-actions clause))))
(if (cond-has-then? clause)
(make-application exp
(if (cond-else-clause? clause)
#t
(list (cond-predicate clause))))
exp)))
式のすべての句 (述語とアクションのペア) を反復するとき、各アクションを展開し、トークンが句に存在cond
するかどうかを尋ねます (を使用)。が見つかった場合は、節のアクション部分を述語に適用します。=>
cond-has-then?
=>
cond
これは、私のインタープリターで式を評価するコードの完全な部分です。メイン プロシージャ ( から呼び出されるものeval
) は、式を一連のネストされた式にcond->if
変換し、構文も処理します。これがお役に立てば幸いです:cond
if
=>
(define (cond->if exp)
(expand-clauses (cond-clauses exp)))
(define cond-clauses cdr)
(define (cond-has-then? clause)
(eq? (cadr clause) '=>))
(define cond-predicate car)
(define (cond-actions clause)
(if (cond-has-then? clause)
(cddr clause)
(cdr clause)))
(define (cond-else-clause? clause)
(eq? (cond-predicate clause) 'else))
(define (expand-clauses clauses)
(if (null? clauses)
(void)
(let ((first (car clauses))
(rest (cdr clauses)))
(if (cond-else-clause? first)
(if (null? rest)
(expand-actions first)
(error "ELSE clause isn't last -- COND->IF" clauses))
(make-if (cond-predicate first)
(expand-actions first)
(expand-clauses rest))))))
(define (expand-actions clause)
(let ((exp (sequence->exp (cond-actions clause))))
(if (cond-has-then? clause)
(make-application exp
(if (cond-else-clause? clause)
#t
(list (cond-predicate clause))))
exp)))
(define (make-if predicate consequent alternative)
(list 'if predicate consequent alternative))
(define (sequence->exp seq)
(cond ((null? seq) '())
((last-exp? seq) (first-exp seq))
(else (make-begin seq))))
(define (last-exp? seq)
(null? (cdr seq)))
(define first-exp car)
(define (make-application proc . args)
(cond ((null? args) (list proc))
((list? (car args)) (cons proc (car args)))
(else (cons proc args))))
(define (make-begin seq)
(cons 'begin seq))