git.fiddlerwoaroof.com
Raw Blame History
;;; This file has some random utilities dealing with instances.

;;; Right now, this is a linear search off the class.

(define (lookup-instance alg-def class-def)
  (let ((res (lookup-instance-1 alg-def (class-instances class-def))))
    (if (and (eq? res '#f) (algdata-real-tuple? alg-def))
	(lookup-possible-tuple-instances alg-def class-def)
	res)))

(define (lookup-instance-1 alg-def instances)
  (cond ((null? instances)
	 '#f)
	((eq? (instance-algdata (car instances)) alg-def)
	 (if (instance-ok? (car instances))
	     (car instances)
	     '#f))
	(else
	 (lookup-instance-1 alg-def (cdr instances)))))

(define (lookup-possible-tuple-instances alg-def class-def)
  (cond ((eq? class-def (core-symbol "Eq"))
	 (get-tuple-eq-instance alg-def))
	((eq? class-def (core-symbol "Ord"))
	 (get-tuple-ord-instance alg-def))
	((eq? class-def (core-symbol "Ix"))
	 (get-tuple-ix-instance alg-def))
	((eq? class-def (core-symbol "Text"))
	 (get-tuple-text-instance alg-def))
	((eq? class-def (core-symbol "Binary"))
	 (get-tuple-binary-instance alg-def))
	(else '#f)))

(define *saved-eq-instances* '())
(define *saved-ord-instances* '())
(define *saved-ix-instances* '())
(define *saved-text-instances* '())
(define *saved-binary-instances* '())

(define (get-tuple-eq-instance tpl)
  (let ((res (assq tpl *saved-eq-instances*)))
    (if (not (eq? res '#f))
	(tuple-2-2 res)
	(let ((inst (make-tuple-instance
		     tpl (core-symbol "Eq") (core-symbol "tupleEqDict"))))
	  (push (tuple tpl inst) *saved-eq-instances*)
	  inst))))

(define (get-tuple-ord-instance tpl)
  (let ((res (assq tpl *saved-ord-instances*)))
    (if (not (eq? res '#f))
	(tuple-2-2 res)
	(let ((inst (make-tuple-instance
		     tpl (core-symbol "Ord") (core-symbol "tupleOrdDict"))))
	  (push (tuple tpl inst) *saved-ord-instances*)
	  inst))))

(define (get-tuple-ix-instance tpl)
  (let ((res (assq tpl *saved-ix-instances*)))
    (if (not (eq? res '#f))
	(tuple-2-2 res)
	(let ((inst (make-tuple-instance
		     tpl (core-symbol "Ix") (core-symbol "tupleIxDict"))))
	  (push (tuple tpl inst) *saved-ix-instances*)
	  inst))))

(define (get-tuple-text-instance tpl)
  (let ((res (assq tpl *saved-text-instances*)))
    (if (not (eq? res '#f))
	(tuple-2-2 res)
	(let ((inst (make-tuple-instance
		     tpl (core-symbol "Text") (core-symbol "tupleTextDict"))))
	  (push (tuple tpl inst) *saved-text-instances*)
	  inst))))

(define (get-tuple-binary-instance tpl)
  (let ((res (assq tpl *saved-binary-instances*)))
    (if (not (eq? res '#f))
	(tuple-2-2 res)
	(let ((inst (make-tuple-instance
		     tpl (core-symbol "Binary")
		     (core-symbol "tupleBinaryDict"))))
	  (push (tuple tpl inst) *saved-binary-instances*)
	  inst))))

(define (make-tuple-instance algdata class dict)
  (let* ((size (tuple-size algdata))
	 (tyvars (gen-symbols size))
	 (context (map (lambda (tyvar)
			  (**context (**class/def class) tyvar))
			tyvars))
	 (sig (**tycon/def algdata (map (lambda (x) (**tyvar x)) tyvars)))
	 (gcontext (gtype-context (ast->gtype context sig))))
    (make instance 
	  (algdata algdata)
	  (tyvars tyvars)
	  (class class)
	  (context context)
	  (gcontext gcontext)
	  (methods '())
	  (dictionary dict)
	  (ok? '#t)
	  (special? '#t))))

;;; I know these are somewhere else too ...

(define (tuple-size alg)
  (con-arity (car (algdata-constrs alg))))

(define (gen-symbols n)
  (gen-symbols-1 n '(|a| |b| |c| |d| |e| |f| |g| |h| |i| |j| |k| |l| |m|
		     |n| |o| |p| |q| |r| |s| |t| |u| |v| |w| |x| |y| |z|)))

(define (gen-symbols-1 n vars)
  (if (eqv? n 0)
      '()
      (if (null? vars)
	  (cons (string->symbol (format '#f "x~A" n))
		(gen-symbols-1 (1- n) '()))
	  (cons (car vars) (gen-symbols-1 (1- n) (cdr vars))))))

;;; This handles the dynamic linking of instances into classes

(define (link-instances modules)
  (dolist (m modules)
    ;; clear out any instances sitting around from old compiles
    (dolist (class (module-class-defs m))
      (setf (class-instances class) '())))
  (dolist (m modules)
    (dolist (inst (module-instance-defs m))
       (link-instance inst)))
  )

(define (link-instance inst)  ; links an instance into the associated class
  (push inst (class-instances (instance-class inst))))

;;; This creates a new instance object and installs it.

(predefine (make-new-var name))  ; in tdecl/tdecl-utils.scm

(define (new-instance class algdata tyvars)
 (let* ((dict-name
	 (string-append "dict-"
			(symbol->string (print-name class)) "-"
			(symbol->string (print-name algdata))))
	(inst (make instance (algdata algdata)
			     (tyvars tyvars)
		             (class class)
			     (gcontext '())
			     (context '())
			     (dictionary (make-new-var dict-name)))))
   (link-instance inst)
   inst))