Handle rest args and case-lambda in app.

Fix parsing.

svn: r14722
This commit is contained in:
Sam Tobin-Hochstadt 2009-05-05 19:10:21 +00:00
parent 6b89062d6a
commit 59dbcade9c
5 changed files with 99 additions and 21 deletions

View File

@ -570,7 +570,7 @@
[(values t ...) [(values t ...)
#:when (eq? 'values (syntax-e #'values)) #:when (eq? 'values (syntax-e #'values))
(ret (map parse-type (syntax->list #'(t ...))))] (ret (map parse-type (syntax->list #'(t ...))))]
[t (parse-type #'t)])) [t (ret (parse-type #'t))]))
(define parse-tc-results/id (parse/id parse-tc-results)) (define parse-tc-results/id (parse/id parse-tc-results))

View File

@ -1,13 +1,24 @@
#lang typed-scheme #lang typed-scheme
(: f (Number String -> Number)) (: f (Number String -> Number))
(define (f x z) (f x z)) (define (f x z) #;(f x z) 7)
(lambda: ([x : Any] [y : Any]) (values (number? y) (number? x))) (lambda: ([x : Any] [y : Any]) (values (number? y) (number? x)))
(lambda: ([x : Any] [y : Any]) (values (number? x) (number? y))) (lambda: ([x : Any] [y : Any]) (values (number? x) (number? y)))
(lambda: ([x : Any] [y : Any]) (values (and (number? x) (boolean? y)) (number? y))) (lambda: ([x : Any] [y : Any]) (values (and (number? x) (boolean? y)) (number? y)))
(lambda: ([x : Any]) (values (number? x) (number? x))) (lambda: ([x : Any]) (values (number? x) (number? x)))
(: g (Any -> Boolean : Number)) (: g (Any -> Boolean : Number))
(define g (lambda: ([x : Any]) (number? x))) (define g (lambda: ([x : Any]) (number? x)))
(: q ((Number -> Number) -> Number))
(define q (lambda: ([x : (Number -> Number)]) (x 1)))
;(q (lambda (z) (f z "foo")))
(: p (Number * -> Number))
(define (p . x) 7)
(lambda x (number? x))
(+)
(+ 1 2 3)
(+ 1 2 3.5)
;(f 12 "hi") ;(f 12 "hi")

View File

@ -0,0 +1,41 @@
#lang scheme/base
(require "../utils/utils.ss"
(utils tc-utils))
(provide (all-defined-out))
(define (stringify-domain dom rst drst [rng #f])
(let ([doms-string (if (null? dom) "" (string-append (stringify dom) " "))]
[rng-string (if rng (format " -> ~a" rng) "")])
(cond [drst
(format "~a~a ... ~a~a" doms-string (car drst) (cdr drst) rng-string)]
[rst
(format "~a~a *~a" doms-string rst rng-string)]
[else (string-append (stringify dom) rng-string)])))
(define (domain-mismatches ty doms rests drests rngs arg-tys tail-ty tail-bound #:expected [expected #f])
(define arguments-str
(stringify-domain arg-tys (if (not tail-bound) tail-ty #f) (if tail-bound (cons tail-ty tail-bound) #f)))
(cond
[(null? doms)
(int-err "How could doms be null: ~a ~a" ty)]
[(= 1 (length doms))
(format "Domain: ~a~nArguments: ~a~n~a"
(stringify-domain (car doms) (car rests) (car drests))
arguments-str
(if expected
(format "Result type: ~a~nExpected result: ~a~n"
(car rngs) expected)
""))]
[else
(format "~a: ~a~nArguments: ~a~n~a"
(if expected "Types" "Domains")
(stringify (if expected
(map stringify-domain doms rests drests rngs)
(map stringify-domain doms rests drests))
"~n\t")
arguments-str
(if expected
(format "Expected result: ~a~n" expected)
""))]))

View File

@ -2,9 +2,10 @@
(require (rename-in "../utils/utils.ss" [infer r:infer]) (require (rename-in "../utils/utils.ss" [infer r:infer])
"signatures.ss" "tc-metafunctions.ss" "signatures.ss" "tc-metafunctions.ss"
"tc-app-helper.ss"
stxclass scheme/match mzlib/trace stxclass scheme/match mzlib/trace
(for-syntax stxclass) (for-syntax stxclass)
(types utils abbrev) (types utils abbrev union subtype)
(utils tc-utils) (utils tc-utils)
(rep type-rep filter-rep object-rep) (rep type-rep filter-rep object-rep)
(for-template (for-template
@ -88,23 +89,47 @@
(define (in-indexes dom) (define (in-indexes dom)
(in-range (length dom))) (in-range (length dom)))
;; syntax? syntax? tc-results? (listof tc-results?) (or/c #f tc-results) -> tc-results?
(define (tc/funapp f-stx args-stx ftype0 argtys expected) (define (tc/funapp f-stx args-stx ftype0 argtys expected)
(match* (ftype0 argtys) (match* (ftype0 argtys)
[((tc-result1: (Function: (list (arr: dom (Values: (list (Result: t-r lf-r lo-r) ...)) #f #f '())))) ;; we special-case this (no case-lambda) for improved error messages
[((tc-result1: (and t (Function: (list (and a (arr: dom (Values: (list (Result: t-r lf-r lo-r) ...)) rest #f kws))))))
argtys)
(tc/funapp1 f-stx args-stx a argtys expected)]
[((tc-result1: (and t (Function: (and arrs (list (arr: doms rngs rests #f kws) ...)))))
(and argtys (list (tc-result1: argtys-t) ...)))
(let loop ([doms* doms] [rngs rngs] [rests* rests] [a arrs])
(cond [(null? doms*)
(tc-error/expr
#:return (or expected (ret (Un)))
(string-append "No function domains matched in function application:\n"
(domain-mismatches t doms rests #f rngs argtys #f #f)))]
[(subtypes/varargs argtys-t (car doms*) (car rests*))
(tc/funapp1 f-stx args-stx (car a) argtys expected #:check #f)]
[else (loop (cdr doms*) (cdr rngs) (cdr rests*) (cdr a))]))]))
;; syntax? syntax? arr? (listof tc-results?) (or/c #f tc-results) [boolean?] -> tc-results?
(define (tc/funapp1 f-stx args-stx ftype0 argtys expected #:check [check? #t])
(match* (ftype0 argtys)
[((arr: dom (Values: (list (Result: t-r lf-r lo-r) ...)) rest #f '())
(list (tc-result1: t-a phi-a o-a) ...)) (list (tc-result1: t-a phi-a o-a) ...))
(unless (= (length dom) (length t-a)) (when check?
(cond [(and (not rest) (not (= (length dom) (length t-a))))
(tc-error/expr #:return (ret t-r) (tc-error/expr #:return (ret t-r)
"Wrong number of arguments")) "Wrong number of arguments, expected ~a and got ~a" (length dom) (length t-a))]
(for ([dom-t (in-list dom)] [arg-t (in-list t-a)]) [(and rest (< (length t-a) (length dom)))
(check-below arg-t dom-t)) (tc-error/expr #:return (ret t-r)
"Wrong number of arguments, expected at least ~a and got ~a" (length dom) (length t-a))])
(for ([dom-t (in-list-forever dom rest)] [a (syntax->list args-stx)] [arg-t (in-list t-a)])
(parameterize ([current-orig-stx a]) (check-below arg-t dom-t))))
(let* (;; Listof[Listof[LFilterSet]] (let* (;; Listof[Listof[LFilterSet]]
[lfs-f (for/list ([lf lf-r]) [lfs-f (for/list ([lf lf-r])
(for/list ([i (in-indexes dom)]) (for/list ([i (in-indexes dom)])
(split-lfilters lf i)))] (split-lfilters lf i)))]
;; Listof[FilterSet] ;; Listof[FilterSet]
[f-r (for/list ([lfs lfs-f]) [f-r (for/list ([lfs lfs-f])
(merge-filter-sets (for/list ([lf lfs] [t t-a] [o o-a]) (merge-filter-sets
(for/list ([lf lfs] [t t-a] [o o-a])
(apply-filter lf t o))))] (apply-filter lf t o))))]
;; Listof[Object] ;; Listof[Object]
[o-r (for/list ([lo lo-r]) [o-r (for/list ([lo lo-r])
@ -116,4 +141,4 @@
[_ (make-Empty)]))]) [_ (make-Empty)]))])
(ret t-r f-r o-r))] (ret t-r f-r o-r))]
[(_ _) [(_ _)
(int-err "funapp with keyword/rest args NYI")])) (int-err "funapp with keyword args NYI")]))

View File

@ -5,7 +5,7 @@
"tc-metafunctions.ss" "tc-metafunctions.ss"
mzlib/trace mzlib/trace
scheme/list scheme/list
stxclass/util stxclass/util syntax/stx
(rename-in scheme/contract [-> -->] [->* -->*] [one-of/c -one-of/c]) (rename-in scheme/contract [-> -->] [->* -->*] [one-of/c -one-of/c])
(except-in (rep type-rep) make-arr) (except-in (rep type-rep) make-arr)
(rename-in (types convenience utils union) (rename-in (types convenience utils union)
@ -160,10 +160,11 @@
#f #f
(tc-exprs (syntax->list body)))))]))])) (tc-exprs (syntax->list body)))))]))]))
(define (formals->list l)
;; FIXED TO HERE (let loop ([l (syntax-e l)])
(cond [(stx-pair? l) (cons (stx-car l) (loop (stx-cdr l)))]
;(trace tc-args) [(pair? l) (cons (car l) (loop (cdr l)))]
[else null])))
;; tc/mono-lambda : syntax-list syntax-list (or/c #f tc-results) -> (listof lam-result) ;; tc/mono-lambda : syntax-list syntax-list (or/c #f tc-results) -> (listof lam-result)
;; typecheck a sequence of case-lambda clauses ;; typecheck a sequence of case-lambda clauses
@ -200,7 +201,7 @@
[(tc-result1: (Function: (list (arr: argss rets rests drests '()) ...))) [(tc-result1: (Function: (list (arr: argss rets rests drests '()) ...)))
(for/list ([args argss] [ret rets] [rest rests] [drest drests]) (for/list ([args argss] [ret rets] [rest rests] [drest drests])
(tc/lambda-clause/check (car (syntax->list formals)) (car (syntax->list bodies)) (tc/lambda-clause/check (car (syntax->list formals)) (car (syntax->list bodies))
args (values->tc-results ret (syntax->list (car (syntax->list formals)))) rest drest))] args (values->tc-results ret (formals->list (car (syntax->list formals)))) rest drest))]
[_ (go (syntax->list formals) (syntax->list bodies) null null null)]))] [_ (go (syntax->list formals) (syntax->list bodies) null null null)]))]
;; otherwise ;; otherwise
[else (go (syntax->list formals) (syntax->list bodies) null null null)])) [else (go (syntax->list formals) (syntax->list bodies) null null null)]))