scsh-0.6/ps-compiler/prescheme/display.scm

224 lines
6.1 KiB
Scheme

; Copyright (c) 1994 by Richard Kelsey. See file COPYING.
; Data must be done last as it may contain references to the other stuff.
(define (display-forms-as-scheme forms out)
(receive (data other)
(partition-list (lambda (f)
(and (node? (form-value f))
(literal-node? (form-value f))))
forms)
(for-each (lambda (f)
(display-form-as-scheme f (schemify (form-value f)) out))
other)
(for-each (lambda (f)
(display-data-form-as-scheme f out))
data)))
(define form-value (structure-ref forms form-value))
(define form-var (structure-ref forms form-var))
(define literal-node? (node-predicate 'literal #f))
(define (display-form-as-scheme f value out)
(cond ((unspecific? value)
(p `(define ,(get-form-name f)) out)
(newline out))
((or (external-value? value)
(memq 'closed-compiled-primitive (variable-flags (form-var f))))
(values))
(else
(p `(define ,(get-form-name f) ,value)
out)
(newline out))))
(define (display-data-form-as-scheme f out)
(let* ((value (clean-literal (node-form (form-value f))))
(value (if (and (quoted? value)
(not (or (list? (cadr value))
(vector? (cadr value)))))
(cadr value)
value)))
(display-form-as-scheme f value out)))
(define (get-form-name form)
(name->symbol (get-variable-name (form-var form))))
(define (schemify node)
(if (node? node)
((operator-table-ref schemifiers (node-operator-id node))
node)
(schemify-sexp node)))
(define unspecific?
(let ((x (if #f #t)))
(lambda (y)
(eq? x y))))
(define schemifiers
(make-operator-table (lambda (node)
(let ((form (node-form node)))
(if (list? form)
(map schemify form)
form)))))
(define (define-schemifier name type proc)
(operator-define! schemifiers name type proc))
(define-schemifier 'name 'leaf
(lambda (node)
(cond ((node-ref node 'binding)
=> (lambda (binding)
(let ((var (binding-place binding)))
(if (variable? var)
(get-variable-name var)
(desyntaxify (node-form node))))))
(else
(name->symbol (node-form node))))))
; Rename things that have differ in Scheme and Pre-Scheme
(define aliases
(map (lambda (s)
(cons s (string->symbol (string-append "ps-" (symbol->string s)))))
'(read-char peek-char write-char newline
open-input-file open-output-file
close-input-port close-output-port)))
(define (get-variable-name var)
(cond ((and (generated-top-variable? var)
(not (memq 'closed-compiled-primitive (variable-flags var))))
(string->symbol (string-append (symbol->string
(name->symbol (variable-name var)))
"."
(number->string (variable-id var)))))
((assq (variable-name var) aliases)
=> cdr)
(else
(variable-name var))))
(define (name->symbol name)
(if (symbol? name)
name
(string->symbol (string-append (symbol->string (generated-symbol name))
"."
(number->string (generated-uid name))))))
(define-schemifier 'quote #f
(lambda (node)
(list 'quote (cadr (node-form node)))))
(define-schemifier 'literal #f
(lambda (node)
(let ((form (node-form node)))
(cond ((primop? form)
(primop-id form))
((external-value? form)
(let ((string (external-value-string form)))
(if (string=? string "(long(*)())")
'integer->procedure
(string->symbol (external-value-string form)))))
((external-constant? form)
`(enum ,(external-constant-enum-name form)
,(external-constant-name form)))
(else
(schemify-sexp form))))))
(define-schemifier 'unspecific #f
(lambda (node)
''unspecific))
; Used for primitives in non-call position. The CDR of the form is a
; variable that will be bound to the primitive's closed-compiled value.
(define-schemifier 'primitive #f
(lambda (node)
(let ((form (node-form node)))
(cond ((pair? form)
(get-variable-name (cdr form))) ; non-call position
((assq (primitive-id form) aliases)
=> cdr)
(else
(primitive-id form))))))
; lambda, let-syntax, letrec-syntax...
(define-schemifier 'letrec #f
(lambda (node)
(let ((form (node-form node)))
`(letrec ,(map (lambda (spec)
`(,(schemify (car spec)) ,(schemify (cadr spec))))
(cadr form))
,@(map (lambda (f) (schemify f))
(cddr form))))))
(define-schemifier 'lambda #f
(lambda (node)
(let ((form (node-form node)))
`(lambda ,(let label ((vars (cadr form)))
(cond ((pair? vars)
(cons (schemify (car vars))
(label (cdr vars))))
((null? vars)
'())
(else
(schemify vars))))
,@(map schemify (cddr form))))))
(define-schemifier 'goto #f
(lambda (node)
(map schemify (cdr (node-form node)))))
(define (schemify-sexp thing)
(cond ((name? thing)
(desyntaxify thing))
((primop? thing)
(primop-id thing))
((primitive? thing)
(primitive-id thing))
((variable? thing)
(get-variable-name thing))
((pair? thing)
(let ((x (schemify-sexp (car thing)))
(y (schemify-sexp (cdr thing))))
(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))))
(vector-set! new i x)
(loop (+ i 1)
(and same? (eq? x (vector-ref thing i)))))))))
(else thing)))
(define (clean-literal thing)
(cond ((name? thing)
(desyntaxify thing))
((variable? thing)
(get-variable-name thing))
((external-constant? thing)
`(enum ,(external-constant-enum-name thing)
,(external-constant-name thing)))
((pair? thing)
(let ((x (clean-literal (car thing)))
(y (clean-literal (cdr thing))))
(if (and (quoted? x) (quoted? y))
`(quote (,(cadr x) . ,(cadr y)))
`(cons ,x ,y))))
((vector? thing)
(let ((elts (map clean-literal (vector->list thing))))
(if (every? quoted? elts)
`(quote ,(list->vector (map cadr elts)))
`(vector . ,elts))))
(else
`(quote ,thing))))
(define (quoted? x)
(and (pair? x)
(eq? (car x) 'quote)))