Skip to content

Commit eed41a0

Browse files
committed
more complete function application
i.e. when applying a case->, the result is the intersection of each applicable range. Here are some quickly gathered performance results from this change: Compile time ratio (old time / new time): schml-specify-rep: 0.99 (i.e. slower, 8.63s (σ 0.09) to 8.72s (σ 0.05)) schml-interp-casts-help: 1.01 (i.e. faster, 20.05s (σ 0.24) to 19.77s (σ 0.01)) parser: 0.95 (i.e. slower, 2.22s (σ 0.05) to 2.33s (σ 0.09)) old-metrics: 0.96 (i.e. slower, 2.68s (σ 0.04) to 2.78s (σ 0.09)) new-metrics: 0.98 (i.e. slower, 3.61s (σ 0.02) to 3.7s (σ 0.08)) math-flonum: 0.98 (i.e. slower, 3.76s (σ 0.02) to 3.83s (σ 0.08)) fsm: 0.94 (i.e. slower, 4.91s (σ 0.09) to 5.22s (σ 0.19)) forth: 0.97 (i.e. slower, 4.87s (σ 0.18) to 5.01s (σ 0.01)) dungeon: 0.95 (i.e. slower, 8.64s (σ 0.11) to 9.11s (σ 0.18)) bernoulli: 0.95 (i.e. slower, 3.95s (σ 0.04) to 4.16s (σ 0.09)) acquire: 0.96 (i.e. slower, 15.53s (σ 0.23) to 16.2s (σ 0.08)) And for the math library, compile time increased from 2m28.281s to 2m40.492s. Note that some primtives (i.e. like those which operate on the numeric tower) currently have quite verbose function types which can be greatly simplified after this change is adopted.
1 parent a3871e6 commit eed41a0

File tree

11 files changed

+117
-44
lines changed

11 files changed

+117
-44
lines changed

typed-racket-lib/typed-racket/base-env/base-env-numeric.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1498,7 +1498,7 @@
14981498
;; no positive / negative cases, possible underflow
14991499
(-NonNegReal . -> . -NonNegSingleFlonum)
15001500
(-NonPosReal . -> . -NonPosSingleFlonum)
1501-
(-Real . -> . -SingleFlonumZero))]
1501+
(-Real . -> . -SingleFlonum))]
15021502
[real->double-flonum
15031503
(from-cases (map unop all-flonum-types)
15041504
(-SingleFlonumPosZero . -> . -FlonumPosZero)

typed-racket-lib/typed-racket/env/lexical-env.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
[lookup-obj-type/lexical ((Object?) (env? #:fail (or/c #f Type? (-> any/c (or/c Type? #f))))
3434
. ->* .
3535
(or/c Type? #f))]
36-
[lookup-alias/lexical ((identifier?) (env?) . ->* . (or/c Path? Empty?))])
36+
[lookup-alias/lexical ((identifier?) (env?) . ->* . OptObject?)])
3737

3838
;; used at the top level
3939
(define (add-props-to-current-lexical! ps)

typed-racket-lib/typed-racket/typecheck/check-subforms-unit.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
[stx:exn-body^
137137
(set! body-results (tc-expr/check #'stx expected))])
138138
(define handler-results (get-handler-results))
139-
(merge-tc-results (cons body-results handler-results)))
139+
(union-tc-results (cons body-results handler-results)))
140140

141141
;; typecheck the expansion of a with-handlers form
142142
;; syntax -> void

typed-racket-lib/typed-racket/typecheck/tc-app-helper.rkt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@
1515
(provide/cond-contract
1616
[tc/funapp1
1717
((syntax? stx-list? Arrow? (listof tc-results/c) (or/c #f tc-results/c))
18-
(#:check boolean?)
18+
(#:check boolean? #:tooltip? boolean?)
1919
. ->* . full-tc-results/c)])
20-
(define (tc/funapp1 f-stx args-stx ftype0 arg-ress expected #:check [check? #t])
20+
(define (tc/funapp1 f-stx args-stx ftype0 arg-ress expected
21+
#:check [check? #t]
22+
#:tooltip? [tooltip? #t])
2123
;; update tooltip-table with inferred function type
22-
(add-typeof-expr f-stx (ret (make-Fun (list ftype0))))
24+
(when tooltip?
25+
(add-typeof-expr f-stx (ret (make-Fun (list ftype0)))))
2326
(match* (ftype0 arg-ress)
2427
;; we check that all kw args are optional
2528
[((Arrow: dom rst (list (Keyword: _ _ #f) ...) rng)

typed-racket-lib/typed-racket/typecheck/tc-funapp.rkt

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
(utils tc-utils identifier)
77
(env tvar-env lexical-env)
88
(for-syntax syntax/parse racket/base)
9-
(types utils subtype resolve abbrev
9+
(types utils subtype resolve abbrev type-table
1010
substitute classes prop-ops)
1111
(typecheck tc-metafunctions tc-app-helper tc-subst tc-envops
1212
check-below)
@@ -115,17 +115,14 @@
115115
;; check there are no RestDots
116116
#:when (not (for/or ([a (in-list arrows)])
117117
(RestDots? (Arrow-rst a))))
118-
(cond
119-
;; find the first function where the argument types match
120-
[(ormap (match-lambda
121-
[(and a (Arrow: dom rst _ _))
122-
(and (subtypes/varargs argtys dom rst) a)])
123-
arrows)
124-
=> (λ (a)
125-
;; then typecheck here -- we call the separate function so that we get
126-
;; the appropriate props/objects
127-
(tc/funapp1 f-stx args-stx a args-res expected #:check #f))]
128-
[else
118+
(define applicable-arrows
119+
(filter (match-lambda
120+
[(Arrow: dom rst _ _)
121+
(subtypes/varargs argtys dom rst)])
122+
arrows))
123+
124+
(match applicable-arrows
125+
[(list)
129126
;; if nothing matched, error
130127
(match arrows
131128
[(list (Arrow: doms rsts _ rngs) ...)
@@ -135,7 +132,30 @@
135132
#:msg-thunk (lambda (dom)
136133
(string-append
137134
"No function domains matched in function application:\n"
138-
dom)))])])]
135+
dom)))])]
136+
[(list a) (tc/funapp1 f-stx args-stx a args-res expected #:check #f)]
137+
[_
138+
;; call a separate function so that we get
139+
;; the appropriate props/objects
140+
(define app-result
141+
(intersect-tc-results
142+
(for/list ([a (in-list applicable-arrows)])
143+
(tc/funapp1 f-stx args-stx a args-res expected
144+
#:check #f
145+
#:tooltip? #f))))
146+
(define applicable-domain
147+
;; gather and intersect applicable domains to report to user
148+
;; generally what class of inputs produces the resulting output
149+
(for/fold ([domtys (build-list (length argtys) (λ (_) Univ))])
150+
([a (in-list applicable-arrows)])
151+
(match a
152+
[(Arrow: dom rst _ _) (for/list ([domty (in-list domtys)]
153+
[idx (in-naturals)])
154+
(intersect domty (dom+rst-ref dom rst idx)))])))
155+
(add-typeof-expr
156+
f-stx
157+
(ret (make-Fun (list (-Arrow applicable-domain (tc-results->values app-result))))))
158+
app-result])]
139159
;; any kind of dotted polymorphic function without mandatory keyword args
140160
[(PolyDots: (list fixed-vars ... dotted-var)
141161
(Fun: arrows))
@@ -308,7 +328,7 @@
308328
;; a union of functions can be applied if we can apply all of the elements
309329
[(Union: (? Bottom?) ts) #:when (for/and ([t (in-list ts)])
310330
(subtype t top-func))
311-
(merge-tc-results
331+
(union-tc-results
312332
(for/list ([fty (in-list ts)])
313333
(tc/funapp f-stx args-stx fty args-res expected)))]
314334
;; bottom or error type is a perfectly good fcn type

typed-racket-lib/typed-racket/typecheck/tc-if.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
;; if there was not any expected results, then merge the 'then'
3131
;; and 'else' results so we propogate the correct info upwards
3232
[(or #f (tc-any-results: #f))
33-
(merge-tc-results (list thn-res els-res))]
33+
(union-tc-results (list thn-res els-res))]
3434
;; otherwise, the subcomponents have already been checked and
3535
;; we just return the expected result 'fixed' to replace any
3636
;; missing fields (i.e. #f props or objects)

typed-racket-lib/typed-racket/typecheck/tc-metafunctions.rkt

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
racket/match racket/list
66
(except-in (types abbrev utils prop-ops)
77
-> ->* one-of/c)
8+
(only-in (infer infer) intersect)
89
(rep type-rep prop-rep object-rep values-rep rep-utils)
910
(typecheck tc-subst)
1011
(logic ineq)
1112
(contract-req))
1213

1314
(provide abstract-results
1415
combine-props
15-
merge-tc-results
16+
union-tc-results
17+
intersect-tc-results
1618
tc-results->values
1719
erase-existentials)
1820

@@ -145,7 +147,7 @@
145147
(-or p+ p-)])
146148
tcrs))]))
147149

148-
(define (merge-tc-results results [ignore-propositions? #f])
150+
(define (union-tc-results results [ignore-propositions? #f])
149151
(define/match (merge-tc-result r1 r2)
150152
[((tc-result: t1 (and ps1 (PropSet: p1+ p1-)) o1)
151153
(tc-result: t2 (PropSet: p2+ p2-) o2))
@@ -165,13 +167,13 @@
165167
(make-RestDots (Un t1 t2) dbound)])
166168

167169

168-
(define/match (merge-two-results res1 res2)
170+
(define/match (union-two-results res1 res2)
169171
[((tc-result1: (== -Bottom)) res2) res2]
170172
[(res1 (tc-result1: (== -Bottom))) res1]
171-
[((tc-any-results: f1) res2)
172-
(-tc-any-results (-or f1 (unconditional-prop res2)))]
173-
[(res1 (tc-any-results: f2))
174-
(-tc-any-results (-or (unconditional-prop res1) f2))]
173+
[((tc-any-results: p1) res2)
174+
(-tc-any-results (-or p1 (unconditional-prop res2)))]
175+
[(res1 (tc-any-results: p2))
176+
(-tc-any-results (-or (unconditional-prop res1) p2))]
175177
[((tc-results: results1 dty1)
176178
(tc-results: results2 dty2))
177179
;; if we have the same number of values in both cases
@@ -188,7 +190,55 @@
188190
(format "~a and ~a." (length results2) (length results1))))])])
189191

190192
(for/fold ([res (ret -Bottom)]) ([res2 (in-list results)])
191-
(merge-two-results res res2)))
193+
(union-two-results res res2)))
194+
195+
(define (intersect-tc-results results)
196+
(define/match (merge-tc-result r1 r2)
197+
[((tc-result: t1 (PropSet: p1+ p1-) o1)
198+
(tc-result: t2 (PropSet: p2+ p2-) o2))
199+
(-tc-result (intersect t1 t2)
200+
(-PS (-and p1+ p2+) (-and p1- p2-))
201+
(match* (o1 o2)
202+
[(o o) o]
203+
[((Empty:) _) o2]
204+
[(_ (Empty:)) o1]
205+
[(_ _) -empty-obj]))])
206+
207+
(define/match (same-dty? r1 r2)
208+
[(#f #f) #t]
209+
[((RestDots: t1 dbound) (RestDots: t2 dbound)) #t]
210+
[(_ _) #f])
211+
(define/match (merge-dty r1 r2)
212+
[(#f #f) #f]
213+
[((RestDots: t1 dbound) (RestDots: t2 dbound))
214+
(make-RestDots (intersect t1 t2) dbound)])
215+
216+
217+
(define/match (intersect-two-results res1 res2)
218+
[((tc-result1: (== -Bottom)) res2) (ret -Bottom)]
219+
[(res1 (tc-result1: (== -Bottom))) (ret -Bottom)]
220+
[((tc-any-results: p1) res2) (add-unconditional-prop res2 p1)]
221+
[(res1 (tc-any-results: p2)) (add-unconditional-prop res1 p2)]
222+
[((tc-results: results1 dty1) (tc-results: results2 dty2))
223+
;; if we have the same number of values in both cases
224+
(cond
225+
[(and (= (length results1) (length results2))
226+
(same-dty? dty1 dty2))
227+
(-tc-results (map merge-tc-result results1 results2)
228+
(merge-dty dty1 dty2))]
229+
;; otherwise, error
230+
[else
231+
(tc-error/expr "Expected the same number of values, but got ~a"
232+
(if (< (length results1) (length results2))
233+
(format "~a and ~a." (length results1) (length results2))
234+
(format "~a and ~a." (length results2) (length results1))))])])
235+
236+
(match results
237+
[(list r) r]
238+
[(cons r rs)
239+
(for/fold ([r-acc r])
240+
([r (in-list rs)])
241+
(intersect-two-results r-acc r))]))
192242

193243

194244
(define (erase-existentials rep)

typed-racket-lib/typed-racket/typecheck/tc-send.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
rcvr-type)])]
4343
;; union of objects, check pointwise and union the results
4444
[(Union: (? Bottom?) objs) #:when (andmap Instance? objs)
45-
(merge-tc-results (map do-check objs))]
45+
(union-tc-results (map do-check objs))]
4646
[_ (tc-error/expr/fields
4747
"send: type mismatch"
4848
"expected" "an object"

typed-racket-lib/typed-racket/types/type-table.rkt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,13 @@
6767
;; the car should be the latest stx for the location
6868
(if (equal? e (car seen))
6969
;; combine types seen at the latest
70-
(tooltip seen (merge-tc-results (list t results) #t))
70+
(tooltip seen (union-tc-results (list t results) #t))
7171
old)
7272
(tooltip (cons e seen) t))]))
7373
#f))
7474
(hash-update! type-table e
7575
(λ (prev) (cond
76-
[prev (merge-tc-results (list t prev) #t)]
76+
[prev (union-tc-results (list t prev) #t)]
7777
[else t]))
7878
#f))
7979

typed-racket-test/unit-tests/metafunction-tests.rkt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,33 +75,33 @@
7575
#t)
7676
)
7777

78-
(test-suite "merge-tc-results"
78+
(test-suite "union-tc-results"
7979
(check-equal?
80-
(merge-tc-results (list))
80+
(union-tc-results (list))
8181
(ret -Bottom))
8282
(check-equal?
83-
(merge-tc-results (list (ret Univ)))
83+
(union-tc-results (list (ret Univ)))
8484
(ret Univ))
8585
(check-equal?
86-
(merge-tc-results (list (ret Univ -tt-propset (make-Path null #'x))))
86+
(union-tc-results (list (ret Univ -tt-propset (make-Path null #'x))))
8787
(ret Univ -tt-propset (make-Path null #'x)))
8888
(check-equal?
89-
(merge-tc-results (list (ret -Bottom) (ret -Symbol -tt-propset (make-Path null #'x))))
89+
(union-tc-results (list (ret -Bottom) (ret -Symbol -tt-propset (make-Path null #'x))))
9090
(ret -Symbol -tt-propset (make-Path null #'x)))
9191
(check-equal?
92-
(merge-tc-results (list (ret -String) (ret -Symbol)))
92+
(union-tc-results (list (ret -String) (ret -Symbol)))
9393
(ret (Un -Symbol -String)))
9494
(check-equal?
95-
(merge-tc-results (list (ret -String -true-propset) (ret -Symbol -true-propset)))
95+
(union-tc-results (list (ret -String -true-propset) (ret -Symbol -true-propset)))
9696
(ret (Un -Symbol -String) -true-propset))
9797
(check-equal?
98-
(merge-tc-results (list (ret (-val #f) -false-propset) (ret -Symbol -true-propset)))
98+
(union-tc-results (list (ret (-val #f) -false-propset) (ret -Symbol -true-propset)))
9999
(ret (Un -Symbol (-val #f)) -tt-propset))
100100
(check-equal?
101-
(merge-tc-results (list (ret (list (-val 0) (-val 1))) (ret (list (-val 1) (-val 2)))))
101+
(union-tc-results (list (ret (list (-val 0) (-val 1))) (ret (list (-val 1) (-val 2)))))
102102
(ret (list (Un (-val 0) (-val 1)) (Un (-val 1) (-val 2)))))
103103
(check-equal?
104-
(merge-tc-results (list (ret null null null -Symbol 'x) (ret null null null -String 'x)))
104+
(union-tc-results (list (ret null null null -Symbol 'x) (ret null null null -String 'x)))
105105
(ret null null null (Un -Symbol -String) 'x))
106106
)
107107

0 commit comments

Comments
 (0)