git.fiddlerwoaroof.com
Raw Blame History
;;; This file handles the scoping and error checking of signatures.

;;; Possible errors:
;;;  Wrong arity in a tycon
;;;  Ambiguous context

;;; Other errors may be present; these are detected at a higher level.
;;; The list of variables used in the signature is returned.

(define (resolve-signature signature)
  (with-slots signature (context type) signature
    (let ((tyvars (resolve-type type)))
      (resolve-signature-aux tyvars context)
      tyvars)))

(define (resolve-signature-aux tyvars context)
  (dolist (ctxt context)
    (with-slots context (class tyvar) ctxt
      (when (not (memq tyvar tyvars))
	(signal-ambiguous-context tyvar))
      (resolve-class class))))

(define (resolve-type type)
  (resolve-type-1 type '()))

(define (resolve-type-1 type vars)
  (cond ((tyvar? type)
	 (cons (tyvar-name type) vars))
	(else
	 (resolve-tycon type)
	 (with-slots tycon (name def args) type
	   (when (not (eq? def *undefined-def*))
	     (if (eqv? (tycon-def-arity def) -1)
		 (setf (tycon-def-arity def) (length args))
		 (when (not (eqv? (length args) (tycon-def-arity def)))
		     (signal-tycon-arity name type))))
	   (resolve-type/list args vars)))))

(define (resolve-type/list args vars)
  (if (null? args)
      vars
      (resolve-type/list (cdr args) (resolve-type-1 (car args) vars))))

;;; This returns the names of the tyvars in a simple tycon

(define (simple-tyvar-list simple)
  (remember-context simple
    (let* ((res (map (lambda (x) (tyvar-name x)) (tycon-args simple)))
	   (dups (find-duplicates res)))
      (when (not (null? dups))
	(signal-non-linear-type-vars simple))
      res)))

;;; This is used to build the class dictionary signature.

(define (substitute-tyvar type tyvar new)
  (cond ((tyvar? type)
	 (if (eq? (tyvar-name type) tyvar)
	     new
	     (**tyvar (tyvar-name type))))
	((tycon? type)
	 (with-slots tycon (name def args) type
	   (make tycon (name name) (def def)
		       (args (map (lambda (x) (substitute-tyvar x tyvar new))
				  args)))))
	(else
	 (**signature (signature-context type)
		      (substitute-tyvar (signature-type type) tyvar new)))))



;;; Error signalling routines

(define (signal-ambiguous-context tyvar)
  (phase-error 'ambiguous-context
    "~a is referenced in a context, but is not bound as a type variable."
    tyvar))

(define (signal-tycon-arity name type)
  (phase-error 'tycon-arity
    "The wrong number of arguments are supplied to the constructor ~a~%~
     in the type ~a."
    name type))


(define (signal-non-linear-type-vars simple)
  (phase-error 'non-linear-type-vars
    "There are duplicate type variables in ~s."
    simple))