summaryrefslogtreecommitdiff
path: root/csys/dump-interface.scm
diff options
context:
space:
mode:
Diffstat (limited to 'csys/dump-interface.scm')
-rw-r--r--csys/dump-interface.scm800
1 files changed, 800 insertions, 0 deletions
diff --git a/csys/dump-interface.scm b/csys/dump-interface.scm
new file mode 100644
index 0000000..37b3bbd
--- /dev/null
+++ b/csys/dump-interface.scm
@@ -0,0 +1,800 @@
+;;; dump-interface.scm -- interface file writer/loader
+;;;
+;;; author : John & Sandra
+;;; date : 8 Jul 1992
+;;;
+;;; This writes binary interface files. A binary interface file is just
+;;; a lisp (mumble) source file which directly builds the ast structure
+;;; created by a compilation. These files could be stored in either
+;;; source or binary (compiled lisp) form.
+
+;;; An interface may reference entities defined in other interfaces.
+;;; To ensure consistancy between when an interface is written and
+;;; when it is read back in, a stamp is assigned to all interface files
+;;; which serves as a unique id. The stamps of all imported units are
+;;; saved and examined at load time.
+
+
+
+;;;==================================================================
+;;; Interface to compilation system
+;;;==================================================================
+
+
+;;; For compiled code, don't actually write out all the source code.
+;;; Use a magic macro to memoize the form to be compiled.
+
+(define *form-to-compile* '#f)
+(define *magic-file-to-compile* "$HASKELL/bin/magic.scm")
+
+
+;;; The output from compiling the prelude can completely overwhelm
+;;; the Lisp compiler. If this variable is a number, it specifies
+;;; a "reasonable" number of top-level forms which can be compiled
+;;; and write-compiled-code-file will try to break up the input
+;;; code automagically.
+
+(define *magic-chunk-size* '#f)
+
+
+;;; This is called to write both the code file and the interface file.
+
+(define (write-compiled-code-file filename code code-quality chunk-size)
+ (let ((phase-start-time (get-run-time))
+ (forms (flatten-forms code)))
+ (dynamic-let ((*magic-chunk-size*
+ (or chunk-size (dynamic *magic-chunk-size*)))
+ (*code-quality*
+ (or code-quality (dynamic *code-quality*))))
+ (if (or (not (dynamic *magic-chunk-size*))
+ (<= (the fixnum (length forms))
+ (the fixnum (dynamic *magic-chunk-size*))))
+ (write-compiled-code-file-aux filename `(begin ,@forms))
+ (with-compilation-unit ()
+ (write-compiled-code-file-aux
+ filename
+ `(begin
+ ,@(map (lambda (f) `(load ,f))
+ (write-compiled-code-file-split filename forms)))
+ ))))
+ (when (memq 'phase-time *printers*)
+ (let* ((current-time (get-run-time))
+ (elapsed-time (- current-time phase-start-time)))
+ (format '#t "Lisp compilation complete: ~A seconds~%" elapsed-time)))
+ ))
+
+(define (write-compiled-code-file-split filename forms)
+ (let ((place (filename-place filename))
+ (name (filename-name filename))
+ (type (filename-type filename))
+ (result '()))
+ (do ((i 0 (1+ i)))
+ ((null? forms))
+ (multiple-value-bind (head tail)
+ (split-list forms (dynamic *magic-chunk-size*))
+ (let ((fname
+ (assemble-filename
+ place (format '#f "~a-part~a" name i) type)))
+ (push fname result)
+ (write-compiled-code-file-aux fname `(begin ,@head))
+ (setf forms tail))))
+ (nreverse result)))
+
+(define (flatten-forms code)
+ (if (and (pair? code) (eq? (car code) 'begin))
+ (nreverse (flatten-forms-aux (cdr code) '()))
+ (list code)))
+
+(define (flatten-forms-aux forms result)
+ (dolist (f forms)
+ (if (and (pair? f) (eq? (car f) 'begin))
+ (setf result (flatten-forms-aux (cdr f) result))
+ (push f result)))
+ result)
+
+
+(define (write-compiled-code-file-aux filename code)
+ (dynamic-let ((*form-to-compile* code))
+ (compile-file (dynamic *magic-file-to-compile*) filename)))
+
+(define-syntax (magic-form-to-compile)
+ (dynamic *form-to-compile*))
+
+
+;;; Writing source code is good for debugging purposes, but slow.
+;;; The *print-circle* and *print-shared* flags have to be set because
+;;; the code printed out may contain gensyms, and this will ensure
+;;; that the code can be read in again.
+
+(define (write-interpreted-code-file filename code hairy?)
+ (dynamic-let ((*print-circle* '#t)
+ (*print-shared* '#t))
+ (call-with-output-file
+ filename
+ (lambda (port)
+ (if hairy?
+ (pprint-flatten code port)
+ (print-flatten code port))))))
+
+
+;;; This attempts to read a compiled interface for a unit. This is
+;;; done whenever the unit file is newer than the source file. If
+;;; imported units have changed, the load will fail and recompilation
+;;; will be attempted.
+;;; The caller is responsible for making sure that the interface file exists
+;;; and for making sure that the interface file is up-to-date with
+;;; respect to imported modules and that all the imported modules are
+;;; known.
+
+;;; These variables are assigned by the code in the dump file.
+
+(define *modules-loaded* '())
+(define *modules-imported* '())
+(define *defs-referenced* '())
+(define *saved-cse-values* '())
+(define *writer-version* '())
+
+(define (read-binary-interface unit)
+ (dynamic-let ((*modules-loaded* '())
+ (*modules-imported* '())
+ (*defs-referenced* '())
+ (*saved-cse-values* '())
+ (*writer-version* '()))
+ (let ((file-date
+ (load-more-recent-file (ucache-cifile unit) (ucache-sifile unit))))
+ (cond ((string=? *writer-version* *haskell-compiler-version*)
+ (setf (ucache-idate unit) file-date)
+ (setf (ucache-modules unit) (vector->list *modules-loaded*))
+ (setf (ucache-ifile-loaded unit) '#t)
+ '#t)
+ (else
+ (signal-incompatible-interface-file (ucache-cifile unit))
+ '#f)))))
+
+(define (signal-incompatible-interface-file filename)
+ (fatal-error 'incompatible-interface-file
+ "File ~A~%~
+ was written by a different version of the Haskell system.~%~
+ You must remove it and recompile."
+ filename))
+
+
+(define (load-more-recent-file cfile sfile)
+ (cond ((file-exists? cfile)
+ (if (or (not (file-exists? sfile))
+ (> (file-write-date cfile)
+ (file-write-date sfile)))
+ (load-compiled-interface-file cfile)
+ (load-interpreted-interface-file sfile)))
+ ((file-exists? sfile)
+ (load-interpreted-interface-file sfile))
+ (else
+ (signal-file-not-found cfile))))
+
+(define (load-interpreted-interface-file file)
+ (load file)
+ (file-write-date file))
+
+(define (load-compiled-interface-file file)
+ (load file)
+ (file-write-date file))
+
+
+;;;==================================================================
+;;; Dump code generator
+;;;==================================================================
+
+;;; Globals
+
+(define *dump-defs* '())
+(define *dump-slot-init-code* '())
+(define *dump-def-counter* 0)
+(define *dump-def-code-table* (make-table))
+(define *cse-objects* '())
+(define *cse-value-num* 0)
+(define *cse-object-num* '())
+(define *gtype-class-index* '())
+(define *context-class-index* '())
+(define *gtype-tycon-index* '())
+(define *gtype-list-index* '())
+(define *gtype-index* '())
+(define *number-vars-dumped* 0)
+
+
+(define-syntax (def-dump-code def)
+ `(table-entry *dump-def-code-table* ,def))
+
+;;; This saves slot initialization code.
+
+(define (add-dump-init code)
+ (push code *dump-slot-init-code*))
+
+
+;;; Here is the top-level call.
+
+(define (create-dump-code unit modules load-prelude?)
+ (dynamic-let ((*unit* (module-unit (car modules)))
+ (*dump-defs* '())
+ (*dump-slot-init-code* '())
+ (*dump-def-counter* 0)
+ (*dump-def-code-table* (make-table))
+ (*cse-objects* '())
+ (*cse-object-num* *num-saved-gtyvars*)
+ (*gtype-class-index* '())
+ (*context-class-index* '())
+ (*gtype-tycon-index* '())
+ (*gtype-list-index* '())
+ (*gtype-index* '())
+ (*number-vars-dumped* 0)
+ (*number-types-dumped* 0)
+ (*number-classes-dumped* 0))
+ (let ((res (create-dump-code-aux unit modules load-prelude?)))
+ (when (memq 'dumper (dynamic *printers*))
+ (pprint* res))
+ (when (memq 'dump-stat (dynamic *printers*))
+ (format '#t
+ "~&Dumped ~A definitions, ~A type objects, and ~A classes.~%"
+ *number-vars-dumped* *number-types-dumped*
+ *number-classes-dumped*)
+ (format '#t "Used ~A definitions and ~A type cells.~%"
+ *dump-def-counter* (length *cse-objects*)))
+ res)))
+
+;;; This assumes all modules are in the same compilation unit and that
+;;; *unit* is set to that unit.
+;;; imod-code establishes local bindings for all the imported modules.
+;;; dmod-code establishes local bindings for all the modules defined in
+;;; this compilation unit.
+
+(define (create-dump-code-aux unit modules load-prelude?)
+ (let* ((imod-counter 0)
+ (imod-alist '())
+ (explicit-imports (collect-all-imported-modules unit))
+ (all-imports (if load-prelude?
+ (append (collect-prelude-modules) explicit-imports)
+ explicit-imports))
+ (imod-code (map (lambda (m)
+ (push (cons (module-name m) imod-counter)
+ imod-alist)
+ (incf imod-counter)
+ `(locate-module ',(module-name m)))
+ all-imports))
+ (dmod-counter 0)
+ (dmod-alist '())
+ (dmod-code (map (lambda (m)
+ (push (cons (module-name m) dmod-counter)
+ dmod-alist)
+ (incf dmod-counter)
+ `(make module
+ (unit ',(module-unit m))
+ (name ',(module-name m))
+ (type ',(module-type m))))
+ modules)))
+ ;; This actually does most of the work. It dumps the module asts by
+ ;; placing inits for each slot into *dump-slot-init-code*. A list of
+ ;; definitions referenced is maintained in *dump-defs*.
+ (dolist (m modules)
+ (dump-module m (cdr (assq (module-name m) dmod-alist))))
+ ;; This creates the final code
+ `(begin
+ (setf *writer-version* ',*haskell-compiler-version*)
+ (setf *modules-imported* (vector ,@imod-code))
+ (setf *modules-loaded* (vector ,@dmod-code))
+ ;; This sets the elements individually instead of using the vector
+ ;; function, because the vector may be longer than
+ ;; call-arguments-limit.
+ (setf *defs-referenced*
+ (make-vector ,(dynamic *dump-def-counter*)))
+ ,@(map (lambda (d)
+ `(setf ,(def-dump-code d)
+ ,(make-def-init-code d imod-alist dmod-alist)))
+ *dump-defs*)
+ ,@(cse-init-code)
+ ,@(dynamic *dump-slot-init-code*)
+ )
+ ))
+
+
+;;; Runtime support
+
+(define-syntax (lookup-imported-mod i)
+ `(vector-ref *modules-imported* ,i))
+
+(define-syntax (lookup-defined-mod i)
+ `(vector-ref *modules-loaded* ,i))
+
+(define (set-export-from-def-vector table key index)
+ (setf (table-entry table key)
+ (list (cons key (vector-ref *defs-referenced* index)))))
+
+(define (set-export-from-def table key def)
+ (setf (table-entry table key)
+ (list (cons key def))))
+
+(define (set-symtab-from-def-vector table key index)
+ (setf (table-entry table key)
+ (vector-ref *defs-referenced* index)))
+
+(define (init-variable-slots var exported? toplevel? type simple? strict?)
+ (setf (def-exported? var) exported?)
+ (setf (var-toplevel? var) toplevel?)
+ (setf (var-type var) type)
+ (setf (var-simple? var) simple?)
+ (setf (var-strict? var) strict?)
+ var)
+
+(define (init-function-slots var exported? toplevel? type simple? strict?
+ arity strictness opt-entry)
+ (setf (def-exported? var) exported?)
+ (setf (var-toplevel? var) toplevel?)
+ (setf (var-type var) type)
+ (setf (var-simple? var) simple?)
+ (setf (var-strict? var) strict?)
+ (setf (var-arity var) arity)
+ (setf (var-strictness var) strictness)
+ (setf (var-optimized-entry var) opt-entry)
+ var)
+
+(define (init-method-var-slots var class default method-signature)
+ (setf (method-var-class var) class)
+ (setf (method-var-default var) default)
+ (setf (method-var-method-signature var) method-signature)
+ var)
+
+(define (init-constructor-slots
+ con arity types signature tag alg fixity infix?)
+ (setf (con-arity con) arity)
+ (setf (con-types con) types)
+ (setf (con-signature con) signature)
+ (setf (con-tag con) tag)
+ (setf (con-alg con) alg)
+ (setf (con-fixity con) fixity)
+ (setf (con-infix? con) infix?)
+ (dotimes (i arity)
+ (push '#f (con-slot-strict? con)))
+ con)
+
+(define (make-new-instance algdata tyvars class context gcontext dictionary m)
+ (make instance
+ (algdata algdata)
+ (tyvars tyvars)
+ (class class)
+ (context context)
+ (gcontext gcontext)
+ (dictionary dictionary)
+ (methods m)
+ (ok? '#t)))
+
+
+;;; This computes the transitive closure of all modules available to
+;;; a unit.
+
+(define (collect-all-imported-modules unit)
+ (collect-all-modules-1 (ucache-imported-units unit) '() '()))
+
+(define (collect-all-modules-1 units mods-so-far units-seen)
+ (cond ((null? units)
+ mods-so-far)
+ ((mem-string (car units) units-seen)
+ (collect-all-modules-1 (cdr units) mods-so-far units-seen))
+ (else
+ (let ((u (lookup-compilation-unit (car units))))
+ (collect-all-modules-1
+ (append (ucache-imported-units u) (cdr units))
+ (append (ucache-modules u) mods-so-far)
+ (cons (ucache-ufile u) units-seen))))
+ ))
+
+(define (collect-prelude-modules)
+ (let ((prelude-unit (lookup-compilation-unit *prelude-unit-filename*)))
+ (append (ucache-modules prelude-unit)
+ (collect-all-imported-modules prelude-unit))))
+
+(define (def->core-name-string def)
+ (if (con? def)
+ (remove-con-prefix (symbol->string (def-name def)))
+ (symbol->string (def-name def))))
+
+;;; This code returns the load time definition for an object. When the
+;;; object is a core symbol or in a different unit, previously
+;;; created definitions are returned. Otherwise, a new definition is
+;;; created.
+
+(define (make-def-init-code d imod-alist dmod-alist)
+ (declare (ignore dmod-alist))
+ (cond ((def-core? d)
+ `(core-symbol ,(def->core-name-string d)))
+ ((eq? (def-unit d) *unit*)
+ `(create-definition/inner
+ ',(def-module d)
+ ',(def-name d)
+ ',(cond ((method-var? d) 'method-var)
+ ((var? d) 'var)
+ ((con? d) 'con)
+ ((synonym? d) 'synonym)
+ ((algdata? d) 'algdata)
+ ((class? d) 'class))))
+ ((is-tuple-constructor? d)
+ `(tuple-constructor ,(tuple-constructor-arity d)))
+ ((is-tuple-tycon? d)
+ `(tuple-tycon ,(tuple-constructor-arity (car (algdata-constrs d)))))
+ (else
+ (let ((m (assq (def-module d) imod-alist)))
+ ;; This is a bogus error message. The problem is that nothing
+ ;; so far ensures units are closed under import/export: some
+ ;; modules may be referenced that are accidentally in the symbol
+ ;; table. The unif file for the current module needs to be
+ ;; updated when this happens.
+ (when (eq? m '#f)
+ (fatal-error 'symbol-not-in-unit
+ "Reference to symbol ~A in module ~A: not in compilation unit.~%"
+ (def-name d) (def-module d)))
+ `(table-entry
+ (module-symbol-table
+ (lookup-imported-mod ,(tuple-2-2 m)))
+ ',(def-name d))))
+ ))
+
+
+;;; Once a module has been compiled, most of its slots are useless.
+;;; All we really need to save are the identifying information,
+;;; symbol table, and export table.
+;;; Instances also need to be dumped here instead of with class objects;
+;;; this is because links can go across compilation unit boundaries.
+;;; They are fixed up when pulling units out of the cache.
+;;; The identifying info is stored when the module variable is bound.
+
+
+(define (dump-module module index)
+ (let ((mod-exp `(lookup-defined-mod ,index))
+ (save-all-symbols (or (eq? (module-type module) 'standard)
+ (eq? (module-name module) '|Prelude|))))
+ ;; Dump symbol table entries only for defs for which this is
+ ;; the "home" module. (In other words, ignore imported defs.)
+ ;; The purpose of this is to allow references from other
+ ;; interface files to be resolved; see make-def-init-code.
+ ;; Jcp: we need to save the complete symbol table for incremental
+ ;; compilation to work.
+ (let ((code '()))
+ (table-for-each
+ (lambda (key val)
+ (when (or save-all-symbols
+ (eq? (def-module val) (module-name module)))
+ (let ((def (dump-object val)))
+ (push
+ (if (and (pair? def)
+ (eq? (car def) 'vector-ref)
+ (eq? (cadr def) '*defs-referenced*))
+ `(set-symtab-from-def-vector table ',key ,(caddr def))
+ `(setf (table-entry table ',key) ,def))
+ code))))
+ (module-symbol-table module))
+ (add-dump-init `(setf (module-symbol-table ,mod-exp)
+ (let ((table (make-table))) ,@code table))))
+ ;; dump the fixity table - needed by the incremental compiler
+ (when save-all-symbols
+ (let ((code '()))
+ (table-for-each
+ (lambda (key val)
+ (push `(setf (table-entry table ',key)
+ (make-fixity ',(fixity-associativity val)
+ ',(fixity-precedence val)))
+ code))
+ (module-fixity-table module))
+ (add-dump-init `(setf (module-fixity-table ,mod-exp)
+ (let ((table (make-table))) ,@code table)))))
+ ;; Dump all export table entries. This is used by the import/export
+ ;; phase to resolve references.
+ (let ((code '()))
+ (table-for-each
+ (lambda (key val)
+ ;; val is an a-list of (sym . def) pairs.
+ ;; Look for shortcut to reduce size of generated code.
+ (push
+ (if (and (null? (cdr val))
+ (eq? (car (car val)) key))
+ (let ((def (dump-object (cdr (car val)))))
+ (if (and (pair? def)
+ (eq? (car def) 'vector-ref)
+ (eq? (cadr def) '*defs-referenced*))
+ `(set-export-from-def-vector table ',key ,(caddr def))
+ `(set-export-from-def table ',key ,def)))
+ `(setf (table-entry table ',key) ,(dump-object val)))
+ code))
+ (module-export-table module))
+ (add-dump-init `(setf (module-export-table ,mod-exp)
+ (let ((table (make-table))) ,@code table))))
+ ;; Dump the instances.
+ (add-dump-init `(setf (module-instance-defs ,mod-exp)
+ ,(dump-object (module-instance-defs module))))
+ (add-dump-init `(setf (module-default ,mod-exp)
+ ,(dump-object (module-default module))))
+ (add-dump-init `(setf (module-uses-standard-prelude? ,mod-exp)
+ ,(dump-object
+ (module-uses-standard-prelude? module))))
+ ))
+
+(define (make-fixity a p)
+ (make fixity (associativity a) (precedence p)))
+
+
+;;;==================================================================
+;;; Dump structure traversal
+;;;==================================================================
+
+;;; This is the general object dumper. It recognizes the basic Lisp
+;;; objects and dumps them. Given an object, this generates lisp code
+;;; to recreate the object at load time.
+
+(define (dump-object x)
+ (cond ((struct? x)
+ (dump x))
+ ((or (symbol? x) (null? x))
+ ;; Symbols and lists must be quoted.
+ `',x)
+ ((or (number? x)
+ (eq? x '#t)
+ (eq? x '#f)
+ (string? x) ; This makes dumped strings immutable.
+ (char? x))
+ ;; These objects are self-evaluating.
+ x)
+ ((list? x)
+ ;; True lists
+ `(list ,@(map (function dump-object) x)))
+ ((pair? x)
+ `(cons ,(dump-object (car x))
+ ,(dump-object (cdr x))))
+ ((vector? x)
+ `(vector ,@(map (function dump-object) (vector->list x))))
+ ((table? x)
+ `(list->table ,@(dump-object (table->list x))))
+ (else
+ (error "Don't know how to dump ~A." x))))
+
+
+;;; *** Should install the walker in the type descriptor.
+
+(define-walker dump)
+
+(define (dump x)
+ (call-walker dump x))
+
+
+
+;;;==================================================================
+;;; Dumpers for defs
+;;;==================================================================
+
+
+;;; All walkers for def structures should call this macro. The body
+;;; is invoked only if the def belongs to the current compilation unit
+;;; and hasn't already been traversed. Within the body, the
+;;; variable "v" is bound to a form that will evaluate to the
+;;; corresponding def structure at run time. This is also
+;;; the return value from the macro.
+
+(define-local-syntax (with-new-def (v d stat-var) . body)
+ (let ((temp (gensym))
+ (expvar (gensym)))
+ `(let ((,temp ,d)
+ (,expvar '#f))
+ (if (not (def-dump-code ,temp))
+ (begin
+ (cond ((not (def-core? ,temp))
+ (setf ,expvar
+ (list 'vector-ref
+ '*defs-referenced*
+ (dynamic *dump-def-counter*)))
+ (incf (dynamic *dump-def-counter*))
+ (push ,temp *dump-defs*))
+ (else
+ (setf ,expvar
+ (make-core-symbol-name
+ (def->core-name-string ,temp)))))
+ (setf (def-dump-code ,temp) ,expvar)
+ (when (eq? (def-unit ,temp) *unit*)
+ (incf (dynamic ,stat-var))
+ (let ((,v ,expvar))
+ ,@body))
+ ,expvar)
+ (def-dump-code ,temp)))))
+
+
+;;; This macro is used to save the value of a structure slot in the
+;;; initforms of the dump.
+
+(define-local-syntax (dump-def-slots obj-var type dexp slots)
+ `(add-dump-init
+ (list 'update-slots ',type ,dexp
+ ,@(map (lambda (s)
+ `(list ',s
+ (dump-object (struct-slot ',type ',s ,obj-var))))
+ slots)))
+ )
+
+
+
+(define-walker-method dump var (var)
+ (dump-var/n var))
+
+(define (dump-var/n var)
+ (with-new-def (dexp var *number-vars-dumped*)
+ (do-dump-var dexp var '#f)))
+
+(define (do-dump-var dexp var method-var?)
+ (let ((code '())
+ (exported? (def-exported? var))
+ (toplevel? (var-toplevel? var))
+ (type (var-type var))
+ (simple? (var-simple? var))
+ (strict? (var-strict? var))
+ (arity (var-arity var))
+ (strictness (var-strictness var))
+ (opt-entry (var-optimized-entry var))
+ (complexity (var-complexity var))
+ (fixity (var-fixity var))
+ (value (var-value var))
+ (inline-value (var-inline-value var))
+ (sel? (var-selector-fn? var)))
+ ;; Some slots are useless for vars that don't name functions.
+ (if (eqv? arity 0)
+ (push `(init-variable-slots var
+ ',exported?
+ ',toplevel?
+ ,(dump-object type)
+ ',simple?
+ ',strict?)
+ code)
+ (push `(init-function-slots var
+ ',exported?
+ ',toplevel?
+ ,(dump-object type)
+ ',simple?
+ ',strict?
+ ',arity
+ ,(dump-strictness strictness)
+ ',opt-entry)
+ code))
+ ;; These slots rarely need to be tweaked from the default.
+ (when sel?
+ (push `(setf (var-selector-fn? var) '#t) code))
+ (when complexity
+ (push `(setf (var-complexity var) ,complexity) code))
+ (when fixity
+ (push `(setf (var-fixity var) ,(dump-object fixity)) code))
+ ;; Save values of simple variables to permit inlining.
+ ;; Save values of structured constants to permit folding of flic-sel
+ ;; operations -- this is necessary to optimize dictionary lookups.
+ (when (or simple? sel?
+ (and value
+ (is-type? 'flic-app value)
+ (structured-constant-app?
+ (flic-app-fn value) (flic-app-args value))))
+ (push `(setf (var-value var) ,(dump-flic-top value)) code))
+ (when inline-value
+ (push `(setf (var-inline-value var) ,(dump-flic-top inline-value)) code))
+ ;; Save extra stuff for method vars
+ (when method-var?
+ (push `(init-method-var-slots var
+ ,(dump-object (method-var-class var))
+ ,(dump-object (method-var-default var))
+ ,(dump-object (method-var-method-signature var)))
+ code))
+ ;; Push the whole mess onto the init code.
+ (add-dump-init `(let ((var ,dexp)) ,@(nreverse code)))))
+
+
+(define-walker-method dump method-var (var)
+ (dump-method-var/n var))
+
+(define (dump-method-var/n var)
+ (with-new-def (dexp var *number-vars-dumped*)
+ (do-dump-var dexp var '#t)))
+
+(define-walker-method dump con (con)
+ (dump-con/n con))
+
+(define (dump-con/n con)
+ (with-new-def (dexp con *number-types-dumped*)
+ (add-dump-init
+ `(let ((con (init-constructor-slots
+ ,dexp
+ ,(con-arity con)
+ ,(dump-object (con-types con))
+ ,(dump-object (con-signature con))
+ ,(con-tag con)
+ ,(dump-object (con-alg con))
+ ,(dump-object (con-fixity con))
+ ',(con-infix? con))))
+ ,@(if (memq '#t (con-slot-strict? con))
+ `((setf (con-slot-strict? con) ',(con-slot-strict? con)))
+ '())
+ ,@(if (eq? (con-lisp-fns con) '())
+ '()
+ `((setf (con-lisp-fns con) ',(con-lisp-fns con))))
+ con))))
+
+;;; *** Could define similar init functions for other defs instead
+;;; *** of setting slots inline, but I'm lazy and they don't show up
+;;; *** nearly as often as the others.
+
+(define-walker-method dump algdata (alg)
+ (dump-algdata/n alg))
+
+(define (dump-algdata/n alg)
+ (with-new-def (dexp alg *number-types-dumped*)
+ (dump-def-slots alg algdata dexp
+ (arity n-constr constrs context tyvars signature
+ enum? tuple? real-tuple? implemented-by-lisp?))))
+
+(define-walker-method dump synonym (syn)
+ (dump-synonym/n syn))
+
+(define (dump-synonym/n syn)
+ (with-new-def (dexp syn *number-types-dumped*)
+ (dump-def-slots syn synonym dexp (arity args body))))
+
+(define-walker-method dump class (class)
+ (dump-class/n class))
+
+(define (dump-class/n class)
+ (with-new-def (dexp class *number-classes-dumped*)
+ (dump-def-slots class class dexp
+ (super super* tyvar method-vars selectors kind
+ n-methods dict-size))))
+
+
+;;;==================================================================
+;;; Dumpers for non-def AST structs
+;;;==================================================================
+
+;;; This section contains dumpers to handle type-related structs that
+;;; are referenced by the various def guys.
+
+
+(define-walker-method dump instance (o)
+ (if (not (instance-ok? o))
+ (error "Attempt to dump instance that's not ok!"))
+ `(make-new-instance
+ ,(dump-object (instance-algdata o))
+ ,(dump-object (instance-tyvars o))
+ ,(dump-object (instance-class o))
+ ,(dump-object (instance-context o))
+ ,(dump-object (instance-gcontext o))
+ ,(dump-object (instance-dictionary o))
+ ,(dump-object (instance-methods o))))
+
+
+
+(define-walker-method dump gtype (o)
+ (dump-gtype/cse o))
+
+(define-walker-method dump fixity (o)
+ `(**fixity ',(fixity-associativity o) ',(fixity-precedence o)))
+
+(define-walker-method dump tyvar (o)
+ `(**tyvar ',(tyvar-name o)))
+
+(define-walker-method dump class-ref (o)
+ `(**class/def ,(dump-object (class-ref-class o))))
+
+(define-walker-method dump context (o)
+ `(**context ,(dump-object (context-class o))
+ ,(dump-object (context-tyvar o))))
+
+(define-walker-method dump tycon (o)
+ `(**tycon/def ,(dump-object (tycon-def o))
+ ,(dump-object (tycon-args o))))
+
+(define-walker-method dump default-decl (o)
+ `(make default-decl (types ,(dump-object (default-decl-types o)))))
+
+(define-walker-method dump signature (o)
+ `(make signature (context ,(dump-object (signature-context o)))
+ (type ,(dump-object (signature-type o)))))
+
+;;; All ntyvars should be instantiated at this point
+
+; (define-walker-method dump ntyvar (o)
+; (dump-object (prune o)))