git.fiddlerwoaroof.com
csys/dump-interface.scm
4e987026
 ;;; 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)))