Make cset-meet take more than two arguments.

original commit: c7645170e36f5431d81595d2115010fd62071c9f
This commit is contained in:
Eric Dobson 2014-04-29 22:57:43 -07:00
parent 52d81a3114
commit 5609e972b2
3 changed files with 42 additions and 45 deletions

View File

@ -58,35 +58,36 @@
(unless (or var (eq? X X*))
(int-err "Non-matching vars in c-meet: ~a ~a" X X*))
(let ([S (join S S*)] [T (meet T T*)])
(and (subtype S T)
(and (subtype S T)
(make-c S (or var X) T)))]))
;; compute the meet of two constraint sets
;; returns #f for failure
(define (cset-meet x y)
(match* (x y)
[((struct cset (maps1)) (struct cset (maps2)))
(define maps (for*/list ([(map1 dmap1) (in-pairs (remove-duplicates maps1))]
[(map2 dmap2) (in-pairs (remove-duplicates maps2))]
[v (in-value (% cons
(hash-union/fail map1 map2 #:combine c-meet)
(dmap-meet dmap1 dmap2)))]
#:when v)
v))
(cond [(null? maps)
#f]
[else (make-cset maps)])]
[(_ _) (int-err "Got non-cset: ~a ~a" x y)]))
(define cset-meet
(case-lambda
[() (empty-cset null null)]
[(x) x]
[(x y)
(match* (x y)
[((struct cset (maps1)) (struct cset (maps2)))
(define maps (for*/list ([(map1 dmap1) (in-pairs (remove-duplicates maps1))]
[(map2 dmap2) (in-pairs (remove-duplicates maps2))]
[v (in-value (% cons
(hash-union/fail map1 map2 #:combine c-meet)
(dmap-meet dmap1 dmap2)))]
#:when v)
v))
(cond [(null? maps)
#f]
[else (make-cset maps)])])]
[(x . ys)
(for/fold ([x x]) ([y (in-list ys)])
(% cset-meet x y))]))
;; combines a list of csets using cset-meet individually
;; returns #f for failure
(define (cset-meet* args)
(for/fold ([c (make-cset (list (cons
(make-immutable-hash null)
(make-dmap (make-immutable-hash null)))))])
([a (in-list args)]
#:break (not c))
(cset-meet a c)))
(apply cset-meet args))
;; produces a cset of all of the maps in all of the given csets
;; FIXME: should this call `remove-duplicates`?

View File

@ -206,11 +206,11 @@
;; the simplest case - no rests, drests, keywords
[((arr: ss s #f #f '())
(arr: ts t #f #f '()))
(% cset-meet* (% list
;; contravariant
(cgen/list V X Y ts ss)
;; covariant
(cg s t)))]
(% cset-meet
;; contravariant
(cgen/list V X Y ts ss)
;; covariant
(cg s t))]
;; just a rest arg, no drest, no keywords
[((arr: ss s s-rest #f '())
(arr: ts t t-rest #f '()))
@ -227,7 +227,7 @@
;; no rest arg on the left, or wrong number = fail
[else #f])]
[ret-mapping (cg s t)])
(% cset-meet* (% list arg-mapping ret-mapping)))]
(% cset-meet arg-mapping ret-mapping))]
;; dotted on the left, nothing on the right
[((arr: ss s #f (cons dty dbound) '())
(arr: ts t #f #f '()))
@ -265,8 +265,7 @@
(let* ([arg-mapping (cgen/list V X Y ts ss)]
[darg-mapping (cgen V X Y t-dty s-dty)]
[ret-mapping (cg s t)])
(% cset-meet*
(% list arg-mapping darg-mapping ret-mapping)))]
(% cset-meet arg-mapping darg-mapping ret-mapping))]
;; bounds are different
[((arr: ss s #f (cons s-dty (? (λ (db) (memq db Y)) dbound)) '())
(arr: ts t #f (cons t-dty dbound*) '()))
@ -276,8 +275,7 @@
;; just add dbound as something that can be constrained
[darg-mapping (% move-dotted-rest-to-dmap (cgen V (cons dbound X) Y t-dty s-dty) dbound)]
[ret-mapping (cg s t)])
(% cset-meet*
(% list arg-mapping darg-mapping ret-mapping)))]
(% cset-meet arg-mapping darg-mapping ret-mapping))]
[((arr: ss s #f (cons s-dty dbound) '())
(arr: ts t #f (cons t-dty (? (λ (db) (memq db Y)) dbound*)) '()))
#:return-unless (= (length ss) (length ts)) #f
@ -286,8 +284,7 @@
[darg-mapping (% move-dotted-rest-to-dmap
(cgen V (cons dbound* X) Y t-dty s-dty) dbound*)]
[ret-mapping (cg s t)])
(% cset-meet*
(% list arg-mapping darg-mapping ret-mapping)))]
(% cset-meet arg-mapping darg-mapping ret-mapping))]
;; * <: ...
[((arr: ss s s-rest #f '())
(arr: ts t #f (cons t-dty dbound) '()))
@ -299,7 +296,7 @@
[darg-mapping (% move-rest-to-dmap
(cgen V (cons dbound X) Y t-dty s-rest) dbound)]
[ret-mapping (cg s t)])
(% cset-meet* (% list arg-mapping darg-mapping ret-mapping)))
(% cset-meet arg-mapping darg-mapping ret-mapping))
;; the hard case
(let* ([vars (var-store-take dbound t-dty (- (length ss) (length ts)))]
[new-tys (for/list ([var (in-list vars)])
@ -329,7 +326,7 @@
(move-rest-to-dmap
rest-mapping dbound #:exact #t))]
[ret-mapping (cg s t)])
(% cset-meet* (% list arg-mapping darg-mapping ret-mapping)))]
(% cset-meet arg-mapping darg-mapping ret-mapping))]
[else #f])]
[(_ _) #f]))
@ -387,10 +384,9 @@
;; check each element
[((Result: s f-s o-s)
(Result: t f-t o-t))
(% cset-meet* (% list
(cg s t)
(cgen/filter-set V X Y f-s f-t)
(cgen/object V X Y o-s o-t)))]
(% cset-meet (cg s t)
(cgen/filter-set V X Y f-s f-t)
(cgen/object V X Y o-s o-t))]
;; values are covariant
[((Values: ss) (Values: ts))
@ -531,7 +527,7 @@
;; To check that mutable pair is a sequence we check that the cdr is
;; both an mutable list and a sequence
[((MPair: t1 t2) (Sequence: (list t*)))
(% cset-meet* (% list (cg t1 t*) (cg t2 T) (cg t2 (Un (-val null) (make-MPairTop)))))]
(% cset-meet (cg t1 t*) (cg t2 T) (cg t2 (Un (-val null) (make-MPairTop))))]
[((List: ts) (Sequence: (list t*)))
(% cset-meet* (for/list/fail ([t (in-list ts)])
(cg t t*)))]
@ -651,7 +647,7 @@
[((Box: e) (Box: e*))
(% cset-meet (cg e e*) (cg e* e))]
[((MPair: s t) (MPair: s* t*))
(% cset-meet* (% list (cg s s*) (cg s* s) (cg t t*) (cg t* t)))]
(% cset-meet (cg s s*) (cg s* s) (cg t t*) (cg t* t))]
[((Channel: e) (Channel: e*))
(% cset-meet (cg e e*) (cg e* e))]
[((ThreadCell: e) (ThreadCell: e*))
@ -659,7 +655,7 @@
[((Continuation-Mark-Keyof: e) (Continuation-Mark-Keyof: e*))
(% cset-meet (cg e e*) (cg e* e))]
[((Prompt-Tagof: s t) (Prompt-Tagof: s* t*))
(% cset-meet* (% list (cg s s*) (cg s* s) (cg t t*) (cg t* t)))]
(% cset-meet (cg s s*) (cg s* s) (cg t t*) (cg t* t))]
[((Promise: e) (Promise: e*))
(cg e e*)]
[((Ephemeron: e) (Ephemeron: e*))
@ -694,7 +690,7 @@
;; we assume all HTs are mutable at the moment
[((Hashtable: s1 s2) (Hashtable: t1 t2))
;; for mutable hash tables, both are invariant
(% cset-meet* (% list (cg t1 s1) (cg s1 t1) (cg t2 s2) (cg s2 t2)))]
(% cset-meet (cg t1 s1) (cg s1 t1) (cg t2 s2) (cg s2 t2))]
;; syntax is covariant
[((Syntax: s1) (Syntax: s2))
(cg s1 s2)]

View File

@ -14,7 +14,7 @@
[cond-contracted var-demote (Type/c (listof symbol?) . -> . Type/c)]))
(define-signature constraints^
([cond-contracted cset-meet (cset? cset? . -> . (or/c #f cset?))]
([cond-contracted cset-meet ((cset? cset?) #:rest (listof cset?) . ->* . (or/c #f cset?))]
[cond-contracted cset-meet* ((listof cset?) . -> . (or/c #f cset?))]
no-constraint
[cond-contracted empty-cset ((listof symbol?) (listof symbol?) . -> . cset?)]