git.fiddlerwoaroof.com
Raw Blame History
;;; This is the main driver for the import / export routine

(define (import-export modules)
  (walk-modules modules
        (lambda () (add-module-to-symbol-table *module*)))
  (walk-modules modules
      (lambda () (init-module-structure)))
  (import-export/fixpoint modules '#t)
  (walk-modules modules (lambda () (check-missing-names)))
  (when (memq 'import (dynamic *printers*))
    (show-export-tables modules))
 modules)

(define (import-export/interface modules)
  (walk-modules modules
        (lambda () (add-module-to-symbol-table *module*)))
  (walk-modules modules
      (lambda () (init-module-structure)))
  (walk-modules modules
      (lambda () (create-top-definitions)
	         (attach-fixities))))

(define (import-export/fixpoint modules initial-cycle?)
  (setf *new-exports-found?* '#f)
  (walk-modules modules
   (lambda ()
     (setf (module-fresh-exports *module*) '())
     (when initial-cycle?
       (create-top-definitions)
       (attach-fixities)
       (import-non-local))
     (locally-import)
     (locally-export)))
  (when *new-exports-found?*
      (import-export/fixpoint modules '#f)))

;;; This does the non-local importing from previously defined modules

(define (import-non-local)
  (setf (module-imports *module*)
	(process-non-local-imports (module-imports *module*))))

(define (process-non-local-imports imports)
  (if (null? imports)
      '()
      (let* ((import (car imports)))
        (with-slots import-decl (module mode specs renamings) import
	  (cond ((eq? *unit* (module-unit module))
		 (cons import (process-non-local-imports (cdr imports))))
		((eq? mode 'all)
		 (import-all-entities module specs renamings import)
		 (process-non-local-imports (cdr imports)))
		(else
		 (import-named-entities module specs renamings import)
		 (process-non-local-imports (cdr imports))))))))

(define (import-all-entities module hiding renamings import-decl)
  (table-for-each
   (lambda (name group)
     (declare (ignore name))
     (cond ((in-hiding-list? group hiding)
	    (setf hiding (remove-entity group hiding)))
	   (else
	    (import-group (rename-group group renamings) module))))
   (module-export-table module))
  (when (not (null? hiding))
    (remember-context import-decl
      (dolist (h hiding)
	(signal-unused-hiding (entity-name h) (module-name module)))))
  (find-unused-renamings renamings import-decl))

(define (import-named-entities mod specs renamings import-decl)
  (dolist (entity specs)
    (let ((group (locate-entity/export-table entity mod '#t)))
      (when (not (eq? group 'error))
	(setf group (rename-group group renamings))
	(import-group group mod))))
  (find-unused-renamings renamings import-decl))

;;; This takes a module and processes the import declarations, moving as
;;; many entities from the freshly exported components of other modules into
;;; the current module.

(define (locally-import)
  (dolist (import (module-imports *module*))
    (with-slots import-decl (module mode specs renamings) import
      (if (eq? mode 'all)
	  (import-fresh-entities import module specs renamings)
	  (setf (import-decl-specs import)
		(import-entities specs module renamings))))))

(define (import-fresh-entities import module hiding renamings)
  (dolist (group (module-fresh-exports module))
    (cond ((in-hiding-list? group hiding)
	    (setf hiding (remove-entity group hiding)))
	   (else
	    (import-group (rename-group group renamings) module))))
  (setf (import-decl-specs import) hiding))

(define (import-entities entities module renamings)
  (if (null? entities)
      '()
      (let ((group (locate-entity/export-table (car entities) module '#f)))
	(cond ((eq? group 'not-found)
	       (cons (car entities)
		     (import-entities (cdr entities) module renamings)))
	      ((eq? group 'error)
	       (import-entities (cdr entities) module renamings))
	      (else
	       (setf group (rename-group group renamings))
	       (import-group group module)
	       (import-entities (cdr entities) module renamings))))))

;;; This imports a group into *module*.  module is the place the group is
;;; taken from.

(define (import-group group module)
  (when (memq module (module-exported-modules *module*))
    (export-group group))
  (dolist (n-d group)
    (insert-top-definition (tuple-2-1 n-d) (tuple-2-2 n-d))))

;;; This takes as yet unresolved exports and moves them to the export table.

(define (locally-export)
  (setf (module-exports *module*)
	(export-entities (module-exports *module*))))

(define (export-entities entities)
  (if (null? entities)
      '()
      (let* ((entity (car entities))
	     (group (locate-entity entity)))
	(cond ((eq? group 'error)
	       (export-entities (cdr entities)))
	      ((eq? group 'not-found)
	       (cons entity (export-entities (cdr entities))))
	      (else
	       (export-group group)
	       (export-entities (cdr entities)))))))


;;; This moves a group into the export table.  If this export is new,
;;; a flag is set.

(define (export-group group)
  (let* ((export-table (module-export-table *module*))
	 (old-group (table-entry export-table (group-name group))))
    (when (or (eq? old-group '#f)
	      (and (hidden-constructors? old-group)
		   (not (hidden-constructors? group))))
      (setf (table-entry export-table (group-name group)) group)
      (dolist (n-d group)
        (setf (def-exported? (tuple-2-2 n-d)) '#t))
      (push group (module-fresh-exports *module*))
      (setf *new-exports-found?* '#t))))

(define (show-export-tables modules)
  (walk-modules modules
    (lambda ()
      (format '#t "~%Exports from module ~A~%" *module-name*)
      (let ((exports '()))
	(table-for-each (lambda (key val)
			  (push (cons key val) exports))
			(module-export-table *module*))
	(setf exports (sort-list exports
				 (lambda (x y)
				   (string-ci<? (symbol->string (car x))
						(symbol->string (car y))))))
	(dolist (e exports)
          (print-exported-group (car e) (group-definition (cdr e))
				(cdr (cdr e))))))))

(define (print-exported-group name def extras)
  (if (eq? (def-module def) *module-name*)
      (format '#t " ")
      (format '#t "*"))
  (cond ((synonym? def)
	 (format '#t "type  "))
	((algdata? def)
	 (format '#t "data  "))
	((class? def)
	 (format '#t "class "))
	(else
	 (format '#t "      ")))
  (format '#t "~A" name)
  (when (not (eq? name (def-name def)))
     (format '#t "[~A]" (def-name def)))
  (when extras
     (format '#t " (")
     (print-exported-group-1 extras (algdata? def)))
  (format '#t "~%"))

(define (print-exported-group-1 extras alg?)
  (let* ((name (tuple-2-1 (car extras)))
	 (ns (symbol->string name))
	 (def (tuple-2-2 (car extras))))
    (format '#t "~A" (if alg? (remove-con-prefix ns) ns))
    (when (not (eq? name (def-name def)))
      (let ((name1 (symbol->string (def-name def))))
	  (format '#t "[~A]" (if alg? (remove-con-prefix name1) name1))))
    (if (null? (cdr extras))
	(format '#t ")")
	(begin
	  (format '#t ",")
	  (print-exported-group-1 (cdr extras) alg?)))))