Fix keyword function type conversion in TR

Makes rest arguments work properly and handles
keywords passed in by sorted order.

original commit: c8554e2489beaab392fe46c9b3eafeb0bf8c2d22
This commit is contained in:
Asumu Takikawa 2014-01-22 21:29:44 -05:00
parent 99f3f62a6e
commit 3feeb553ac
2 changed files with 71 additions and 17 deletions

View File

@ -19,6 +19,8 @@
#:kws kw-t
#:rest rest
#:drest drest)))
;; the kw function protocol passes rest args as an explicit list
(define rest-type (if rest (-lst rest) empty))
(define ts
(flatten
(list
@ -31,39 +33,38 @@
plain-t
(for/list ([t (in-list opt-t)]) (-opt t))
(for/list ([t (in-list opt-t)]) -Boolean)
;; the kw function protocol passes rest args as an explicit list
(if rest (-lst rest) empty))))
rest-type)))
;; the kw protocol puts the arguments in keyword-sorted order in the
;; function header, so we need to sort the types to match
(define sorted-kws
(sort kw-t keyword<? #:key (match-lambda [(Keyword: kw _ _) kw])))
(define ts/true
(flatten
(list
(for/list ([k (in-list mand-kw-t)])
(for/list ([k (in-list sorted-kws)])
(match k
[(Keyword: _ t _) t]))
(for/list ([k (in-list opt-kw-t)])
(match k
[(Keyword: _ t _) (list t (-val #t))]))
[(Keyword: _ t #t) t]
[(Keyword: _ t #f) (list t (-val #t))]))
plain-t
(for/list ([t (in-list opt-t)]) t)
(for/list ([t (in-list opt-t)]) (-val #t))
;; the kw function protocol passes rest args as an explicit list
(if rest (-lst rest) empty))))
rest-type)))
(define ts/false
(flatten
(list
(for/list ([k (in-list mand-kw-t)])
(for/list ([k (in-list sorted-kws)])
(match k
[(Keyword: _ t _) t]))
(for/list ([k (in-list opt-kw-t)])
(match k
[(Keyword: _ t _) (list (-val #f) (-val #f))]))
[(Keyword: _ t #t) t]
[(Keyword: _ t #f) (list (-val #f) (-val #f))]))
plain-t
(for/list ([t (in-list opt-t)]) (-val #f))
(for/list ([t (in-list opt-t)]) (-val #f)))))
(for/list ([t (in-list opt-t)]) (-val #f))
rest-type)))
(make-Function
(if split?
(remove-duplicates
(list (make-arr* ts/true rng #:rest rest #:drest drest)
(make-arr* ts/false rng #:rest rest #:drest drest)))
(list (make-arr* ts/true rng #:drest drest)
(make-arr* ts/false rng #:drest drest)))
(list (make-arr* ts rng #:rest rest #:drest drest)))))
(define (prefix-of a b)

View File

@ -32,3 +32,56 @@
(g 0 #:k 1)
(g2 0 #:k 1)
;; Additional keyword function tests
;; FIXME: These really belong in the unit tests, but for some reason
;; the unit tests don't work well with keywords.
(: f0:a (#:a String -> (List String)))
(define (f0:a #:a a) (list a))
(: f1:a (Symbol #:a String -> (List Symbol String)))
(define (f1:a x #:a a) (list x a))
(: f1:a? (Symbol [#:a String] -> (List Symbol String)))
(define (f1:a? x #:a [a "a"]) (list x a))
(: f1+:a (String #:a String String * -> (Listof String)))
(define (f1+:a x #:a a . args) (cons x (cons a args)))
(: f1+:a? (String [#:a String] String * -> (Listof String)))
(define (f1+:a? x #:a [a "a"] . args) (cons x (cons a args)))
(: f0:a:b (#:a String #:b Symbol -> (List String Symbol)))
(define (f0:a:b #:a a #:b b) (list a b))
(: f0:a?:b ([#:a String] #:b Symbol -> (List String Symbol)))
(define (f0:a?:b #:a [a "a"] #:b b) (list a b))
(: f1:a:b (String #:a String #:b Symbol -> (List String String Symbol)))
(define (f1:a:b x #:a a #:b b) (list x a b))
(: f1:a?:b (String [#:a String] #:b Symbol -> (List String String Symbol)))
(define (f1:a?:b x #:a [a "a"] #:b b) (list x a b))
(: f1+:a:b (String #:a String #:b String String * -> (Listof String)))
(define (f1+:a:b x #:a a #:b b . args) (cons x (cons a (cons b args))))
(: f0:a:b? (#:a String [#:b Symbol] -> (List String Symbol)))
(define (f0:a:b? #:a a #:b [b 'b]) (list a b))
(: f0:a?:b? ([#:a String] [#:b Symbol] -> (List String Symbol)))
(define (f0:a?:b? #:a [a "a"] #:b [b 'b]) (list a b))
(: f1:a:b? (String #:a String [#:b Symbol] -> (List String String Symbol)))
(define (f1:a:b? x #:a a #:b [b 'b]) (list x a b))
(: f1:a?:b? (String [#:a String] [#:b Symbol] -> (List String String Symbol)))
(define (f1:a?:b? x #:a [a "a"] #:b [b 'b]) (list x a b))
(: f1+:a:b? (String #:a String [#:b String] String * -> (Listof String)))
(define (f1+:a:b? x #:a a #:b [b "b"] . args)
(cons x (cons a (cons b args))))
(: f1+:a?:b? (String [#:a String] [#:b String] String * -> (Listof String)))
(define (f1+:a?:b? x #:a [a "a"] #:b [b "b"] . args)
(cons x (cons a (cons b args))))