126 lines
3.6 KiB
Scheme
126 lines
3.6 KiB
Scheme
; Copyright (c) 1993, 1994 Richard Kelsey and Jonathan Rees. See file COPYING.
|
|
|
|
; schemify
|
|
|
|
|
|
; Flush nodes and generated names in favor of something a little more
|
|
; readable. Eventually, (schemify node) ought to produce an
|
|
; s-expression that has the same semantics as node, when node is fully
|
|
; expanded.
|
|
|
|
(define (schemify node . env-option)
|
|
(schemify1 node (if (null? env-option) #f (car env-option))))
|
|
|
|
(define (schemify1 node env)
|
|
(if (node? node)
|
|
(or (node-ref node 'schemify)
|
|
(let ((form ((operator-table-ref schemifiers (node-operator-id node))
|
|
node env)))
|
|
(node-set! node 'schemify form)
|
|
form))
|
|
(schemify-sexp node env)))
|
|
|
|
(define schemifiers
|
|
(make-operator-table (lambda (node env)
|
|
(let ((form (node-form node)))
|
|
(if (list? form)
|
|
(map (lambda (f) (schemify1 f env)) form)
|
|
form)))))
|
|
|
|
(define (define-schemifier name type proc)
|
|
(operator-define! schemifiers name type proc))
|
|
|
|
(define-schemifier 'name 'leaf
|
|
(lambda (node env)
|
|
(name->qualified (node-form node) env)))
|
|
|
|
(define-schemifier 'quote syntax-type
|
|
(lambda (node env)
|
|
(let ((form (node-form node)))
|
|
(list (schemify1 (car form) env) (cadr form)))))
|
|
|
|
; Convert an alias (generated name) to S-expression form ("qualified name").
|
|
;
|
|
; As an optimization, we elide intermediate steps in the lookup path
|
|
; when possible. E.g.
|
|
; #(>> #(>> #(>> define-record-type define-accessors)
|
|
; define-accessor)
|
|
; record-ref)
|
|
; is replaced with
|
|
; #(>> define-record-type record-ref)
|
|
|
|
(define (name->qualified name env)
|
|
(if env
|
|
(if (generated? name)
|
|
(if (same-denotation? (lookup env name)
|
|
(lookup env (generated-symbol name)))
|
|
(generated-symbol name) ;+++
|
|
(make-qualified
|
|
(let recur ((name (generated-parent-name name)))
|
|
(if (generated? name)
|
|
(let ((parent (generated-parent-name name)))
|
|
(if (let ((b1 (lookup env name))
|
|
(b2 (lookup env parent)))
|
|
(or (same-denotation? b1 b2)
|
|
(and (binding? b1)
|
|
(binding? b2)
|
|
(let ((s1 (binding-static b1))
|
|
(s2 (binding-static b2)))
|
|
(and (transform? s1)
|
|
(transform? s2)
|
|
(eq? (transform-env s1)
|
|
(transform-env s2)))))))
|
|
(recur parent) ;+++
|
|
`#(>> ,(recur parent)
|
|
,(generated-symbol name))))
|
|
name))
|
|
(generated-symbol name)))
|
|
name)
|
|
(desyntaxify name)))
|
|
|
|
; lambda, let-syntax, letrec-syntax...
|
|
|
|
(define-schemifier 'letrec syntax-type
|
|
(lambda (node env)
|
|
(let ((form (node-form node)))
|
|
`(letrec ,(map (lambda (spec)
|
|
`(,(car spec) ,(schemify1 (cadr spec) env)))
|
|
(cadr form))
|
|
,@(map (lambda (f) (schemify1 f env))
|
|
(cddr form))))))
|
|
|
|
(define (schemify-sexp thing env)
|
|
(cond ((name? thing)
|
|
(name->qualified thing env))
|
|
((pair? thing)
|
|
(let ((x (schemify-sexp (car thing) env))
|
|
(y (schemify-sexp (cdr thing) env)))
|
|
(if (and (eq? x (car thing))
|
|
(eq? y (cdr thing)))
|
|
thing ;+++
|
|
(cons x y))))
|
|
((vector? thing)
|
|
(let ((new (make-vector (vector-length thing) #f)))
|
|
(let loop ((i 0) (same? #t))
|
|
(if (>= i (vector-length thing))
|
|
(if same? thing new) ;+++
|
|
(let ((x (schemify-sexp (vector-ref thing i) env)))
|
|
(vector-set! new i x)
|
|
(loop (+ i 1)
|
|
(and same? (eq? x (vector-ref thing i)))))))))
|
|
(else thing)))
|
|
|
|
|
|
; Qualified names
|
|
|
|
(define (make-qualified transform-name sym)
|
|
(vector '>> transform-name sym))
|
|
|
|
(define (qualified? thing)
|
|
(and (vector? thing)
|
|
(= (vector-length thing) 3)
|
|
(eq? (vector-ref thing 0) '>>)))
|
|
|
|
(define (qualified-parent-name q) (vector-ref q 1))
|
|
(define (qualified-symbol q) (vector-ref q 2))
|