git.fiddlerwoaroof.com
Raw Blame History
;;; This file deals with entities in import / export lists

;;; This resolves an entity with the export table of a
;;; module.  It returns either a group, the symbol 'error, or the symbol
;;; 'not-found.  When force-error? is true, signal an error when
;;; the module is not found & return 'error.

(define (locate-entity/export-table entity mod force-error?)
  (let* ((name (entity-name entity))
	 (group (table-entry (module-export-table mod) name)))
    (if (eq? group '#f)
	(if (not force-error?)
	    'not-found
	    (signal-entity-not-found name (module-name mod)))
	(let ((def (group-definition group)))
	  (cond ((is-type? 'entity-var entity)
		 group)
		((is-type? 'entity-con entity)
		 (cond ((algdata? def)
			(strip-constructors group))
		       ((synonym? def)
			(signal-synonym-needs-dots name (module-name mod)))
		       (else
			(signal-wrong-definition
			  "type constructor" name (module-name mod)))))
		((is-type? 'entity-abbreviated entity)
		 (cond ((algdata? def)
			(cond ((hidden-constructors? group)
			       (if force-error?
				   (signal-abstract-type
				     name (module-name mod))
				   'not-found))
			      (else
			       group)))
		       ((or (class? def) (synonym? def))
			group)
		       (else
			(signal-wrong-definition
			  "class or datatype" name (module-name mod)))))
		((is-type? 'entity-class entity)
		 (if (class? def)
		     (match-constituents group (entity-class-methods entity)
					 entity "method")
		     (signal-wrong-definition "class" name (module-name mod))))
		((is-type? 'entity-datatype entity)
		 (if (algdata? def)
		     (match-constituents group
					 (entity-datatype-constructors entity)
					 entity "constructor")
		     (signal-wrong-definition
		       "data type" name (module-name mod))))
		(else
		 (error "Bad entity ~s." entity))
		)))))

(define (match-constituents group names entity what)
  (check-duplicates names entity)
  (dolist (n-d (cdr group))
    (when (not (memq (tuple-2-1 n-d) names))
      (signal-extra-constituent entity (tuple-2-1 n-d) what)))
  (dolist (name names)
    (when (not (assq name (cdr group)))
      (signal-missing-constituent entity name what)))
  group)


;;; The following routine locates an entity in the current module.
;;; It may return 'error, 'not-found, or a group.

(define (locate-entity entity)
  (let* ((name (entity-name entity))
	 (def (resolve-toplevel-name name)))
    (cond ((eq? def '#f)
	   'not-found)
	  ((is-type? 'entity-var entity)
	   (if (method-var? def)
	       (signal-export-method-var name)
	       (make-group name def)))
	  ((is-type? 'entity-con entity)
	   (cond ((algdata? def)
		  (make-group name def))
		 ((synonym? def)
		  (signal-synonym-needs-dots name *module-name*))
		 (else
		  (signal-wrong-definition
		    "type constructor" name *module-name*))))
	  ((is-type? 'entity-abbreviated entity)
	   (cond ((algdata? def)
		  (require-complete-algdata
		   (gather-algdata-group name def)))
		 ((synonym? def)
		  (make-group name def))
		 ((class? def)
		  (gather-class-group name def))
		 (else
		  (signal-wrong-definition
		    "type constructor or class" name *module-name*))))
	  ((is-type? 'entity-class entity)
	   (if (class? def)
	       (match-group-names
		 (gather-class-group name def)
		 (entity-class-methods entity)
		 entity
		 "method")
	       (signal-wrong-definition "class" name *module-name*)))
	  ((is-type? 'entity-datatype entity)
	   (if (algdata? def)
	       (match-group-names
		 (require-complete-algdata (gather-algdata-group name def))
		 (entity-datatype-constructors entity)
		 entity "constructor")
	       (signal-wrong-definition "data type" name *module-name*)))
	  (else
	   (error "Bad entity ~s." entity)))))

(define (require-complete-algdata group)
  (if (hidden-constructors? group)
      'not-found
      group))

(define (match-group-names group names entity what)
  (when (not (eq? group 'not-found))
    (match-constituents group names entity what))
  group)