2232 lines
89 KiB
Scheme
2232 lines
89 KiB
Scheme
|
|
(library (ikarus syntax)
|
|
(export)
|
|
(import (scheme))
|
|
(define who 'expander)
|
|
(define-syntax no-source
|
|
(lambda (x) #f))
|
|
(begin ;;; GOOD ONES
|
|
(define-syntax build-application
|
|
(syntax-rules ()
|
|
((_ ae fun-exp arg-exps)
|
|
`(,fun-exp . ,arg-exps))))
|
|
(define-syntax build-conditional
|
|
(syntax-rules ()
|
|
((_ ae test-exp then-exp else-exp)
|
|
`(if ,test-exp ,then-exp ,else-exp))))
|
|
(define-syntax build-lexical-reference
|
|
(syntax-rules ()
|
|
((_ ae var) var)
|
|
((_ type ae var) var)))
|
|
(define-syntax build-lexical-assignment
|
|
(syntax-rules ()
|
|
((_ ae var exp) `(set! ,var ,exp))))
|
|
(define-syntax build-global-reference
|
|
(syntax-rules ()
|
|
[(_ ae var) `(top-level-value ',var)]))
|
|
(define-syntax build-global-assignment
|
|
(syntax-rules ()
|
|
[(_ ae var exp) `(#%set-top-level-value! ',var ,exp)]))
|
|
(define-syntax build-global-definition
|
|
(syntax-rules ()
|
|
[(_ ae var exp) (build-global-assignment ae var exp)]))
|
|
(define-syntax build-lambda
|
|
(syntax-rules ()
|
|
[(_ ae vars exp) `(case-lambda [,vars ,exp])]))
|
|
(define build-case-lambda
|
|
(lambda (ae vars* exp*)
|
|
`(case-lambda . ,(map list vars* exp*))))
|
|
(define build-let
|
|
(lambda (ae lhs* rhs* body)
|
|
`((case-lambda [,lhs* ,body]) . ,rhs*)))
|
|
(define-syntax build-primref
|
|
(syntax-rules ()
|
|
[(_ ae name) (build-primref ae 1 name)]
|
|
[(_ ae level name) `(|#primitive| ,name)]))
|
|
(define-syntax build-foreign-call
|
|
(syntax-rules ()
|
|
[(_ ae name arg*) `(foreign-call ,name . ,arg*)]))
|
|
(define-syntax build-data
|
|
(syntax-rules ()
|
|
((_ ae exp) `',exp)))
|
|
(define build-sequence
|
|
(lambda (ae exps)
|
|
(let loop ((exps exps))
|
|
(if (null? (cdr exps))
|
|
(car exps)
|
|
(if (equal? (car exps) '(#%void))
|
|
(loop (cdr exps))
|
|
`(begin ,@exps))))))
|
|
(define build-void
|
|
(lambda () '(#%void)))
|
|
(define build-letrec
|
|
(lambda (ae vars val-exps body-exp)
|
|
(if (null? vars) body-exp `(letrec ,(map list vars val-exps) ,body-exp)))))
|
|
(define top-mark* '(top))
|
|
(define top-marked?
|
|
(lambda (m*) (memq 'top m*)))
|
|
(define gen-lexical
|
|
(lambda (sym)
|
|
(cond
|
|
[(symbol? sym)
|
|
(gensym (symbol->string sym))]
|
|
[(stx? sym) (gen-lexical (id->sym sym))]
|
|
[else (error 'gen-lexical "invalid arg ~s" sym)])))
|
|
(define gen-label
|
|
(lambda (_) (gensym)))
|
|
(define make-rib
|
|
(lambda (sym* mark** label*)
|
|
(vector 'rib sym* mark** label*)))
|
|
(define make-full-rib
|
|
(lambda (id* label*)
|
|
(make-rib (map id->sym id*) (map stx-mark* id*) label*)))
|
|
(define make-empty-rib
|
|
(lambda ()
|
|
(make-rib '() '() '())))
|
|
(define extend-rib!
|
|
(lambda (rib id label)
|
|
(if (rib? rib)
|
|
(let ([sym (id->sym id)] [mark* (stx-mark* id)])
|
|
(vector-set! rib 1 (cons sym (vector-ref rib 1)))
|
|
(vector-set! rib 2 (cons mark* (vector-ref rib 2)))
|
|
(vector-set! rib 3 (cons label (vector-ref rib 3))))
|
|
(error 'extend-rib! "~s is not a rib" rib))))
|
|
(define rib?
|
|
(lambda (x)
|
|
(and (vector? x)
|
|
(= (vector-length x) 4)
|
|
(eq? (vector-ref x 0) 'rib))))
|
|
(define rib-sym*
|
|
(lambda (x)
|
|
(if (rib? x)
|
|
(vector-ref x 1)
|
|
(error 'rib-sym* "~s is not a rib" x))))
|
|
(define rib-mark**
|
|
(lambda (x)
|
|
(if (rib? x)
|
|
(vector-ref x 2)
|
|
(error 'rib-mark** "~s is not a rib" x))))
|
|
(define rib-label*
|
|
(lambda (x)
|
|
(if (rib? x)
|
|
(vector-ref x 3)
|
|
(error 'rib-label* "~s is not a rib" x))))
|
|
(module (make-stx stx? stx-expr stx-mark* stx-subst*)
|
|
(define-record stx (expr mark* subst*)))
|
|
(define datum->stx
|
|
(lambda (id datum)
|
|
(make-stx datum (stx-mark* id) (stx-subst* id))))
|
|
(define join-wraps
|
|
(lambda (m1* s1* e)
|
|
(define cancel
|
|
(lambda (ls1 ls2)
|
|
(let f ((x (car ls1)) (ls1 (cdr ls1)))
|
|
(if (null? ls1)
|
|
(cdr ls2)
|
|
(cons x (f (car ls1) (cdr ls1)))))))
|
|
(let ((m2* (stx-mark* e)) (s2* (stx-subst* e)))
|
|
(if (and (not (null? m1*))
|
|
(not (null? m2*))
|
|
(eq? (car m2*) anti-mark))
|
|
; cancel mark, anti-mark, and corresponding shifts
|
|
(values (cancel m1* m2*) (cancel s1* s2*))
|
|
(values (append m1* m2*) (append s1* s2*))))))
|
|
(define stx
|
|
(lambda (e m* s*)
|
|
(if (stx? e)
|
|
(let-values ([(m* s*) (join-wraps m* s* e)])
|
|
(make-stx (stx-expr e) m* s*))
|
|
(make-stx e m* s*))))
|
|
(define add-subst
|
|
(lambda (subst e)
|
|
(if subst
|
|
(stx e '() (list subst))
|
|
e)))
|
|
(define gen-mark
|
|
(lambda () (string #\m)))
|
|
(define add-mark
|
|
(lambda (m e)
|
|
(stx e (list m) '(shift))))
|
|
(define anti-mark #f)
|
|
(define syntax-kind?
|
|
(lambda (x p?)
|
|
(if (stx? x)
|
|
(syntax-kind? (stx-expr x) p?)
|
|
(p? x))))
|
|
(define syntax-vector->list
|
|
(lambda (x)
|
|
(cond
|
|
[(stx? x)
|
|
(let ([ls (syntax-vector->list (stx-expr x))]
|
|
[m* (stx-mark* x)] [s* (stx-subst* x)])
|
|
(map (lambda (x) (stx x m* s*)) ls))]
|
|
[(vector? x) (vector->list x)]
|
|
[else (error 'syntax-vector->list "not a syntax vector ~s" x)])))
|
|
(define syntax-pair?
|
|
(lambda (x) (syntax-kind? x pair?)))
|
|
(define syntax-vector?
|
|
(lambda (x) (syntax-kind? x vector?)))
|
|
(define syntax-null?
|
|
(lambda (x) (syntax-kind? x null?)))
|
|
(define syntax-list?
|
|
(lambda (x)
|
|
(or (syntax-null? x)
|
|
(and (syntax-pair? x) (syntax-list? (syntax-cdr x))))))
|
|
(define syntax-car
|
|
(lambda (x)
|
|
(if (stx? x)
|
|
(stx (syntax-car (stx-expr x)) (stx-mark* x) (stx-subst* x))
|
|
(if (pair? x)
|
|
(car x)
|
|
(error 'syntax-car "~s is not a pair" x)))))
|
|
(define syntax->list
|
|
(lambda (x)
|
|
(if (syntax-pair? x)
|
|
(cons (syntax-car x) (syntax->list (syntax-cdr x)))
|
|
(if (syntax-null? x)
|
|
'()
|
|
(error 'syntax->list "invalid ~s" x)))))
|
|
(define syntax-cdr
|
|
(lambda (x)
|
|
(if (stx? x)
|
|
(stx (syntax-cdr (stx-expr x)) (stx-mark* x) (stx-subst* x))
|
|
(if (pair? x)
|
|
(cdr x)
|
|
(error 'syntax-cdr "~s is not a pair" x)))))
|
|
(define id?
|
|
(lambda (x) (syntax-kind? x symbol?)))
|
|
(define id->sym
|
|
(lambda (x)
|
|
(if (stx? x)
|
|
(id->sym (stx-expr x))
|
|
(if (symbol? x)
|
|
x
|
|
(error 'id->sym "~s is not an id" x)))))
|
|
(define same-marks?
|
|
(lambda (x y)
|
|
(or (eq? x y)
|
|
(and (pair? x) (pair? y)
|
|
(eq? (car x) (car y))
|
|
(same-marks? (cdr x) (cdr y))))))
|
|
(define bound-id=?
|
|
(lambda (x y)
|
|
(and (eq? (id->sym x) (id->sym y))
|
|
(same-marks? (stx-mark* x) (stx-mark* y)))))
|
|
(define free-id=?
|
|
(lambda (i j)
|
|
(let ((t0 (id->label i)) (t1 (id->label j)))
|
|
(if (or t0 t1)
|
|
(eq? t0 t1)
|
|
(eq? (id->sym i) (id->sym j))))))
|
|
(define valid-bound-ids?
|
|
(lambda (id*)
|
|
(and (andmap id? id*)
|
|
(distinct-bound-ids? id*))))
|
|
(define distinct-bound-ids?
|
|
(lambda (id*)
|
|
(or (null? id*)
|
|
(and (not (bound-id-member? (car id*) (cdr id*)))
|
|
(distinct-bound-ids? (cdr id*))))))
|
|
(define bound-id-member?
|
|
(lambda (id id*)
|
|
(and (pair? id*)
|
|
(or (bound-id=? id (car id*))
|
|
(bound-id-member? id (cdr id*))))))
|
|
(define self-evaluating?
|
|
(lambda (x)
|
|
(or (number? x) (string? x) (char? x) (boolean? x))))
|
|
(define stx->datum
|
|
(lambda (x)
|
|
(strip x '())))
|
|
(define extend-env
|
|
(lambda (lab b r)
|
|
(cons (cons lab b) r)))
|
|
(define extend-env*
|
|
(lambda (lab* b* r)
|
|
(append (map cons lab* b*) r)))
|
|
(define cons-id
|
|
(lambda (kwd kwd*)
|
|
(if (id? kwd)
|
|
(cons kwd kwd*)
|
|
kwd*)))
|
|
(define strip
|
|
(lambda (x m*)
|
|
(if (top-marked? m*)
|
|
x
|
|
(let f ([x x])
|
|
(cond
|
|
[(stx? x) (strip (stx-expr x) (stx-mark* x))]
|
|
[(pair? x)
|
|
(let ([a (f (car x))] [d (f (cdr x))])
|
|
(if (and (eq? a (car x)) (eq? d (cdr x)))
|
|
x
|
|
(cons a d)))]
|
|
[(vector? x)
|
|
(let ([old (vector->list x)])
|
|
(let ([new (map f old)])
|
|
(if (andmap eq? old new)
|
|
x
|
|
(list->vector new))))]
|
|
[else x])))))
|
|
(define id->label
|
|
(lambda (id)
|
|
(let ([sym (id->sym id)])
|
|
(let search ([subst* (stx-subst* id)] [mark* (stx-mark* id)])
|
|
(cond
|
|
[(null? subst*) #f]
|
|
[(eq? (car subst*) 'shift)
|
|
(search (cdr subst*) (cdr mark*))]
|
|
[else
|
|
(let ([rib (car subst*)])
|
|
(let f ([sym* (rib-sym* rib)]
|
|
[mark** (rib-mark** rib)]
|
|
[label* (rib-label* rib)])
|
|
(cond
|
|
[(null? sym*) (search (cdr subst*) mark*)]
|
|
[(and (eq? (car sym*) sym)
|
|
(same-marks? (car mark**) mark*))
|
|
(car label*)]
|
|
[else (f (cdr sym*) (cdr mark**) (cdr label*))])))])))))
|
|
(define label->binding
|
|
(lambda (x r)
|
|
(cond
|
|
[(not x) (cons 'unbound #f)]
|
|
[(assq x r) => cdr]
|
|
[(imported-label->binding x)]
|
|
[else (cons 'displaced-lexical #f)])))
|
|
(define make-binding cons)
|
|
(define binding-type car)
|
|
(define binding-value cdr)
|
|
(define syntax-type
|
|
(lambda (e r)
|
|
(cond
|
|
[(id? e)
|
|
(let ([id e])
|
|
(let* ([label (id->label id)]
|
|
[b (label->binding label r)]
|
|
[type (binding-type b)])
|
|
(unless label
|
|
(stx-error e "unbound identifier"))
|
|
(case type
|
|
[(lexical core-prim macro global)
|
|
(values type (binding-value b) id)]
|
|
[else (values 'other #f #f)])))]
|
|
[(syntax-pair? e)
|
|
(let ([id (syntax-car e)])
|
|
(if (id? id)
|
|
(let* ([label (id->label id)]
|
|
[b (label->binding label r)]
|
|
[type (binding-type b)])
|
|
(case type
|
|
[(define define-syntax core-macro begin macro module set!)
|
|
(values type (binding-value b) id)]
|
|
[else
|
|
(values 'call #f #f)]))
|
|
(values 'call #f #f)))]
|
|
[else (let ([d (strip e '())])
|
|
(if (self-evaluating? d)
|
|
(values 'constant d #f)
|
|
(values 'other #f #f)))])))
|
|
(define-syntax stx-error
|
|
(lambda (x)
|
|
(syntax-case x ()
|
|
[(_ stx) #'(error 'chi "invalid syntax ~s" (strip stx '()))]
|
|
[(_ stx msg) #'(error 'chi "~a: ~s" msg (strip stx '()))])))
|
|
(define sanitize-binding
|
|
(lambda (x)
|
|
(cond
|
|
[(procedure? x) (cons 'macro x)]
|
|
[(and (pair? x) (eq? (car x) 'macro!) (procedure? (cdr x)))
|
|
x]
|
|
[(and (pair? x) (eq? (car x) '$rtd)) x]
|
|
[else (error 'expand "invalid transformer ~s" x)])))
|
|
(define make-eval-transformer
|
|
(lambda (x)
|
|
(sanitize-binding (eval-core x))))
|
|
(module (syntax-match)
|
|
(define-syntax syntax-match-test
|
|
(lambda (ctx)
|
|
(define dots?
|
|
(lambda (x)
|
|
(and (identifier? x)
|
|
(free-identifier=? x #'(... ...)))))
|
|
(define free-identifier-member?
|
|
(lambda (x ls)
|
|
(and (ormap (lambda (y) (free-identifier=? x y)) ls) #t)))
|
|
(define f
|
|
(lambda (ctx lits)
|
|
(syntax-case ctx ()
|
|
[id (identifier? #'id)
|
|
(if (free-identifier-member? #'id lits)
|
|
#'(lambda (x) (and (id? x) (free-id=? x (scheme-stx 'id))))
|
|
#'(lambda (x) #t))]
|
|
[(pat dots) (dots? #'dots)
|
|
(with-syntax ([p (f #'pat lits)])
|
|
#'(lambda (x)
|
|
(and (syntax-list? x)
|
|
(andmap p (syntax->list x)))))]
|
|
[(pat dots . last) (dots? #'dots)
|
|
(with-syntax ([p (f #'pat lits)] [l (f #'last lits)])
|
|
#'(lambda (x)
|
|
(let loop ([x x])
|
|
(cond
|
|
[(syntax-pair? x)
|
|
(and (p (syntax-car x))
|
|
(loop (syntax-cdr x)))]
|
|
[else (l x)]))))]
|
|
[(a . d)
|
|
(with-syntax ([pa (f #'a lits)] [pd (f #'d lits)])
|
|
#'(lambda (x)
|
|
(and (syntax-pair? x)
|
|
(pa (syntax-car x))
|
|
(pd (syntax-cdr x)))))]
|
|
[#(pats ...)
|
|
(with-syntax ([p (f #'(pats ...) lits)])
|
|
#'(lambda (x)
|
|
(and (syntax-vector? x)
|
|
(p (syntax-vector->list x)))))]
|
|
[datum
|
|
#'(lambda (x)
|
|
(equal? (strip x '()) 'datum))])))
|
|
(syntax-case ctx ()
|
|
[(_ x (lits ...) [pat code code* ...])
|
|
(with-syntax ([pat-code (f #'pat #'(lits ...))])
|
|
#'(pat-code x))])))
|
|
(define-syntax syntax-match-conseq
|
|
(lambda (ctx)
|
|
(define free-identifier-member?
|
|
(lambda (x ls)
|
|
(and (ormap (lambda (y) (free-identifier=? x y)) ls) #t)))
|
|
(define dots?
|
|
(lambda (x)
|
|
(and (identifier? x)
|
|
(free-identifier=? x #'(... ...)))))
|
|
(define f
|
|
(lambda (stx lits)
|
|
(syntax-case stx ()
|
|
[id (identifier? #'id)
|
|
(if (free-identifier-member? #'id lits)
|
|
(values '() #'(lambda (x) (dont-call-me)))
|
|
(values (list #'id) #'(lambda (x) x)))]
|
|
[(pat dots) (dots? #'dots)
|
|
(let-values ([(vars extractor) (f #'pat lits)])
|
|
(cond
|
|
[(null? vars)
|
|
(values '() #'(lambda (x) (dont-call-me)))]
|
|
[else
|
|
(values vars
|
|
(with-syntax ([(vars ...) vars]
|
|
[ext extractor]
|
|
[(t* ...) (generate-temporaries vars)])
|
|
#'(lambda (x)
|
|
(let f ([x x] [vars '()] ...)
|
|
(cond
|
|
[(syntax-null? x)
|
|
(values (reverse vars) ...)]
|
|
[else
|
|
(let-values ([(t* ...) (ext (syntax-car x))])
|
|
(f (syntax-cdr x)
|
|
(cons t* vars)
|
|
...))])))))]))]
|
|
[(pat dots . last) (dots? #'dots)
|
|
(let-values ([(pvars pext) (f #'pat lits)])
|
|
(let-values ([(lvars lext) (f #'last lits)])
|
|
(cond
|
|
[(and (null? pvars) (null? lvars))
|
|
(values '() #'(lambda (x) (dont-call-me)))]
|
|
[(null? lvars)
|
|
(values pvars
|
|
(with-syntax ([(pvars ...) pvars]
|
|
[(t* ...) (generate-temporaries pvars)]
|
|
[pext pext])
|
|
#'(lambda (x)
|
|
(let loop ([x x] [pvars '()] ...)
|
|
(cond
|
|
[(syntax-pair? x)
|
|
(let-values ([(t* ...) (pext (syntax-car x))])
|
|
(loop (syntax-cdr x)
|
|
(cons t* pvars) ...))]
|
|
[else
|
|
(values (reverse pvars) ...)])))))]
|
|
[(null? pvars)
|
|
(values lvars
|
|
(with-syntax ([lext lext])
|
|
#'(let loop ([x x])
|
|
(cond
|
|
[(syntax-pair? x) (loop (syntax-cdr x))]
|
|
[else (lext x)]))))]
|
|
[else
|
|
(values (append pvars lvars)
|
|
(with-syntax ([(pvars ...) pvars]
|
|
[(t* ...) (generate-temporaries pvars)]
|
|
[(lvars ...) lvars]
|
|
[lext lext]
|
|
[pext pext])
|
|
#'(lambda (x)
|
|
(let loop ([x x] [pvars '()] ...)
|
|
(cond
|
|
[(syntax-pair? x)
|
|
(let-values ([(t* ...) (pext (syntax-car x))])
|
|
(loop (syntax-cdr x)
|
|
(cons t* pvars) ...))]
|
|
[else
|
|
(let-values ([(lvars ...) (lext x)])
|
|
(values (reverse pvars) ...
|
|
lvars ...))])))))])))]
|
|
[(a . d)
|
|
(let-values ([(avars aextractor) (f #'a lits)])
|
|
(let-values ([(dvars dextractor) (f #'d lits)])
|
|
(cond
|
|
[(and (null? avars) (null? dvars))
|
|
(values '() #'(lambda (x) (dot-call-me)))]
|
|
[(null? avars)
|
|
(values dvars
|
|
(with-syntax ([d dextractor])
|
|
#'(lambda (x) (d (syntax-cdr x)))))]
|
|
[(null? dvars)
|
|
(values avars
|
|
(with-syntax ([a aextractor])
|
|
#'(lambda (x) (a (syntax-car x)))))]
|
|
[else
|
|
(values (append avars dvars)
|
|
(with-syntax ([(avars ...) avars]
|
|
[(dvars ...) dvars]
|
|
[a aextractor]
|
|
[d dextractor])
|
|
#'(lambda (x)
|
|
(let-values ([(avars ...) (a (syntax-car x))])
|
|
(let-values ([(dvars ...) (d (syntax-cdr x))])
|
|
(values avars ... dvars ...))))))])))]
|
|
[#(pats ...)
|
|
(let-values ([(vars extractor) (f #'(pats ...) lits)])
|
|
(cond
|
|
[(null? vars) (values '() #f)]
|
|
[else
|
|
(values vars
|
|
(with-syntax ([extractor extractor])
|
|
#'(lambda (x)
|
|
(extractor (syntax-vector->list x)))))]))]
|
|
[datum
|
|
(values '() #'(lambda (x) (dot-call-me)))])))
|
|
(syntax-case ctx ()
|
|
[(_ x (lits ...) [pat code code* ...])
|
|
(let-values ([(vars extractor)
|
|
(f #'pat #'(lits ...))])
|
|
(with-syntax ([e extractor] [(vs ...) vars])
|
|
(case (length vars)
|
|
[(0) #'(begin code code* ...)]
|
|
[(1) #'(let ([vs ... (e x)]) code code* ...)]
|
|
[else #'(let-values ([(vs ...) (e x)]) code code* ...)])))])))
|
|
(define-syntax syntax-match
|
|
(lambda (x)
|
|
(syntax-case x ()
|
|
[(_ expr (lits ...)) #'(stx-error expr)]
|
|
[(_ expr (lits ...) cls cls* ...)
|
|
#'(let ([t expr])
|
|
(if (syntax-match-test t (lits ...) cls)
|
|
(syntax-match-conseq t (lits ...) cls)
|
|
(syntax-match t (lits ...) cls* ...)))]))))
|
|
(define parse-define
|
|
(lambda (x)
|
|
(syntax-match x ()
|
|
[(_ (id . fmls) b b* ...)
|
|
(if (id? id)
|
|
(values id
|
|
(cons 'defun (cons fmls (cons b b*))))
|
|
(stx-error x))]
|
|
[(_ id val)
|
|
(if (id? id)
|
|
(values id (cons 'expr val))
|
|
(stx-error x))])))
|
|
(define parse-define-syntax
|
|
(lambda (x)
|
|
(syntax-match x ()
|
|
[(_ id val)
|
|
(if (id? id)
|
|
(values id val)
|
|
(stx-error x))])))
|
|
(define scheme-stx
|
|
(lambda (sym)
|
|
(let-values ([(subst env)
|
|
(library-subst/env
|
|
(find-library-by-name '(scheme)))])
|
|
(cond
|
|
[(assq sym subst) =>
|
|
(lambda (x)
|
|
(let ([name (car x)] [label (cdr x)])
|
|
(add-subst
|
|
(make-rib (list name) (list top-mark*) (list label))
|
|
(stx sym top-mark* '()))))]
|
|
[else (stx sym top-mark* '())]))))
|
|
;;; macros
|
|
(define add-lexicals
|
|
(lambda (lab* lex* r)
|
|
(append (map (lambda (lab lex)
|
|
(cons lab (cons 'lexical lex)))
|
|
lab* lex*)
|
|
r)))
|
|
(define let-values-transformer ;;; go away
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ ([(fml** ...) rhs*] ...) b b* ...)
|
|
(let ([rhs* (chi-expr* rhs* r mr)])
|
|
(let ([lex** (map (lambda (ls) (map gen-lexical ls)) fml**)]
|
|
[lab** (map (lambda (ls) (map gen-label ls)) fml**)])
|
|
(let ([fml* (apply append fml**)]
|
|
[lab* (apply append lab**)]
|
|
[lex* (apply append lex**)])
|
|
(let f ([lex** lex**] [rhs* rhs*])
|
|
(cond
|
|
[(null? lex**)
|
|
(chi-internal
|
|
(add-subst
|
|
(make-full-rib fml* lab*)
|
|
(cons b b*))
|
|
(add-lexicals lab* lex* r)
|
|
mr)]
|
|
[else
|
|
(build-application no-source
|
|
(build-primref no-source 'call-with-values)
|
|
(list
|
|
(build-lambda no-source '() (car rhs*))
|
|
(build-lambda no-source (car lex**)
|
|
(f (cdr lex**) (cdr rhs*)))))])))))])))
|
|
(define letrec-transformer
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ ([lhs* rhs*] ...) b b* ...)
|
|
(if (not (valid-bound-ids? lhs*))
|
|
(stx-error e)
|
|
(let ([lex* (map gen-lexical lhs*)]
|
|
[lab* (map gen-label lhs*)])
|
|
(let ([rib (make-full-rib lhs* lab*)]
|
|
[r (add-lexicals lab* lex* r)])
|
|
(let ([body (chi-internal
|
|
(add-subst rib (cons b b*))
|
|
r mr)]
|
|
[rhs* (chi-expr*
|
|
(map (lambda (x)
|
|
(add-subst rib x))
|
|
rhs*)
|
|
r mr)])
|
|
(build-letrec no-source
|
|
lex* rhs* body)))))])))
|
|
(define type-descriptor-transformer
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ id)
|
|
(unless (id? id) (stx-error e))
|
|
(let* ([lab (id->label id)]
|
|
[b (label->binding lab r)]
|
|
[type (binding-type b)])
|
|
(unless lab (stx-error e "unbound identifier"))
|
|
(case type
|
|
[($rtd)
|
|
(build-data no-source (binding-value b))]
|
|
[else (stx-error e "invalid type")]))])))
|
|
(define when-transformer ;;; go away
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ test e e* ...)
|
|
(build-conditional no-source
|
|
(chi-expr test r mr)
|
|
(build-sequence no-source
|
|
(chi-expr* (cons e e*) r mr))
|
|
(build-void))])))
|
|
(define unless-transformer ;;; go away
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ test e e* ...)
|
|
(build-conditional no-source
|
|
(chi-expr test r mr)
|
|
(build-void)
|
|
(build-sequence no-source
|
|
(chi-expr* (cons e e*) r mr)))])))
|
|
(define if-transformer
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ e0 e1 e2)
|
|
(build-conditional no-source
|
|
(chi-expr e0 r mr)
|
|
(chi-expr e1 r mr)
|
|
(chi-expr e2 r mr))]
|
|
[(_ e0 e1)
|
|
(build-conditional no-source
|
|
(chi-expr e0 r mr)
|
|
(chi-expr e1 r mr)
|
|
(build-void))])))
|
|
(define case-transformer ;;; go away
|
|
(lambda (e r mr)
|
|
(define build-one
|
|
(lambda (t cls rest)
|
|
(syntax-match cls ()
|
|
[((d* ...) e e* ...)
|
|
(build-conditional no-source
|
|
(build-application no-source
|
|
(build-primref no-source 'memv)
|
|
(list t (build-data no-source (strip d* '()))))
|
|
(build-sequence no-source
|
|
(chi-expr* (cons e e*) r mr))
|
|
rest)]
|
|
[else (stx-error e)])))
|
|
(define build-last
|
|
(lambda (t cls)
|
|
(syntax-match cls ()
|
|
[((d* ...) e e* ...)
|
|
(build-one t cls (build-void))]
|
|
[(else-kwd x x* ...)
|
|
(if (and (id? else-kwd)
|
|
(free-id=? else-kwd (scheme-stx 'else)))
|
|
(build-sequence no-source
|
|
(chi-expr* (cons x x*) r mr))
|
|
(stx-error e))]
|
|
[else (stx-error e)])))
|
|
(syntax-match e ()
|
|
[(_ expr)
|
|
(build-sequence no-source
|
|
(list (chi-expr expr r mr) (build-void)))]
|
|
[(_ expr cls cls* ...)
|
|
(let ([t (gen-lexical 't)])
|
|
(build-let no-source
|
|
(list t) (list (chi-expr expr r mr))
|
|
(let f ([cls cls] [cls* cls*])
|
|
(cond
|
|
[(null? cls*) (build-last t cls)]
|
|
[else
|
|
(build-one t cls
|
|
(f (car cls*) (cdr cls*)))]))))])))
|
|
(define quote-transformer
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ datum) (build-data no-source (strip datum '()))])))
|
|
(define case-lambda-transformer
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ [fmls* b* b** ...] ...)
|
|
(let-values ([(fmls* body*)
|
|
(chi-lambda-clause* fmls*
|
|
(map cons b* b**) r mr)])
|
|
(build-case-lambda no-source fmls* body*))])))
|
|
(define lambda-transformer
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ fmls b b* ...)
|
|
(let-values ([(fmls body)
|
|
(chi-lambda-clause fmls
|
|
(cons b b*) r mr)])
|
|
(build-lambda no-source fmls body))])))
|
|
(define bless
|
|
(lambda (x)
|
|
(stx
|
|
(let f ([x x])
|
|
(cond
|
|
[(pair? x) (cons (f (car x)) (f (cdr x)))]
|
|
[(symbol? x) (scheme-stx x)]
|
|
[else x]))
|
|
'() '())))
|
|
(define with-syntax-macro
|
|
(lambda (e)
|
|
(syntax-match e ()
|
|
[(_ ([fml* expr*] ...) b b* ...)
|
|
(bless
|
|
`(syntax-case (list . ,expr*) ()
|
|
[,fml* (begin ,b . ,b*)]))])))
|
|
(define let-macro
|
|
(lambda (stx)
|
|
(syntax-match stx ()
|
|
[(_ ([lhs* rhs*] ...) b b* ...)
|
|
(if (valid-bound-ids? lhs*)
|
|
(bless `((lambda ,lhs* ,b . ,b*) . ,rhs*))
|
|
(stx-error stx "invalid syntax"))]
|
|
[(_ f ([lhs* rhs*] ...) b b* ...)
|
|
(if (and (id? f) (valid-bound-ids? lhs*))
|
|
(bless `(letrec ([,f (lambda ,lhs* ,b . ,b*)])
|
|
(,f . ,rhs*)))
|
|
(stx-error stx "invalid syntax"))])))
|
|
(define let*-macro
|
|
(lambda (stx)
|
|
(syntax-match stx ()
|
|
[(_ ([lhs* rhs*] ...) b b* ...)
|
|
(if (andmap id? lhs*)
|
|
(bless
|
|
(let f ([x* (map list lhs* rhs*)])
|
|
(cond
|
|
[(null? x*) `(let () ,b . ,b*)]
|
|
[else `(let (,(car x*)) ,(f (cdr x*)))])))
|
|
(stx-error stx "invalid bindings"))])))
|
|
(define or-macro
|
|
(lambda (stx)
|
|
(syntax-match stx ()
|
|
[(_) #f]
|
|
[(_ e e* ...)
|
|
(bless
|
|
(let f ([e e] [e* e*])
|
|
(cond
|
|
[(null? e*) `(begin #f ,e)]
|
|
[else
|
|
`(let ([t ,e])
|
|
(if t t ,(f (car e*) (cdr e*))))])))])))
|
|
(define and-macro
|
|
(lambda (stx)
|
|
(syntax-match stx ()
|
|
[(_) #t]
|
|
[(_ e e* ...)
|
|
(bless
|
|
(let f ([e e] [e* e*])
|
|
(cond
|
|
[(null? e*) `(begin #f ,e)]
|
|
[else `(if ,e ,(f (car e*) (cdr e*)) #f)])))])))
|
|
(define cond-macro
|
|
(lambda (stx)
|
|
(syntax-match stx ()
|
|
[(_ cls cls* ...)
|
|
(bless
|
|
(let f ([cls cls] [cls* cls*])
|
|
(cond
|
|
[(null? cls*)
|
|
(syntax-match cls (else =>)
|
|
[(else e e* ...) `(begin ,e . ,e*)]
|
|
[(e => p) `(let ([t ,e]) (if t (,p t) (void)))]
|
|
[(e) `(or ,e (void))]
|
|
[(e e* ...) `(if ,e (begin . ,e*) (void))]
|
|
[_ (stx-error stx "invalid last clause")])]
|
|
[else
|
|
(syntax-match cls (else =>)
|
|
[(else e e* ...) (stx-error stx "incorrect position of keyword else")]
|
|
[(e => p) `(let ([t ,e]) (if t (,p t) ,(f (car cls*) (cdr cls*))))]
|
|
[(e) `(or ,e ,(f (car cls*) (cdr cls*)))]
|
|
[(e e* ...) `(if ,e (begin . ,e*) ,(f (car cls*) (cdr cls*)))]
|
|
[_ (stx-error stx "invalid last clause")])])))])))
|
|
(define include-macro
|
|
(lambda (e)
|
|
(syntax-match e ()
|
|
[(id filename)
|
|
(let ([filename (stx->datum filename)])
|
|
(unless (string? filename) (stx-error e))
|
|
(with-input-from-file filename
|
|
(lambda ()
|
|
(let f ([ls '()])
|
|
(let ([x (read)])
|
|
(cond
|
|
[(eof-object? x)
|
|
(cons (bless 'begin)
|
|
(datum->stx id (reverse ls)))]
|
|
[else (f (cons x ls))]))))))])))
|
|
(define syntax-rules-macro
|
|
(lambda (e)
|
|
(syntax-match e ()
|
|
[(_ (lits ...)
|
|
[pat* tmp*] ...)
|
|
(unless (andmap
|
|
(lambda (x)
|
|
(and (id? x)
|
|
(not (free-id=? x (scheme-stx '...)))
|
|
(not (free-id=? x (scheme-stx '_)))))
|
|
lits)
|
|
(stx-error e "invalid literals"))
|
|
(bless `(lambda (x)
|
|
(syntax-case x ,lits
|
|
,@(map (lambda (pat tmp)
|
|
`[,pat (syntax ,tmp)])
|
|
pat* tmp*))))])))
|
|
(define quasiquote-macro
|
|
(let ()
|
|
(define-syntax app
|
|
(syntax-rules (quote)
|
|
[(_ 'x arg* ...)
|
|
(list (scheme-stx 'x) arg* ...)]))
|
|
(define-syntax app*
|
|
(syntax-rules (quote)
|
|
[(_ 'x arg* ... last)
|
|
(list* (scheme-stx 'x) arg* ... last)]))
|
|
(define quasilist*
|
|
(lambda (x y)
|
|
(let f ((x x))
|
|
(if (null? x) y (quasicons (car x) (f (cdr x)))))))
|
|
(define quasicons
|
|
(lambda (x y)
|
|
(syntax-match y (quote list)
|
|
[(quote dy)
|
|
(syntax-match x (quote)
|
|
[(quote dx) (app 'quote (cons dx dy))]
|
|
[_
|
|
(syntax-match dy ()
|
|
[() (app 'list x)]
|
|
[_ (app 'cons x y)])])]
|
|
[(list stuff ...)
|
|
(app* 'list x stuff)]
|
|
[_ (app 'cons x y)])))
|
|
(define quasiappend
|
|
(lambda (x y)
|
|
(let ([ls (let f ((x x))
|
|
(if (null? x)
|
|
(syntax-match y (quote)
|
|
[(quote ()) '()]
|
|
[_ (list y)])
|
|
(syntax-match (car x) (quote)
|
|
[(quote ()) (f (cdr x))]
|
|
[_ (cons (car x) (f (cdr x)))])))])
|
|
(cond
|
|
[(null? ls) (app 'quote '())]
|
|
[(null? (cdr ls)) (car ls)]
|
|
[else (app* 'append ls)]))))
|
|
(define quasivector
|
|
(lambda (x)
|
|
(let ((pat-x x))
|
|
(syntax-match pat-x (quote)
|
|
[(quote (x* ...)) (app 'quote (list->vector x*))]
|
|
[_ (let f ((x x) (k (lambda (ls) (app* 'vector ls))))
|
|
(syntax-match x (quote list cons)
|
|
[(quote (x* ...))
|
|
(k (map (lambda (x) (app 'quote x)) x*))]
|
|
[(list x* ...)
|
|
(k x*)]
|
|
[(cons x y)
|
|
(f y (lambda (ls) (k (cons x ls))))]
|
|
[_ (app 'list->vector pat-x)]))]))))
|
|
(define vquasi
|
|
(lambda (p lev)
|
|
(syntax-match p ()
|
|
[(p . q)
|
|
(syntax-match p (unquote unquote-splicing)
|
|
[(unquote p ...)
|
|
(if (= lev 0)
|
|
(quasilist* p (vquasi q lev))
|
|
(quasicons
|
|
(quasicons (app 'quote 'unquote)
|
|
(quasi p (- lev 1)))
|
|
(vquasi q lev)))]
|
|
[(unquote-splicing p ...)
|
|
(if (= lev 0)
|
|
(quasiappend p (vquasi q lev))
|
|
(quasicons
|
|
(quasicons
|
|
(app 'quote 'unquote-splicing)
|
|
(quasi p (- lev 1)))
|
|
(vquasi q lev)))]
|
|
[p (quasicons (quasi p lev) (vquasi q lev))])]
|
|
[() (app 'quote '())])))
|
|
(define quasi
|
|
(lambda (p lev)
|
|
(syntax-match p (unquote unquote-splicing quasiquote)
|
|
[(unquote p)
|
|
(if (= lev 0)
|
|
p
|
|
(quasicons (app 'quote 'unquote) (quasi (list p) (- lev 1))))]
|
|
[((unquote p ...) . q)
|
|
(if (= lev 0)
|
|
(quasilist* p (quasi q lev))
|
|
(quasicons
|
|
(quasicons (app 'quote 'unquote) (quasi p (- lev 1)))
|
|
(quasi q lev)))]
|
|
[((unquote-splicing p ...) . q)
|
|
(if (= lev 0)
|
|
(quasiappend p (quasi q lev))
|
|
(quasicons
|
|
(quasicons
|
|
(app 'quote 'unquote-splicing)
|
|
(quasi p (- lev 1)))
|
|
(quasi q lev)))]
|
|
[(quasiquote p)
|
|
(quasicons (app 'quote 'quasiquote) (quasi (list p) (+ lev 1)))]
|
|
[(p . q) (quasicons (quasi p lev) (quasi q lev))]
|
|
[#(x ...) (quasivector (vquasi x lev))]
|
|
[p (app 'quote p)])))
|
|
(lambda (x)
|
|
(syntax-match x ()
|
|
[(_ e) (quasi e 0)]))))
|
|
(define define-record-macro
|
|
(lambda (e)
|
|
(define enumerate
|
|
(lambda (ls)
|
|
(let f ([i 0] [ls ls])
|
|
(cond
|
|
[(null? ls) '()]
|
|
[else (cons i (f (add1 i) (cdr ls)))]))))
|
|
(define mkid
|
|
(lambda (id str)
|
|
(datum->stx id (string->symbol str))))
|
|
(syntax-match e ()
|
|
[(_ name (field* ...))
|
|
(let* ([namestr (symbol->string (id->sym name))]
|
|
[fields (map id->sym field*)]
|
|
[fieldstr* (map symbol->string fields)]
|
|
[rtd (datum->stx name (make-record-type namestr fields))]
|
|
[constr (mkid name (format "make-~a" namestr))]
|
|
[pred (mkid name (format "~a?" namestr))]
|
|
[i* (enumerate field*)]
|
|
[getters
|
|
(map (lambda (x)
|
|
(mkid name (format "~a-~a" namestr x)))
|
|
fieldstr*)]
|
|
[setters
|
|
(map (lambda (x)
|
|
(mkid name (format "set-~a-~a!" namestr x)))
|
|
fieldstr*)])
|
|
(bless
|
|
`(begin
|
|
(define-syntax ,name (cons '$rtd ',rtd))
|
|
(define ,constr
|
|
(lambda ,field*
|
|
($record ',rtd ,@field*)))
|
|
(define ,pred
|
|
(lambda (x) ($record/rtd? x ',rtd)))
|
|
,@(map (lambda (getter i)
|
|
`(define ,getter
|
|
(lambda (x)
|
|
(if ($record/rtd? x ',rtd)
|
|
($record-ref x ,i)
|
|
(error ',getter
|
|
"~s is not a record of type ~s"
|
|
x ',rtd)))))
|
|
getters i*)
|
|
,@(map (lambda (setter i)
|
|
`(define ,setter
|
|
(lambda (x v)
|
|
(if ($record/rtd? x ',rtd)
|
|
($record-set! x ,i v)
|
|
(error ',setter
|
|
"~s is not a record of type ~s"
|
|
x ',rtd)))))
|
|
setters i*))))])))
|
|
(define parameterize-transformer ;;; go away
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ () b b* ...)
|
|
(chi-internal (cons b b*) r mr)]
|
|
[(_ ([olhs* orhs*] ...) b b* ...)
|
|
(let ([lhs* (map (lambda (x) (gen-lexical 'lhs)) olhs*)]
|
|
[rhs* (map (lambda (x) (gen-lexical 'rhs)) olhs*)]
|
|
[t* (map (lambda (x) (gen-lexical 't)) olhs*)]
|
|
[swap (gen-lexical 'swap)])
|
|
(build-let no-source
|
|
(append lhs* rhs*)
|
|
(append (chi-expr* olhs* r mr) (chi-expr* orhs* r mr))
|
|
(build-let no-source
|
|
(list swap)
|
|
(list (build-lambda no-source '()
|
|
(build-sequence no-source
|
|
(map (lambda (t lhs rhs)
|
|
(build-let no-source
|
|
(list t)
|
|
(list (build-application no-source
|
|
(build-lexical-reference no-source lhs)
|
|
'()))
|
|
(build-sequence no-source
|
|
(list (build-application no-source
|
|
(build-lexical-reference no-source lhs)
|
|
(list (build-lexical-reference no-source rhs)))
|
|
(build-lexical-assignment no-source rhs
|
|
(build-lexical-reference no-source t))))))
|
|
t* lhs* rhs*))))
|
|
(build-application no-source
|
|
(build-primref no-source 'dynamic-wind)
|
|
(list (build-lexical-reference no-source swap)
|
|
(build-lambda no-source '()
|
|
(chi-internal (cons b b*) r mr))
|
|
(build-lexical-reference no-source swap))))))])))
|
|
(define foreign-call-transformer
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ name arg* ...)
|
|
(build-foreign-call no-source
|
|
(chi-expr name r mr)
|
|
(chi-expr* arg* r mr))])))
|
|
;; p in pattern: matches:
|
|
;; () empty list
|
|
;; _ anything (no binding created)
|
|
;; any anything
|
|
;; (p1 . p2) pair
|
|
;; #(free-id <key>) <key> with free-identifier=?
|
|
;; each-any any proper list
|
|
;; #(each p) (p*)
|
|
;; #(each+ p1 (p2_1 ... p2_n) p3) (p1* (p2_n ... p2_1) . p3)
|
|
;; #(vector p) #(x ...) if p matches (x ...)
|
|
;; #(atom <object>) <object> with "equal?"
|
|
(define convert-pattern
|
|
; returns syntax-dispatch pattern & ids
|
|
(lambda (pattern keys)
|
|
(define cvt*
|
|
(lambda (p* n ids)
|
|
(if (null? p*)
|
|
(values '() ids)
|
|
(let-values (((y ids) (cvt* (cdr p*) n ids)))
|
|
(let-values (((x ids) (cvt (car p*) n ids)))
|
|
(values (cons x y) ids))))))
|
|
(define id-dots?
|
|
(lambda (x)
|
|
(and (syntax-pair? x)
|
|
(let ([d (syntax-cdr x)])
|
|
(and (syntax-pair? d)
|
|
(syntax-null? (syntax-cdr d))
|
|
(ellipsis? (syntax-car d)))))))
|
|
(define id-dots-id
|
|
(lambda (x) (syntax-car x)))
|
|
(define syntax-foo?
|
|
(lambda (x)
|
|
(and (syntax-pair? x)
|
|
(let ((d (syntax-cdr x)))
|
|
(and (syntax-pair? d)
|
|
(ellipsis? (syntax-car d)))))))
|
|
(define syntax-foo-z
|
|
(lambda (x)
|
|
(let f ([x (syntax-cdr (syntax-cdr x))])
|
|
(cond
|
|
((syntax-pair? x) (f (syntax-cdr x)))
|
|
(else x)))))
|
|
(define syntax-foo-ys
|
|
(lambda (x)
|
|
(let f ([x (syntax-cdr (syntax-cdr x))])
|
|
(cond
|
|
[(syntax-pair? x)
|
|
(cons (syntax-car x) (f (syntax-cdr x)))]
|
|
[else '()]))))
|
|
(define syntax-foo-x
|
|
(lambda (x) (syntax-car x)))
|
|
(define cvt
|
|
(lambda (p n ids)
|
|
(cond
|
|
[(not (id? p))
|
|
(cond
|
|
[(id-dots? p)
|
|
(let-values ([(p ids) (cvt (id-dots-id p) (+ n 1) ids)])
|
|
(values
|
|
(if (eq? p 'any) 'each-any (vector 'each p))
|
|
ids))]
|
|
[(syntax-foo? p) ; (x dots y ... . z)
|
|
(let-values ([(z ids) (cvt (syntax-foo-z p) n ids)])
|
|
(let-values ([(y ids) (cvt* (syntax-foo-ys p) n ids)])
|
|
(let-values ([(x ids) (cvt (syntax-foo-x p) (+ n 1) ids)])
|
|
(values (vector 'each+ x (reverse y) z) ids))))]
|
|
[(syntax-pair? p)
|
|
(let-values ([(y ids) (cvt (syntax-cdr p) n ids)])
|
|
(let-values ([(x ids) (cvt (syntax-car p) n ids)])
|
|
(values (cons x y) ids)))]
|
|
[(syntax-null? p) (values '() ids)]
|
|
[(syntax-vector? p)
|
|
(let-values ([(p ids) (cvt (syntax-vector->list p) n ids)])
|
|
(values (vector 'vector p) ids))]
|
|
[else (values (vector 'atom (strip p '())) ids)])]
|
|
[(bound-id-member? p keys)
|
|
(values (vector 'free-id p) ids)]
|
|
[(free-id=? p (scheme-stx '_))
|
|
(values '_ ids)]
|
|
[else (values 'any (cons (cons p n) ids))])))
|
|
(cvt pattern 0 '())))
|
|
(define syntax-dispatch
|
|
(lambda (e p)
|
|
(define match-each
|
|
(lambda (e p m* s*)
|
|
(cond
|
|
((pair? e)
|
|
(let ((first (match (car e) p m* s* '())))
|
|
(and first
|
|
(let ((rest (match-each (cdr e) p m* s*)))
|
|
(and rest (cons first rest))))))
|
|
((null? e) '())
|
|
((stx? e)
|
|
(let-values (((m* s*) (join-wraps m* s* e)))
|
|
(match-each (stx-expr e) p m* s*)))
|
|
(else #f))))
|
|
(define match-each+
|
|
(lambda (e x-pat y-pat z-pat m* s* r)
|
|
(let f ((e e) (m* m*) (s* s*))
|
|
(cond
|
|
((pair? e)
|
|
(let-values (((xr* y-pat r) (f (cdr e) m* s*)))
|
|
(if r
|
|
(if (null? y-pat)
|
|
(let ((xr (match (car e) x-pat m* s* '())))
|
|
(if xr
|
|
(values (cons xr xr*) y-pat r)
|
|
(values #f #f #f)))
|
|
(values
|
|
'()
|
|
(cdr y-pat)
|
|
(match (car e) (car y-pat) m* s* r)))
|
|
(values #f #f #f))))
|
|
((stx? e)
|
|
(let-values (((m* s*) (join-wraps m* s* e)))
|
|
(f (stx-expr e) m* s*)))
|
|
(else (values '() y-pat (match e z-pat m* s* r)))))))
|
|
(define match-each-any
|
|
(lambda (e m* s*)
|
|
(cond
|
|
((pair? e)
|
|
(let ((l (match-each-any (cdr e) m* s*)))
|
|
(and l (cons (stx (car e) m* s*) l))))
|
|
((null? e) '())
|
|
((stx? e)
|
|
(let-values (((m* s*) (join-wraps m* s* e)))
|
|
(match-each-any (stx-expr e) m* s*)))
|
|
(else #f))))
|
|
(define match-empty
|
|
(lambda (p r)
|
|
(cond
|
|
((null? p) r)
|
|
((eq? p '_) r)
|
|
((eq? p 'any) (cons '() r))
|
|
((pair? p) (match-empty (car p) (match-empty (cdr p) r)))
|
|
((eq? p 'each-any) (cons '() r))
|
|
(else
|
|
(case (vector-ref p 0)
|
|
((each) (match-empty (vector-ref p 1) r))
|
|
((each+)
|
|
(match-empty
|
|
(vector-ref p 1)
|
|
(match-empty
|
|
(reverse (vector-ref p 2))
|
|
(match-empty (vector-ref p 3) r))))
|
|
((free-id atom) r)
|
|
((vector) (match-empty (vector-ref p 1) r))
|
|
(else (error 'syntax-dispatch "invalid pattern" p)))))))
|
|
(define combine
|
|
(lambda (r* r)
|
|
(if (null? (car r*))
|
|
r
|
|
(cons (map car r*) (combine (map cdr r*) r)))))
|
|
(define match*
|
|
(lambda (e p m* s* r)
|
|
(cond
|
|
((null? p) (and (null? e) r))
|
|
((pair? p)
|
|
(and (pair? e)
|
|
(match (car e) (car p) m* s*
|
|
(match (cdr e) (cdr p) m* s* r))))
|
|
((eq? p 'each-any)
|
|
(let ((l (match-each-any e m* s*))) (and l (cons l r))))
|
|
(else
|
|
(case (vector-ref p 0)
|
|
((each)
|
|
(if (null? e)
|
|
(match-empty (vector-ref p 1) r)
|
|
(let ((r* (match-each e (vector-ref p 1) m* s*)))
|
|
(and r* (combine r* r)))))
|
|
((free-id)
|
|
(and (symbol? e)
|
|
(free-id=? (stx e m* s*) (vector-ref p 1))
|
|
r))
|
|
((each+)
|
|
(let-values (((xr* y-pat r)
|
|
(match-each+ e (vector-ref p 1)
|
|
(vector-ref p 2) (vector-ref p 3) m* s* r)))
|
|
(and r
|
|
(null? y-pat)
|
|
(if (null? xr*)
|
|
(match-empty (vector-ref p 1) r)
|
|
(combine xr* r)))))
|
|
((atom) (and (equal? (vector-ref p 1) (strip e m*)) r))
|
|
((vector)
|
|
(and (vector? e)
|
|
(match (vector->list e) (vector-ref p 1) m* s* r)))
|
|
(else (error 'syntax-dispatch "invalid pattern" p)))))))
|
|
(define match
|
|
(lambda (e p m* s* r)
|
|
(cond
|
|
((not r) #f)
|
|
((eq? p '_) r)
|
|
((eq? p 'any) (cons (stx e m* s*) r))
|
|
((stx? e)
|
|
(let-values (((m* s*) (join-wraps m* s* e)))
|
|
(match (stx-expr e) p m* s* r)))
|
|
(else (match* e p m* s* r)))))
|
|
(match e p '() '() '())))
|
|
(define ellipsis?
|
|
(lambda (x)
|
|
(and (id? x) (free-id=? x (scheme-stx '...)))))
|
|
(define syntax-case-transformer
|
|
(let ()
|
|
(define build-dispatch-call
|
|
(lambda (pvars expr y r mr)
|
|
(let ([ids (map car pvars)]
|
|
[levels (map cdr pvars)])
|
|
(let ([labels (map gen-label ids)]
|
|
[new-vars (map gen-lexical ids)])
|
|
(let ([body
|
|
(chi-expr
|
|
(add-subst (make-full-rib ids labels) expr)
|
|
(extend-env*
|
|
labels
|
|
(map (lambda (var level)
|
|
(make-binding 'syntax (cons var level)))
|
|
new-vars
|
|
(map cdr pvars))
|
|
r)
|
|
mr)])
|
|
(build-application no-source
|
|
(build-primref no-source 'apply)
|
|
(list (build-lambda no-source new-vars body) y)))))))
|
|
(define invalid-ids-error
|
|
(lambda (id* e class)
|
|
(let find ((id* id*) (ok* '()))
|
|
(if (null? id*)
|
|
(stx-error e) ; shouldn't happen
|
|
(if (id? (car id*))
|
|
(if (bound-id-member? (car id*) ok*)
|
|
(syntax-error (car id*) "duplicate " class)
|
|
(find (cdr id*) (cons (car id*) ok*)))
|
|
(syntax-error (car id*) "invalid " class))))))
|
|
(define gen-clause
|
|
(lambda (x keys clauses r mr pat fender expr)
|
|
(let-values (((p pvars) (convert-pattern pat keys)))
|
|
(cond
|
|
((not (distinct-bound-ids? (map car pvars)))
|
|
(invalid-ids-error (map car pvars) pat "pattern variable"))
|
|
((not (andmap (lambda (x) (not (ellipsis? (car x)))) pvars))
|
|
(stx-error pat "3misplaced ellipsis in syntax-case pattern"))
|
|
(else
|
|
(let ((y (gen-lexical 'tmp)))
|
|
(let ([test
|
|
(cond
|
|
[(eq? fender #t) y]
|
|
[else
|
|
(let ([call
|
|
(build-dispatch-call
|
|
pvars fender y r mr)])
|
|
(build-conditional no-source
|
|
(build-lexical-reference no-source y)
|
|
call
|
|
(build-data no-source #f)))])])
|
|
(let ([conseq
|
|
(build-dispatch-call pvars expr
|
|
(build-lexical-reference no-source y)
|
|
r mr)])
|
|
(let ([altern
|
|
(gen-syntax-case x keys clauses r mr)])
|
|
(build-application no-source
|
|
(build-lambda no-source (list y)
|
|
(build-conditional no-source test conseq altern))
|
|
(list
|
|
(build-application no-source
|
|
(build-primref no-source 'syntax-dispatch)
|
|
(list
|
|
(build-lexical-reference no-source x)
|
|
(build-data no-source p))))))))))))))
|
|
(define gen-syntax-case
|
|
(lambda (x keys clauses r mr)
|
|
(if (null? clauses)
|
|
(build-application no-source
|
|
(build-primref no-source 'syntax-error)
|
|
(list (build-lexical-reference no-source x)))
|
|
(syntax-match (car clauses) ()
|
|
[(pat expr)
|
|
(if (and (id? pat)
|
|
(not (bound-id-member? pat keys))
|
|
(not (ellipsis? pat)))
|
|
(if (free-id=? pat (scheme-stx '_))
|
|
(chi-expr expr r mr)
|
|
(let ([lab (gen-label pat)]
|
|
[lex (gen-lexical pat)])
|
|
(let ([body
|
|
(chi-expr
|
|
(add-subst
|
|
(make-full-rib (list pat) (list lab))
|
|
expr)
|
|
(extend-env lab
|
|
(make-binding 'syntax (cons lex 0))
|
|
r)
|
|
mr)])
|
|
(build-application no-source
|
|
(build-lambda no-source (list lex) body)
|
|
(list (build-lexical-reference no-source x))))))
|
|
(gen-clause x keys (cdr clauses) r mr pat #t expr))]
|
|
[(pat fender expr)
|
|
(gen-clause x keys (cdr clauses) r mr pat fender expr)]))))
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ expr (keys ...) clauses ...)
|
|
(unless (andmap (lambda (x) (and (id? x) (not (ellipsis? x)))) keys)
|
|
(stx-error e))
|
|
(let ((x (gen-lexical 'tmp)))
|
|
(let ([body (gen-syntax-case x keys clauses r mr)])
|
|
(build-application no-source
|
|
(build-lambda no-source (list x) body)
|
|
(list (chi-expr expr r mr)))))]))))
|
|
(define syntax-transformer
|
|
(let ()
|
|
(define match2
|
|
(lambda (e f? sk fk)
|
|
(if (syntax-list? e)
|
|
(let ((e (syntax->list e)))
|
|
(if (= (length e) 2)
|
|
(let ((e0 (car e)) (e1 (cadr e)))
|
|
(if (or (eq? f? #t) (f? e0 e1))
|
|
(sk e0 e1)
|
|
(fk)))
|
|
(fk)))
|
|
(fk))))
|
|
(define gen-syntax
|
|
(lambda (src e r maps ellipsis? vec?)
|
|
(if (id? e)
|
|
(let ((label (id->label e)))
|
|
(let ((b (label->binding label r)))
|
|
(if (eq? (binding-type b) 'syntax)
|
|
(let-values (((var maps)
|
|
(let ((var.lev (binding-value b)))
|
|
(gen-ref src (car var.lev) (cdr var.lev) maps))))
|
|
(values (list 'ref var) maps))
|
|
(if (ellipsis? e)
|
|
(syntax-error src "1misplaced ellipsis in syntax form")
|
|
(begin
|
|
(values (list 'quote e) maps))))))
|
|
(match2 e (lambda (dots e) (ellipsis? dots))
|
|
(lambda (dots e)
|
|
(if vec?
|
|
(syntax-error src "2misplaced ellipsis in syntax form")
|
|
(gen-syntax src e r maps (lambda (x) #f) #f)))
|
|
(lambda ()
|
|
(cond
|
|
((and (syntax-pair? e) ;(x dots . y)
|
|
(let ((t (syntax-cdr e)))
|
|
(and (syntax-pair? t)
|
|
(ellipsis? (syntax-car t)))))
|
|
(let f ((y (syntax-cdr (syntax-cdr e)))
|
|
(k (lambda (maps)
|
|
(let-values (((x maps)
|
|
(gen-syntax src (syntax-car e) r
|
|
(cons '() maps) ellipsis? #f)))
|
|
(if (null? (car maps))
|
|
(syntax-error src
|
|
"extra ellipsis in syntax form")
|
|
(values (gen-map x (car maps)) (cdr maps)))))))
|
|
(cond
|
|
((syntax-null? y) (k maps))
|
|
((and (syntax-pair? y) (ellipsis? (syntax-car y)))
|
|
; (dots . y)
|
|
(f (syntax-cdr y)
|
|
(lambda (maps)
|
|
(let-values (((x maps) (k (cons '() maps))))
|
|
(if (null? (car maps))
|
|
(syntax-error src "extra ellipsis in syntax form")
|
|
(values (gen-mappend x (car maps)) (cdr maps)))))))
|
|
(else
|
|
(let-values (((y maps)
|
|
(gen-syntax src y r maps ellipsis? vec?)))
|
|
(let-values (((x maps) (k maps)))
|
|
(values (gen-append x y) maps)))))))
|
|
((syntax-pair? e) ;(x . y)
|
|
(let-values (((xnew maps)
|
|
(gen-syntax src (syntax-car e) r
|
|
maps ellipsis? #f)))
|
|
(let-values (((ynew maps)
|
|
(gen-syntax src (syntax-cdr e) r
|
|
maps ellipsis? vec?)))
|
|
(values (gen-cons e (syntax-car e) (syntax-cdr e) xnew ynew)
|
|
maps))))
|
|
((syntax-vector? e) ;#(x1 x2 ...)
|
|
(let ((ls (syntax-vector->list e)))
|
|
(let-values (((lsnew maps)
|
|
(gen-syntax src ls r maps ellipsis? #t)))
|
|
(values (gen-vector e ls lsnew) maps))))
|
|
((and (syntax-null? e) vec?) (values '(quote ()) maps))
|
|
(else (values `(quote ,e) maps))))))))
|
|
(define gen-ref
|
|
(lambda (src var level maps)
|
|
(if (= level 0)
|
|
(values var maps)
|
|
(if (null? maps)
|
|
(syntax-error src "missing ellipsis in syntax form")
|
|
(let-values (((outer-var outer-maps)
|
|
(gen-ref src var (- level 1) (cdr maps))))
|
|
(cond
|
|
((assq outer-var (car maps)) =>
|
|
(lambda (b) (values (cdr b) maps)))
|
|
(else
|
|
(let ((inner-var (gen-lexical 'tmp)))
|
|
(values
|
|
inner-var
|
|
(cons
|
|
(cons (cons outer-var inner-var) (car maps))
|
|
outer-maps))))))))))
|
|
(define gen-append
|
|
(lambda (x y)
|
|
(if (equal? y '(quote ())) x (list 'append x y))))
|
|
(define gen-mappend
|
|
(lambda (e map-env)
|
|
(list 'apply '(primitive append) (gen-map e map-env))))
|
|
(define gen-map
|
|
(lambda (e map-env)
|
|
(let ((formals (map cdr map-env))
|
|
(actuals (map (lambda (x) (list 'ref (car x))) map-env)))
|
|
(cond
|
|
; identity map equivalence:
|
|
; (map (lambda (x) x) y) == y
|
|
((eq? (car e) 'ref)
|
|
(car actuals))
|
|
; eta map equivalence:
|
|
; (map (lambda (x ...) (f x ...)) y ...) == (map f y ...)
|
|
((andmap
|
|
(lambda (x) (and (eq? (car x) 'ref) (memq (cadr x) formals)))
|
|
(cdr e))
|
|
(list* 'map (list 'primitive (car e))
|
|
(map (let ((r (map cons formals actuals)))
|
|
(lambda (x) (cdr (assq (cadr x) r))))
|
|
(cdr e))))
|
|
(else (list* 'map (list 'lambda formals e) actuals))))))
|
|
(define gen-cons
|
|
(lambda (e x y xnew ynew)
|
|
(case (car ynew)
|
|
((quote)
|
|
(if (eq? (car xnew) 'quote)
|
|
(let ((xnew (cadr xnew)) (ynew (cadr ynew)))
|
|
(if (and (eq? xnew x) (eq? ynew y))
|
|
(list 'quote e)
|
|
(list 'quote (cons xnew ynew))))
|
|
(if (eq? (cadr ynew) '())
|
|
(list 'list xnew)
|
|
(list 'cons xnew ynew))))
|
|
((list) (list* 'list xnew (cdr ynew)))
|
|
(else (list 'cons xnew ynew)))))
|
|
(define gen-vector
|
|
(lambda (e ls lsnew)
|
|
(cond
|
|
((eq? (car lsnew) 'quote)
|
|
(if (eq? (cadr lsnew) ls)
|
|
(list 'quote e)
|
|
(list 'quote (list->vector (cadr lsnew)))))
|
|
;`(quote #(,@(cadr lsnew)))))
|
|
((eq? (car lsnew) 'list)
|
|
(cons 'vector (cdr lsnew)))
|
|
(else (list 'list->vector lsnew)))))
|
|
(define regen
|
|
(lambda (x)
|
|
(case (car x)
|
|
((ref) (build-lexical-reference no-source (cadr x)))
|
|
((primitive) (build-primref no-source (cadr x)))
|
|
((quote) (build-data no-source (cadr x)))
|
|
((lambda) (build-lambda no-source (cadr x) (regen (caddr x))))
|
|
((map)
|
|
(let ((ls (map regen (cdr x))))
|
|
(build-application no-source
|
|
(build-primref no-source 'map)
|
|
ls)))
|
|
(else
|
|
(build-application no-source
|
|
(build-primref no-source (car x))
|
|
(map regen (cdr x)))))))
|
|
(lambda (e r mr)
|
|
(match2 e #t
|
|
(lambda (_ x)
|
|
(let-values (((e maps) (gen-syntax e x r '() ellipsis? #f)))
|
|
(regen e)))
|
|
(lambda () (syntax-error e))))))
|
|
(define core-macro-transformer
|
|
(lambda (name)
|
|
(case name
|
|
[(quote) quote-transformer]
|
|
[(lambda) lambda-transformer]
|
|
[(case-lambda) case-lambda-transformer]
|
|
[(let-values) let-values-transformer]
|
|
[(letrec) letrec-transformer]
|
|
[(case) case-transformer]
|
|
[(if) if-transformer]
|
|
[(when) when-transformer]
|
|
[(unless) unless-transformer]
|
|
[(parameterize) parameterize-transformer]
|
|
[(foreign-call) foreign-call-transformer]
|
|
[(syntax-case) syntax-case-transformer]
|
|
[(syntax) syntax-transformer]
|
|
[(type-descriptor) type-descriptor-transformer]
|
|
[else (error 'macro-transformer "cannot find ~s" name)])))
|
|
(define macro-transformer
|
|
(lambda (x)
|
|
(cond
|
|
[(procedure? x) x]
|
|
[(symbol? x)
|
|
(case x
|
|
[(define-record) define-record-macro]
|
|
[(include) include-macro]
|
|
[(cond) cond-macro]
|
|
[(let) let-macro]
|
|
[(or) or-macro]
|
|
[(and) and-macro]
|
|
[(let*) let*-macro]
|
|
[(syntax-rules) syntax-rules-macro]
|
|
[(quasiquote) quasiquote-macro]
|
|
[(with-syntax) with-syntax-macro]
|
|
[else (error 'macro-transformer "invalid macro ~s" x)])]
|
|
[else (error 'core-macro-transformer "invalid macro ~s" x)])))
|
|
;;; chi procedures
|
|
(define chi-macro
|
|
(lambda (p e)
|
|
(let ([s ((macro-transformer p) (add-mark anti-mark e))])
|
|
(add-mark (gen-mark) s))))
|
|
(define chi-expr*
|
|
(lambda (e* r mr)
|
|
;;; expand left to right
|
|
(cond
|
|
[(null? e*) '()]
|
|
[else
|
|
(let ([e (chi-expr (car e*) r mr)])
|
|
(cons e (chi-expr* (cdr e*) r mr)))])))
|
|
(define chi-application
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(rator rands ...)
|
|
(let ([rator (chi-expr rator r mr)])
|
|
(build-application no-source
|
|
rator
|
|
(chi-expr* rands r mr)))])))
|
|
(define chi-expr
|
|
(lambda (e r mr)
|
|
(let-values ([(type value kwd) (syntax-type e r)])
|
|
(case type
|
|
[(core-macro)
|
|
(let ([transformer (core-macro-transformer value)])
|
|
(transformer e r mr))]
|
|
[(global)
|
|
(let* ([loc value]
|
|
[lib (imported-loc->library loc)])
|
|
(unless lib
|
|
(syntax-error e "BUG: cannot find defining library"))
|
|
((run-collector) lib)
|
|
(build-global-reference no-source loc))]
|
|
[(core-prim)
|
|
(let ([name value])
|
|
(build-primref no-source name))]
|
|
[(call) (chi-application e r mr)]
|
|
[(lexical)
|
|
(let ([lex value])
|
|
(build-lexical-reference no-source lex))]
|
|
[(macro) (chi-expr (chi-macro value e) r mr)]
|
|
[(constant)
|
|
(let ([datum value])
|
|
(build-data no-source datum))]
|
|
[(set!) (chi-set! e r mr)]
|
|
[(begin)
|
|
(syntax-match e ()
|
|
[(_ x x* ...)
|
|
(build-sequence no-source
|
|
(chi-expr* (cons x x*) r mr))])]
|
|
[else (error 'chi-expr "invalid type ~s for ~s" type
|
|
(strip e '())) (stx-error e)]))))
|
|
(define chi-set!
|
|
(lambda (e r mr)
|
|
(syntax-match e ()
|
|
[(_ x v)
|
|
(if (id? x)
|
|
(let-values ([(type value kwd) (syntax-type x r)])
|
|
(case type
|
|
[(lexical)
|
|
(build-lexical-assignment no-source
|
|
value
|
|
(chi-expr v r mr))]
|
|
[else (stx-error e)]))
|
|
(stx-error e))])))
|
|
(define chi-lambda-clause
|
|
(lambda (fmls body* r mr)
|
|
(syntax-match fmls ()
|
|
[(x* ...)
|
|
(if (valid-bound-ids? x*)
|
|
(let ([lex* (map gen-lexical x*)]
|
|
[lab* (map gen-label x*)])
|
|
(values
|
|
lex*
|
|
(chi-internal
|
|
(add-subst
|
|
(make-full-rib x* lab*)
|
|
body*)
|
|
(add-lexicals lab* lex* r)
|
|
mr)))
|
|
(stx-error fmls "invalid fmls"))]
|
|
[(x* ... . x)
|
|
(if (valid-bound-ids? (cons x x*))
|
|
(let ([lex* (map gen-lexical x*)]
|
|
[lab* (map gen-label x*)]
|
|
[lex (gen-lexical x)]
|
|
[lab (gen-label x)])
|
|
(values
|
|
(append lex* lex)
|
|
(chi-internal
|
|
(add-subst
|
|
(make-full-rib (cons x x*) (cons lab lab*))
|
|
body*)
|
|
(add-lexicals (cons lab lab*)
|
|
(cons lex lex*)
|
|
r)
|
|
mr)))
|
|
(stx-error fmls "invalid fmls"))]
|
|
[_ (stx-error fmls "invalid fmls")])))
|
|
(define chi-lambda-clause*
|
|
(lambda (fmls* body** r mr)
|
|
(cond
|
|
[(null? fmls*) (values '() '())]
|
|
[else
|
|
(let-values ([(a b)
|
|
(chi-lambda-clause (car fmls*) (car body**) r mr)])
|
|
(let-values ([(a* b*)
|
|
(chi-lambda-clause* (cdr fmls*) (cdr body**) r mr)])
|
|
(values (cons a a*) (cons b b*))))])))
|
|
(define chi-rhs*
|
|
(lambda (rhs* r mr)
|
|
(define chi-rhs
|
|
(lambda (rhs)
|
|
(case (car rhs)
|
|
[(defun)
|
|
(let ([x (cdr rhs)])
|
|
(let ([fmls (car x)] [body* (cdr x)])
|
|
(let-values ([(fmls body)
|
|
(chi-lambda-clause fmls body* r mr)])
|
|
(build-lambda no-source fmls body))))]
|
|
[(expr)
|
|
(let ([expr (cdr rhs)])
|
|
(chi-expr expr r mr))]
|
|
[else (error 'chi-rhs "invalid rhs ~s" rhs)])))
|
|
(let f ([ls rhs*])
|
|
(cond ;;; chi in order
|
|
[(null? ls) '()]
|
|
[else
|
|
(let ([a (chi-rhs (car ls))])
|
|
(cons a (f (cdr ls))))]))))
|
|
(define find-bound=?
|
|
(lambda (x lhs* rhs*)
|
|
(cond
|
|
[(null? lhs*) #f]
|
|
[(bound-id=? x (car lhs*)) (car rhs*)]
|
|
[else (find-bound=? x (cdr lhs*) (cdr rhs*))])))
|
|
(define (find-dups ls)
|
|
(let f ([ls ls] [dups '()])
|
|
(cond
|
|
[(null? ls) dups]
|
|
[(find-bound=? (car ls) (cdr ls) (cdr ls)) =>
|
|
(lambda (x) (f (cdr ls) (cons (list (car ls) x) dups)))]
|
|
[else (f (cdr ls) dups)])))
|
|
(define chi-internal
|
|
(lambda (e* r mr)
|
|
(define return
|
|
(lambda (init* module-init** r mr lhs* lex* rhs*)
|
|
(let ([mod-init* (apply append (reverse module-init**))])
|
|
(unless (valid-bound-ids? lhs*)
|
|
(stx-error (find-dups lhs*) "multiple definitions in internal"))
|
|
(let ([rhs* (chi-rhs* rhs* r mr)]
|
|
[init* (chi-expr* (append mod-init* init*) r mr)])
|
|
(build-letrec no-source
|
|
(reverse lex*) (reverse rhs*)
|
|
(build-sequence no-source init*))))))
|
|
(let* ([rib (make-empty-rib)]
|
|
[e* (map (lambda (x) (add-subst rib x))
|
|
(syntax->list e*))])
|
|
(let f ([e* e*] [module-init** '()] [r r] [mr r] [lhs* '()] [lex* '()] [rhs* '()] [kwd* '()])
|
|
(cond
|
|
[(null? e*) (error 'chi-internal "empty body")]
|
|
[else
|
|
(let ([e (car e*)])
|
|
(let-values ([(type value kwd) (syntax-type e r)])
|
|
(let ([kwd* (cons-id kwd kwd*)])
|
|
(case type
|
|
[(define)
|
|
(let-values ([(id rhs) (parse-define e)])
|
|
(when (bound-id-member? id kwd*)
|
|
(stx-error id "undefined identifier"))
|
|
(let ([lex (gen-lexical id)]
|
|
[lab (gen-label id)])
|
|
(extend-rib! rib id lab)
|
|
(f (cdr e*)
|
|
module-init**
|
|
(cons (cons lab (cons 'lexical lex)) r)
|
|
mr
|
|
(cons id lhs*)
|
|
(cons lex lex*)
|
|
(cons rhs rhs*)
|
|
kwd*)))]
|
|
[(define-syntax)
|
|
(let-values ([(id rhs) (parse-define-syntax e)])
|
|
(when (bound-id-member? id kwd*)
|
|
(syntax-error id "undefined identifier"))
|
|
(let ([lab (gen-label id)])
|
|
(let ([expanded-rhs (chi-expr rhs mr mr)])
|
|
(extend-rib! rib id lab)
|
|
(let ([b (make-eval-transformer expanded-rhs)])
|
|
(f (cdr e*)
|
|
module-init**
|
|
(cons (cons lab b) r)
|
|
(cons (cons lab b) mr)
|
|
(cons id lhs*) lex* rhs* kwd*)))))]
|
|
[(begin)
|
|
(syntax-match e ()
|
|
[(_ x* ...)
|
|
(f (append x* (cdr e*)) module-init**
|
|
r mr lhs* lex* rhs* kwd*)])]
|
|
[(macro)
|
|
(f (cons (add-subst rib (chi-macro value e)) (cdr e*))
|
|
module-init** r mr lhs* lex* rhs* kwd*)]
|
|
[(module)
|
|
(let-values ([(m-lhs* m-lex* m-rhs* m-init* m-exp-id* m-exp-lab* r mr kwd*)
|
|
(chi-internal-module e r mr kwd*)])
|
|
(for-each
|
|
(lambda (id lab) (extend-rib! rib id lab))
|
|
m-exp-id* m-exp-lab*)
|
|
(f (cdr e*)
|
|
(cons m-init* module-init**)
|
|
r mr
|
|
(append m-exp-id* lhs*)
|
|
(append m-lex* lex*)
|
|
(append m-rhs* rhs*)
|
|
kwd*))]
|
|
[else
|
|
(return e* module-init** r mr lhs* lex* rhs*)]))))])))))
|
|
(define chi-internal-module
|
|
(lambda (e r mr kwd*)
|
|
(define parse-module
|
|
(lambda (e)
|
|
(syntax-match e ()
|
|
[(_ (export* ...) b* ...)
|
|
(unless (andmap id? export*) (stx-error e))
|
|
(values #f export* b*)]
|
|
[(_ name (export* ...) b* ...)
|
|
(unless (and (id? name) (andmap id? export*)) (stx-error e))
|
|
(values name export* b*)])))
|
|
(let-values ([(name exp-id* e*) (parse-module e)])
|
|
(let* ([rib (make-empty-rib)]
|
|
[e* (map (lambda (x) (add-subst rib x))
|
|
(syntax->list e*))])
|
|
(define return
|
|
(lambda (init* r mr lhs* lex* rhs* kwd*)
|
|
(unless (valid-bound-ids? lhs*)
|
|
(stx-error (find-dups lhs*) "multiple definitions in module"))
|
|
(let ([exp-lab*
|
|
(map (lambda (x)
|
|
(or (id->label (add-subst rib x))
|
|
(stx-error x "cannot find export")))
|
|
exp-id*)])
|
|
(if (not name) ;;; explicit export
|
|
(values lhs* lex* rhs* init* exp-id* exp-lab* r mr kwd*)
|
|
(let ([lab (gen-label 'module)]
|
|
[iface (cons exp-id* exp-lab*)])
|
|
(values lhs* lex* rhs* init*
|
|
(list name) ;;; FIXME: module cannot
|
|
(list lab) ;;; export itself yet
|
|
(cons (cons lab (cons '$module iface)) r)
|
|
(cons (cons lab (cons '$module iface)) mr)
|
|
kwd*))))))
|
|
(let f ([e* e*] [r r] [mr mr] [lhs* '()] [lex* '()] [rhs* '()] [kwd* kwd*])
|
|
(cond
|
|
[(null? e*) (return '() r mr lhs* lex* rhs* kwd*)]
|
|
[else
|
|
(let ([e (car e*)])
|
|
(let-values ([(type value kwd) (syntax-type e r)])
|
|
(let ([kwd* (cons-id kwd kwd*)])
|
|
(case type
|
|
[(define)
|
|
(let-values ([(id rhs) (parse-define e)])
|
|
(when (bound-id-member? id kwd*)
|
|
(stx-error id "undefined identifier"))
|
|
(let ([lex (gen-lexical id)]
|
|
[lab (gen-label id)])
|
|
(extend-rib! rib id lab)
|
|
(f (cdr e*)
|
|
(cons (cons lab (cons 'lexical lex)) r)
|
|
mr
|
|
(cons id lhs*)
|
|
(cons lex lex*)
|
|
(cons rhs rhs*)
|
|
kwd*)))]
|
|
[(define-syntax)
|
|
(let-values ([(id rhs) (parse-define-syntax e)])
|
|
(when (bound-id-member? id kwd*)
|
|
(syntax-error id "undefined identifier"))
|
|
(let ([lab (gen-label id)])
|
|
(let ([expanded-rhs (chi-expr rhs mr mr)])
|
|
(extend-rib! rib id lab)
|
|
(let ([b (make-eval-transformer expanded-rhs)])
|
|
(f (cdr e*)
|
|
(cons (cons lab b) r)
|
|
(cons (cons lab b) mr)
|
|
(cons id lhs*)
|
|
lex* rhs* kwd*)))))]
|
|
[(begin)
|
|
(syntax-match e ()
|
|
[(_ x* ...)
|
|
(f (append x* (cdr e*)) r mr lhs* lex* rhs* kwd*)])]
|
|
[(macro)
|
|
(f (cons (add-subst rib (chi-macro value e)) (cdr e*))
|
|
r mr lhs* lex* rhs* kwd*)]
|
|
[else (return e* r mr lhs* lex* rhs* kwd*)]))))]))))))
|
|
(define chi-library-internal
|
|
(lambda (e* rib kwd*)
|
|
(define return
|
|
(lambda (init* module-init** r mr lhs* lex* rhs*)
|
|
(let ([module-init* (apply append (reverse module-init**))])
|
|
(values (append module-init* init*)
|
|
r mr (reverse lex*) (reverse rhs*)))))
|
|
(let f ([e* e*] [module-init** '()] [r '()] [mr '()]
|
|
[lhs* '()] [lex* '()] [rhs* '()] [kwd* kwd*])
|
|
(cond
|
|
[(null? e*) (return e* module-init** r mr lhs* lex* rhs*)]
|
|
[else
|
|
(let ([e (car e*)])
|
|
(let-values ([(type value kwd) (syntax-type e r)])
|
|
(let ([kwd* (cons-id kwd kwd*)])
|
|
(case type
|
|
[(define)
|
|
(let-values ([(id rhs) (parse-define e)])
|
|
(when (bound-id-member? id kwd*)
|
|
(stx-error id "cannt redefine identifier"))
|
|
(when (bound-id-member? id lhs*)
|
|
(stx-error id "multiple definition"))
|
|
(let ([lex (gen-lexical id)]
|
|
[lab (gen-label id)])
|
|
(extend-rib! rib id lab)
|
|
(f (cdr e*)
|
|
module-init**
|
|
(cons (cons lab (cons 'lexical lex)) r)
|
|
mr
|
|
(cons id lhs*) (cons lex lex*) (cons rhs rhs*)
|
|
kwd*)))]
|
|
[(define-syntax)
|
|
(let-values ([(id rhs) (parse-define-syntax e)])
|
|
(when (bound-id-member? id kwd*)
|
|
(syntax-error id "undefined identifier"))
|
|
(let ([lab (gen-label id)])
|
|
(let ([expanded-rhs (chi-expr rhs mr mr)])
|
|
(extend-rib! rib id lab)
|
|
(let ([b (make-eval-transformer expanded-rhs)])
|
|
(f (cdr e*)
|
|
module-init**
|
|
(cons (cons lab b) r)
|
|
(cons (cons lab b) mr)
|
|
(cons id lhs*) lex* rhs* kwd*)))))]
|
|
[(module)
|
|
(let-values ([(m-lhs* m-lex* m-rhs* m-init* m-exp-id* m-exp-lab* r mr kwd*)
|
|
(chi-internal-module e r mr kwd*)])
|
|
(for-each
|
|
(lambda (id lab) (extend-rib! rib id lab))
|
|
m-exp-id* m-exp-lab*)
|
|
(f (cdr e*)
|
|
(cons m-init* module-init**)
|
|
r mr
|
|
(append m-exp-id* lhs*)
|
|
(append m-lex* lex*)
|
|
(append m-rhs* rhs*)
|
|
kwd*))]
|
|
[(begin)
|
|
(syntax-match e ()
|
|
[(_ x* ...)
|
|
(f (append x* (cdr e*)) module-init** r mr lhs* lex* rhs*
|
|
kwd*)])]
|
|
[(macro)
|
|
(f (cons (add-subst rib (chi-macro value e)) (cdr e*))
|
|
module-init**
|
|
r mr lhs* lex* rhs* kwd*)]
|
|
[else
|
|
(return e* module-init** r mr lhs* lex* rhs*)]))))]))))
|
|
(define (parse-exports exp*)
|
|
(let f ([exp* exp*] [int* '()] [ext* '()])
|
|
(cond
|
|
[(null? exp*)
|
|
(let ([id* (map (lambda (x) (stx x top-mark* '())) ext*)])
|
|
(unless (valid-bound-ids? id*)
|
|
(error #f "duplicate exports of ~s" (find-dups id*))))
|
|
(values int* ext*)]
|
|
[else
|
|
(syntax-match (car exp*) ()
|
|
[(rename (i* e*) ...)
|
|
(unless (and (eq? rename 'rename) (andmap symbol? i*) (andmap symbol? e*))
|
|
(error #f "invalid export specifier ~s" (car exp*)))
|
|
(f (cdr exp*) (append i* int*) (append e* ext*))]
|
|
[ie
|
|
(unless (symbol? ie) (error #f "invalid export ~s" ie))
|
|
(f (cdr exp*) (cons ie int*) (cons ie ext*))])])))
|
|
(define parse-library
|
|
(lambda (e)
|
|
(syntax-match e ()
|
|
[(_ (name name* ...)
|
|
(export exp* ...)
|
|
(import imp* ...)
|
|
b* ...)
|
|
(if (and (eq? export 'export)
|
|
(eq? import 'import)
|
|
(symbol? name)
|
|
(andmap symbol? name*))
|
|
(let-values ([(exp-int* exp-ext*) (parse-exports exp*)])
|
|
(values (cons name name*) exp-int* exp-ext* imp* b*))
|
|
(error who "malformed library ~s" e))]
|
|
[_ (error who "malformed library ~s" e)])))
|
|
(define (set-cons x ls)
|
|
(cond
|
|
[(memq x ls) ls]
|
|
[else (cons x ls)]))
|
|
(define (set-union ls1 ls2)
|
|
(cond
|
|
[(null? ls1) ls2]
|
|
[(memq (car ls1) ls2) (set-union (cdr ls1) ls2)]
|
|
[else (cons (car ls1) (set-union (cdr ls1) ls2))]))
|
|
(define (get-import-subst/libs imp*)
|
|
(define (insert-to-subst a subst)
|
|
(let ([name (car a)] [label (cdr a)])
|
|
(cond
|
|
[(assq name subst) =>
|
|
(lambda (x)
|
|
(cond
|
|
[(eq? (cdr x) label) subst]
|
|
[else
|
|
(error 'import
|
|
"two imports of ~s with different bindings"
|
|
name)]))]
|
|
[else
|
|
(cons a subst)])))
|
|
(define (merge-substs s subst)
|
|
(cond
|
|
[(null? s) subst]
|
|
[else
|
|
(insert-to-subst (car s)
|
|
(merge-substs (cdr s) subst))]))
|
|
(define (exclude* sym* subst)
|
|
(define (exclude sym subst)
|
|
(cond
|
|
[(null? subst)
|
|
(error 'import "cannot rename unbound identifier ~s" sym)]
|
|
[(eq? sym (caar subst))
|
|
(values (cdar subst) (cdr subst))]
|
|
[else
|
|
(let ([a (car subst)])
|
|
(let-values ([(old subst) (exclude sym (cdr subst))])
|
|
(values old (cons a subst))))]))
|
|
(cond
|
|
[(null? sym*) (values '() subst)]
|
|
[else
|
|
(let-values ([(old subst) (exclude (car sym*) subst)])
|
|
(let-values ([(old* subst) (exclude* (cdr sym*) subst)])
|
|
(values (cons old old*) subst)))]))
|
|
(define (find* sym* subst)
|
|
(map (lambda (x)
|
|
(cond
|
|
[(assq x subst) => cdr]
|
|
[else (error 'import "cannot find identifier ~s" x)]))
|
|
sym*))
|
|
(define (rem* sym* subst)
|
|
(let f ([subst subst])
|
|
(cond
|
|
[(null? subst) '()]
|
|
[(memq (caar subst) sym*) (f (cdr subst))]
|
|
[else (cons (car subst) (f (cdr subst)))])))
|
|
(define (get-import spec)
|
|
(define (remove-dups ls)
|
|
(cond
|
|
[(null? ls) '()]
|
|
[(memq (car ls) (cdr ls)) (remove-dups (cdr ls))]
|
|
[else (cons (car ls) (remove-dups (cdr ls)))]))
|
|
(unless (pair? spec)
|
|
(error 'import "invalid import spec ~s" spec))
|
|
(case (car spec)
|
|
[(rename)
|
|
(syntax-match spec ()
|
|
[(_ isp (old* new*) ...)
|
|
(unless (and (andmap symbol? old*) (andmap symbol? new*))
|
|
(error 'import "invalid import spec ~s" spec))
|
|
(let-values ([(subst lib) (get-import isp)])
|
|
(let ([old-label* (find* old* subst)])
|
|
(let ([subst (rem* old* subst)])
|
|
;;; FIXME: make sure map is valid
|
|
(values (merge-substs (map cons new* old-label*) subst)
|
|
lib))))]
|
|
[_ (error 'import "invalid rename spec ~s" spec)])]
|
|
[(except)
|
|
(syntax-match spec ()
|
|
[(_ isp sym* ...)
|
|
(unless (andmap symbol? sym*)
|
|
(error 'import "invalid import spec ~s" spec))
|
|
(let-values ([(subst lib) (get-import isp)])
|
|
(values (rem* sym* subst) lib))]
|
|
[_ (error 'import "invalid import spec ~s" spec)])]
|
|
[(only)
|
|
(syntax-match spec ()
|
|
[(_ isp sym* ...)
|
|
(unless (andmap symbol? sym*)
|
|
(error 'import "invalid import spec ~s" spec))
|
|
(let-values ([(subst lib) (get-import isp)])
|
|
(let ([sym* (remove-dups sym*)])
|
|
(let ([lab* (find* sym* subst)])
|
|
(values (map cons sym* lab*) lib))))]
|
|
[_ (error 'import "invalid import spec ~s" spec)])]
|
|
[(prefix) (error #f "prefix found")]
|
|
[else
|
|
(let ([lib (find-library-by-name spec)])
|
|
(let-values ([(s _r) (library-subst/env lib)])
|
|
(values s lib)))]))
|
|
(cond
|
|
[(null? imp*) (values '() '())]
|
|
[else
|
|
(let-values ([(subst1 lib1*)
|
|
(get-import-subst/libs (cdr imp*))])
|
|
(let-values ([(subst2 lib2) (get-import (car imp*))])
|
|
(values (merge-substs subst1 subst2)
|
|
(set-cons lib2 lib1*))))]))
|
|
(define (make-top-rib subst)
|
|
(let ([rib (make-empty-rib)])
|
|
(for-each
|
|
(lambda (x)
|
|
(let ([name (car x)] [label (cdr x)])
|
|
(extend-rib! rib (stx name top-mark* '()) label)))
|
|
subst)
|
|
rib))
|
|
(define (make-collector)
|
|
(let ([ls '()])
|
|
(case-lambda
|
|
[() ls]
|
|
[(x) (set! ls (set-cons x ls))])))
|
|
(define run-collector
|
|
(make-parameter
|
|
(lambda args
|
|
(error 'run-collector "not initialized"))
|
|
(lambda (x)
|
|
(unless (procedure? x)
|
|
(error 'run-collector "~s is not a procedure" x))
|
|
x)))
|
|
(define core-library-expander
|
|
(lambda (e)
|
|
(let-values ([(name exp-int* exp-ext* imp* b*) (parse-library e)])
|
|
(let-values ([(subst imp*) (get-import-subst/libs imp*)])
|
|
(let ([rib (make-top-rib subst)])
|
|
(let ([b* (map (lambda (x) (stx x top-mark* (list rib))) b*)]
|
|
[kwd* (map (lambda (sym mark*) (stx sym mark* (list rib)))
|
|
(rib-sym* rib) (rib-mark** rib))]
|
|
[rtc (make-collector)])
|
|
(parameterize ([run-collector rtc])
|
|
(let-values ([(init* r mr lex* rhs*)
|
|
(chi-library-internal b* rib kwd*)])
|
|
(let ([rhs* (chi-rhs* rhs* r mr)])
|
|
(let ([body (if (and (null? init*) (null? lex*))
|
|
(build-void)
|
|
(build-sequence no-source
|
|
(append
|
|
(map build-export lex*)
|
|
(chi-expr* init* r mr))))])
|
|
(let-values ([(export-subst export-env)
|
|
(find-exports exp-int* exp-ext* rib r)])
|
|
(values
|
|
name imp* (rtc)
|
|
(build-letrec no-source lex* rhs* body)
|
|
export-subst export-env))))))))))))
|
|
(define (library-expander x)
|
|
(let-values ([(name imp* run* invoke-code export-subst export-env)
|
|
(core-library-expander x)])
|
|
(let ([id (gensym)]
|
|
[name name]
|
|
[ver '()] ;;; FIXME
|
|
[imp* (map library-spec imp*)]
|
|
[vis* '()] ;;; FIXME
|
|
[inv* (map library-spec run*)])
|
|
(install-library id name ver
|
|
imp* vis* inv* export-subst export-env
|
|
void ;;; FIXME
|
|
(lambda () (eval-core invoke-code)))
|
|
(values invoke-code export-subst export-env))))
|
|
(define (boot-library-expander x)
|
|
(let-values ([(invoke-code export-subst export-env)
|
|
(library-expander x)])
|
|
(values invoke-code export-subst export-env)))
|
|
(define build-export
|
|
(lambda (x)
|
|
;;; exports use the same gensym
|
|
`(#%$set-symbol-value! ',x ,x)))
|
|
(define (find-exports int* ext* rib r)
|
|
(let f ([int* int*] [ext* ext*] [subst '()] [env '()])
|
|
(cond
|
|
[(null? int*) (values subst env)]
|
|
[else
|
|
(let* ([sym (car int*)]
|
|
[id (stx sym top-mark* (list rib))]
|
|
[label (id->label id)]
|
|
[b (label->binding label r)]
|
|
[type (binding-type b)])
|
|
(unless label
|
|
(stx-error id "cannot export unbound identifier"))
|
|
(case type
|
|
[(lexical)
|
|
(f (cdr int*) (cdr ext*)
|
|
(cons (cons (car ext*) label) subst)
|
|
(cons (cons label (cons 'global (binding-value b))) env))]
|
|
[else (error #f "cannot export ~s of type ~s" sym type)]))])))
|
|
(primitive-set! 'identifier? id?)
|
|
(primitive-set! 'generate-temporaries
|
|
(lambda (ls)
|
|
(unless (list? ls)
|
|
(error 'generate-temporaries "~s is not a list"))
|
|
(map (lambda (x) (stx (gensym 't) top-mark* '())) ls)))
|
|
(primitive-set! 'free-identifier=?
|
|
(lambda (x y)
|
|
(if (id? x)
|
|
(if (id? y)
|
|
(free-id=? x y)
|
|
(error 'free-identifier=? "~s is not an identifier" y))
|
|
(error 'free-identifier=? "~s is not an identifier" x))))
|
|
(primitive-set! 'syntax-error
|
|
(lambda (x . args)
|
|
(unless (andmap string? args)
|
|
(error 'syntax-error "invalid argument ~s" args))
|
|
(error #f "~a: ~s"
|
|
(apply string-append args)
|
|
(strip x '()))))
|
|
(primitive-set! 'syntax-dispatch syntax-dispatch)
|
|
(primitive-set! 'boot-library-expand boot-library-expander)
|
|
(primitive-set! 'eval-top-level
|
|
(lambda (x)
|
|
(unless (pair? x)
|
|
(error #f "invalid expression at top-level ~s" x))
|
|
(case (car x)
|
|
[(library)
|
|
(library-expander x)
|
|
(void)]
|
|
[(invoke)
|
|
(syntax-match x ()
|
|
[(_ (id** ...) ...)
|
|
(unless (andmap (lambda (id*) (andmap symbol? id*)) id**)
|
|
(error #f "invalid invoke form ~s" x))
|
|
(let ([lib*
|
|
(map (lambda (x)
|
|
(or (find-library-by-name x)
|
|
(error #f "cannot find library ~s"
|
|
x)))
|
|
id**)])
|
|
(for-each invoke-library lib*))]
|
|
[else (error #f "invalid invoke form ~s" x)])]
|
|
[else (error #f "invalid top-level form ~s" x)])))
|
|
)
|
|
|
|
|
|
|
|
|
|
#!eof junk
|
|
|
|
(build-application no-source
|
|
(build-primref no-source 'install-library)
|
|
(list (build-data no-source id)
|
|
(build-data no-source name)
|
|
(build-data no-source ver)
|
|
(build-data no-source imp*)
|
|
(build-data no-source vis*)
|
|
(build-data no-source inv*)
|
|
(build-data no-source exp-subst)
|
|
(build-data no-source exp-env)
|
|
(build-primref no-source 'void)
|
|
(build-sequence no-source
|
|
(list invoke-code
|
|
(build-primref no-source 'void)))))
|
|
|
|
|
|
(module (make-stx stx? stx-expr stx-mark* stx-subst*)
|
|
(define make-stx
|
|
(lambda (e m* s*)
|
|
(vector 'stx e m* s*)))
|
|
(define stx?
|
|
(lambda (x)
|
|
(and (vector? x)
|
|
(= (vector-length x) 4)
|
|
(eq? (vector-ref x 0) 'stx))))
|
|
(define stx-expr
|
|
(lambda (x)
|
|
(if (stx? x)
|
|
(vector-ref x 1)
|
|
(error 'stx-expr "~s is not a syntax object" x))))
|
|
(define stx-mark*
|
|
(lambda (x)
|
|
(if (stx? x)
|
|
(vector-ref x 2)
|
|
(error 'stx-mark* "~s is not a syntax object" x))))
|
|
(define stx-subst*
|
|
(lambda (x)
|
|
(if (stx? x)
|
|
(vector-ref x 3)
|
|
(error 'stx-subst* "~s is not a syntax object" x)))))
|