;;; 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))
|