git.fiddlerwoaroof.com
import-export/init-modules.scm
4e987026
 ;;; This initializes the module ast structures.
 
 ;;; This requires that the module table be created and updated with new
 ;;; modules first.  *unit* must also be defined.
 
 ;;; Things initialized there:
 ;;;  all tables in the module structure
 ;;;  the module slot of all import declarations and entity-modules
 ;;;  The import Prelude is added when necessary
 ;;;  Empty export lists are explicated
 
 (define (init-module-structure)
   (when (not (eq? (module-type *module*) 'extension))
     ;; If this is an extension, the incremental compiler has already
     ;; filled in the compilation unit.
     (setf (module-unit *module*) *unit*))
   ;;; This processes the annotations.  Annotations used at the top
   ;;; level of the module:
   ;;;   {-#PRELUDE#-} : this contains definitions in the Haskell prelude
   (setf (module-prelude? *module*) '#f)
   (setf (module-interface-codefile *module*) '())
   (dolist (a (module-annotations *module*))
     (when (annotation-value? a)
       (let ((name (annotation-value-name a)))
 	(cond ((eq? name '|Prelude|)
 	       (setf (module-prelude? *module*) '#t))))))
   (cond ((eq? (module-type *module*) 'interface)
 	 (setf (module-exported-modules *module*) (list *module*))
 	 (process-interface-imports *module*))
 	((eq? (module-type *module*) 'standard)
 	 (init-standard-module))))
 
 (define (init-standard-module)
    (let ((seen-prelude? '#f))
     (dolist (import (module-imports *module*))
       (let* ((name (import-decl-module-name import))
 	     (imported-mod (locate-module name)))
 	(when (eq? name '|Prelude|)
 	   (setf seen-prelude? '#t))
 	(if (eq? imported-mod '#f)
 	    (signal-undefined-module-import name)
 	    (setf (import-decl-module import) imported-mod))
 	(when (eq? name *module-name*)
 	  (signal-self-import name))))
     (when (null? (module-exports *module*))
 	(setf (module-exports *module*)
 	      (list (make entity-module (name *module-name*)
 			                (module *module*)))))
     (when (not seen-prelude?)
       (let ((prelude (locate-module '|Prelude|)))
 	(cond ((eq? prelude '#f)
 	       (signal-missing-prelude))
 	      ((module-prelude? *module*)
 	       (setf (module-uses-standard-prelude? *module*) '#f)
 	       (add-imported-module prelude))
 	      (else
 	       (setf (module-uses-standard-prelude? *module*) '#t)
 	       (let ((fix-table (module-fixity-table *module*)))
 		 (table-for-each (lambda (k v)
 				   (setf (table-entry fix-table k) v))
 				 *prelude-fixity-table*))))))
     (let ((prelude-core (locate-module '|PreludeCore|)))
        (if (eq? prelude-core '#f)
 	   (signal-missing-prelude-core)
 	   (when (module-prelude? *module*)
 		 (add-imported-module prelude-core))))
     (setf (module-exports *module*)
 	  (filter-complete-module-exports (module-exports *module*))))
     )
 
 
 (define (add-imported-module module)
   (setf (module-imports *module*)
 	(cons (make import-decl
 		    (module-name (module-name module))
 		    (module module)
 		    (mode 'all)
 		    (specs '())
 		    (renamings '()))
 	      (module-imports *module*))))
 
 (define (filter-complete-module-exports exports)
   (if (null? exports)
       '()
       (let ((export (car exports))
 	    (others (filter-complete-module-exports (cdr exports))))
 	(if (is-type? 'entity-module export)
 	    (let* ((name (entity-name export))
 		   (exported-mod (locate-module name)))
 	      (when (eq? exported-mod '#f)
 		(signal-undefined-module-export name))
 	      (push exported-mod (module-exported-modules *module*))
 	      (when (not (memq name
 			   (cons *module-name*
 				 (map
 				   (lambda (import)
 				     (import-decl-module-name import))
 				   (module-imports *module*)))))
 		(signal-export-not-imported name))
 	      others)
 	    (cons export others)))))
 
 (define (process-interface-imports module)
   (let ((imports '()))
     (dolist (i (module-imports module))
       (let ((module (import-decl-module-name i))
 	    (renamings (import-decl-renamings i)))
 	(dolist (s (import-decl-specs i))
           (let* ((n (entity-name s))
 		 (n1 (do-interface-rename n renamings)))
 	    (when (assq n1 imports)
                (signal-multiple-imports n1))
 	    (push (tuple n1 (tuple module n)) imports)
 	    (cond ((entity-class? s)
 		   (dolist (m (entity-class-methods s))
                      (let ((m1 (do-interface-rename m renamings)))
 		       (when (assq m1 imports)
                           (signal-multiple-imports m1))
 		       (push (tuple m1 (tuple module m)) imports))))
 		  ((entity-datatype? s)
 		   (dolist (m (entity-datatype-constructors s))
                      (let ((m1 (do-interface-rename m renamings)))
 		       (when (assq m1 imports)
                           (signal-multiple-imports m1))
 		       (push (tuple m1 (tuple module m)) imports)))))))))
     (setf (module-interface-imports module) imports)))
 
 (define (signal-multiple-imports name)
   (phase-error 'multuple-interface-import
     "Interface file has more than one definition of ~A~%" name))
 
 (define (do-interface-rename name renamings)
   (if (has-con-prefix? (symbol->string name))
       (let* ((n1 (remove-con-prefix/symbol name))
 	     (res (locate-renaming n1 renamings)))
 	(if (eq? res '#f)
 	    name
 	    (add-con-prefix/symbol (renaming-to res))))
       (let ((res (locate-renaming name renamings)))
 	(if (eq? res '#f)
 	    name
 	    (renaming-to res)))))