pcs/expand.scm

148 lines
3.2 KiB
Scheme
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(define %sc-expand
(lambda (exp)
(letrec
;------!
(
(expand
(lambda (x env)
(cond ((atom? x)
(exp-atom x env))
((macro? (car x))
(exp-macro x env))
(else
(expand2 x env)))))
(exp-macro
(lambda (x env)
(let ((y (if (pair? macfun)
(cons (cdr macfun)(cdr x)) ; alias
(macfun x)))) ; macro
(if (or (atom? y)
(equal? x y))
(expand2 y env)
(expand y env)))))
(macfun '())
(macro?
(lambda (id)
(set! macfun
(and (symbol? id)
(or (getprop id 'pcs*macro))))
macfun))
(expand2
(lambda (x env)
(if (atom? x)
(exp-atom x env)
(case (car x)
((QUOTE) x)
((SET!) (exp-set! x env))
((DEFINE) (exp-define x env))
((LAMBDA) (exp-lambda x env))
((BEGIN IF) (exp-begin x env))
((LETREC) (exp-letrec x env))
(else (exp-application x env))
))))
(exp-atom
(lambda (x env)
(if (or (not (symbol? x))
(memq x env)
(memq x '(#!true #!false
#!unassigned ))
(getprop x 'pcs*macro)
(getprop x 'pcs*primop-handler))
x
(list '%%get-scoops%% (list 'quote x)))))
(exp-set!
(lambda (x env)
(pcs-chk-length= x x 3)
(let ((id (set!-id x))
(val (expand (set!-exp x) env)))
(if (or (not (symbol? id))
(memq id env)
(memq id '(#!true #!false
#!unassigned ))
(getprop id 'pcs*macro)
(getprop id 'pcs*primop-handler))
(list 'SET! id val)
(list '%%set-scoops%% (list 'QUOTE id) val)))))
(exp-define
(lambda (x env)
(pcs-chk-length= x x 3)
(let ((op (car x)) ; define!, define
(id (set!-id x))
(val (expand (set!-exp x) env)))
(list op id val))))
(exp-lambda
(lambda (x env)
(pcs-chk-length>= x x 3)
(let ((bvl (lambda-bvl x)))
(pcs-chk-bvl x bvl #!true)
(cons 'LAMBDA
(cons bvl
(exp-args (lambda-body-list x)
'()
(extend env bvl)))))))
(exp-begin
(lambda (x env)
(pcs-chk-length>= x x 1)
(cons (car x) ; begin, if
(exp-args (cdr x) '() env))))
(exp-letrec
(lambda (x env)
(pcs-chk-length>= x x 3)
(let ((pairs (letrec-pairs x)))
(pcs-chk-pairs x pairs)
(let ((newenv (extend env (mapcar car pairs))))
(cons 'LETREC
(cons (exp-pairs pairs '() newenv)
(exp-args (letrec-body-list x) '() newenv)))))))
(exp-pairs
(lambda (old new env)
(if (null? old)
(reverse! new)
(let ((id (caar old))
(exp (expand (cadar old) env)))
(exp-pairs (cdr old)
(cons (list id exp) new)
env)))))
(exp-application
(lambda (form env)
(pcs-chk-length>= form form 1)
(exp-args form '() env)))
(exp-args
(lambda (old new env)
(if (null? old)
(reverse! new)
(exp-args (cdr old)
(cons (expand (car old) env) new)
env))))
(extend
(lambda (env bvl)
(cond ((pair? bvl)
(extend (cons (car bvl) env) (cdr bvl)))
((null? bvl)
env)
(else
(cons bvl env)))))
;------!
)
(expand exp '()))))