home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-386-Vol-2of3.iso
/
c
/
cr-macro.zip
/
EXPAND.SCM
< prev
next >
Wrap
Text File
|
1990-02-16
|
6KB
|
194 lines
; Translate Scheme to Scheme, expanding macros and alpha-converting
(define (expand exp env)
(classify exp env perform-expansion))
(define (expand-list exp-list env)
(map (lambda (exp) (expand exp env))
exp-list))
(define (perform-expansion class exp env)
((vector-ref expansion-procedures class) exp env))
(define (expand-literal exp env) exp)
(define (expand-variable exp env)
(let ((binding (lookup-variable exp env)))
(cond ((symbol? binding) binding)
((unbound? binding)
(unbound-name binding))
(else (error "invalid binding" binding)))))
(define (expand-application exp env)
(classify (operator exp) env
(lambda (class op-exp op-env)
(if (= class class/lambda)
(let* ((formals (lambda-formals op-exp))
(body-env (bind-variables (normalize-formals formals)
op-env)))
`(let ,(map list
(rename-formals formals body-env)
(expand-list (operands exp) env))
,(expand-body (lambda-body op-exp) body-env)))
(cons (perform-expansion class op-exp op-env)
(expand-list (operands exp) env))))))
(define (expand-lambda exp env)
(let* ((formals (lambda-formals exp))
(env (bind-variables (normalize-formals formals)
env)))
`(lambda ,(rename-formals formals env)
,(expand-body (lambda-body exp) env))))
(define (rename-formals formals env)
(cond ((null? formals) '())
((pair? formals)
(cons (lookup-variable (car formals) env)
(rename-formals (cdr formals) env)))
(else (lookup-variable formals env))))
(define (normalize-formals formals)
(cond ((null? formals) '())
((pair? formals)
(cons (car formals) (normalize-formals (cdr formals))))
(else (list formals))))
(define (expand-letrec exp env)
(let* ((bspecs (letrec-bspecs exp))
(env (bind-variables (map bspec-name bspecs) env)))
`(letrec ,(map (lambda (bspec)
`(,(lookup-variable (bspec-name bspec) env)
,(expand (bspec-rhs bspec) env)))
bspecs)
,(expand-body (letrec-body exp) env))))
(define (expand-if exp env)
(let ((alt (expand (if-alternate exp) env)))
(if (equal? alt unspecified-expression)
`(if ,(expand (if-test exp) env)
,(expand (if-consequent exp) env))
`(if ,(expand (if-test exp) env)
,(expand (if-consequent exp) env)
,alt))))
(define (expand-quote exp env)
`',(unpaint (quotation-text exp)))
(define (expand-begin exp env)
`(begin ,@(expand-list (begin-statements exp) env)))
(define (expand-set! exp env)
`(set! ,(expand-variable (set!-lhs exp) env)
,(expand (set!-rhs exp) env)))
(define (expand-let-syntax exp env)
(classify-let-syntax exp env perform-expansion))
(define (expand-letrec-syntax exp env)
(classify-letrec-syntax exp env perform-expansion))
(define (expand-invalid-context exp env)
(syntax-error "form not appropriate in expression context" exp))
(define expansion-procedures
(let ((v (make-vector number-of-classes expand-invalid-context)))
(vector-set! v class/literal expand-literal)
(vector-set! v class/variable expand-variable)
(vector-set! v class/application expand-application)
(vector-set! v class/lambda expand-lambda)
(vector-set! v class/letrec expand-letrec)
(vector-set! v class/if expand-if)
(vector-set! v class/quote expand-quote)
(vector-set! v class/begin expand-begin)
(vector-set! v class/set! expand-set!)
(vector-set! v class/let-syntax expand-let-syntax)
(vector-set! v class/letrec-syntax expand-letrec-syntax)
v))
(define *counter* 0)
(define (bind-variables names env)
(if (null? names)
env
(begin (set! *counter* (+ *counter* 1))
(let ((suffix (number->string *counter* '(heur))))
(bind names
(map (lambda (name)
(string->symbol (string-append "."
(symbol->string (name->symbol name))
"."
suffix)))
names)
env)))))
(define (make-name-generator)
;; Don't bump counter if no names are generated
(let ((color (delay (new-color))))
(lambda (name)
(make-painted name (force color)))))
; Process a lambda or letrec body
(define (expand-body body env)
(scan-body body env
(lambda (names ds exps)
(let* ((env (bind-variables names env))
(beg (if (null? (cdr exps))
(expand (car exps) env)
`(begin ,@(expand-list exps env)))))
(if (null? names)
beg
`(letrec ,(map (lambda (name d)
`(,(lookup name env)
,(d env perform-expansion)))
names
ds)
,beg))))))
; Top level processing
(define expand-top
(lambda (form env)
(classify form env perform-expansion-top)))
(define (perform-expansion-top class form env)
(cond ((= class class/define)
(let ((name (define-name form)))
(environment-define! env name (name->symbol name))
`(define ,name ,(expand (define-rhs form) env))))
((= class class/define-syntax)
(environment-define! env
(define-syntax-name form)
(process-syntax-binding (define-syntax-rhs form)
env))
''define-syntax)
((= class class/begin)
`(begin ,@(map (lambda (form)
(expand-top form env))
(begin-statements form))))
(else (expand form env))))
; Test routine
(define (test exp . maybe-env)
(set! *color* 0)
(set! *counter* 0)
(expand-top exp
(if (null? maybe-env)
test-environment
(car maybe-env))))
(define bare-environment
(make-mutable-environment (make-transformer-environment)))
(define-special-operators! bare-environment)
(define test-environment bare-environment)
; ??? where does this belong?
; (put 'bind 'scheme-indent-hook nil)
; (put 'classify 'scheme-indent-hook 2)