|
17 | 17 |
|
18 | 18 |
|
19 | 19 | (provide/cond-contract |
20 | | - [optimize ((static-contract?) (#:trusted-positive boolean? #:trusted-negative boolean?) |
| 20 | + [optimize ((static-contract?) (#:trusted-positive boolean? #:trusted-negative boolean? #:recursive-kinds (or/c #f hash?)) |
21 | 21 | . ->* . static-contract?)]) |
22 | 22 |
|
23 | 23 | ;; Reduce a static contract to a smaller simpler one that protects in the same way |
|
110 | 110 |
|
111 | 111 |
|
112 | 112 | ;; Reduce a static contract assuming that we trusted the current side |
113 | | -(define (trusted-side-reduce sc) |
| 113 | +(define (trusted-side-reduce sc flat-sc?) |
114 | 114 | (match sc |
115 | 115 | [(->/sc: mand-args opt-args mand-kw-args opt-kw-args rest-arg (list (any/sc:) ...)) |
116 | 116 | (function/sc #t mand-args opt-args mand-kw-args opt-kw-args rest-arg #f)] |
117 | 117 | [(arr/sc: args rest (list (any/sc:) ...)) |
118 | 118 | (arr/sc args rest #f)] |
119 | 119 | [(none/sc:) any/sc] |
120 | | - [(or/sc: (? flat-terminal-kind?) ...) any/sc] |
121 | | - [(? flat-terminal-kind?) any/sc] |
| 120 | + [(or/sc: (? flat-sc?) ...) any/sc] |
| 121 | + [(? flat-sc?) any/sc] |
122 | 122 | [(syntax/sc: (? recursive-sc?)) |
123 | 123 | ;;bg; _temporary_ case to allow contracts from the `Syntax` type. |
124 | 124 | ;; This is temporary until TR has types for immutable-vector |
125 | 125 | ;; and box-immutable & changes the definition of the `Syntax` type. |
126 | 126 | any/sc] |
127 | 127 | [else sc])) |
128 | 128 |
|
129 | | -(define (flat-terminal-kind? sc) |
130 | | - (eq? 'flat (sc-terminal-kind sc))) |
131 | | - |
132 | 129 | ;; The side of a static contract describes the source of the values that |
133 | 130 | ;; the contract needs to check. |
134 | 131 | ;; - 'positive : values exported by the server module |
|
176 | 173 | ;; update-side : sc? weak-side? -> weak-side? |
177 | 174 | ;; Change the current side to something safe & strong-as-possible |
178 | 175 | ;; for optimizing the sub-contracts of the given `sc`. |
179 | | -(define (update-side sc side) |
| 176 | +(define (update-side sc side flat-sc?) |
180 | 177 | (match sc |
181 | 178 | [(or/sc: scs ...) |
182 | | - #:when (not (andmap flat-terminal-kind? scs)) |
| 179 | + #:when (not (andmap flat-sc? scs)) |
183 | 180 | (weaken-side side)] |
184 | 181 | [_ |
185 | 182 | #:when (guarded-sc? sc) |
|
195 | 192 | ;; type constructor. E.g. list/sc is "real" and or/sc is not. |
196 | 193 | (define (guarded-sc? sc) |
197 | 194 | (match sc |
198 | | - [(or (? flat-terminal-kind?) |
199 | | - (->/sc: _ _ _ _ _ _) |
| 195 | + [(or (->/sc: _ _ _ _ _ _) |
200 | 196 | (arr/sc: _ _ _) |
201 | 197 | (async-channel/sc: _) |
202 | 198 | (box/sc: _) |
|
295 | 291 |
|
296 | 292 |
|
297 | 293 | ;; If we trust a specific side then we drop all contracts protecting that side. |
298 | | -(define (optimize sc #:trusted-positive [trusted-positive #f] #:trusted-negative [trusted-negative #f]) |
| 294 | +(define (optimize sc #:trusted-positive [trusted-positive #f] #:trusted-negative [trusted-negative #f] #:recursive-kinds [recursive-kinds #f]) |
| 295 | + (define sc->kind |
| 296 | + (if (not recursive-kinds) |
| 297 | + sc-terminal-kind |
| 298 | + (λ (sc) |
| 299 | + (let loop ([sc sc]) |
| 300 | + (match sc |
| 301 | + [(recursive-sc _ _ body) |
| 302 | + (loop body)] |
| 303 | + [(or (recursive-sc-use id) |
| 304 | + (name/sc: id)) |
| 305 | + (hash-ref recursive-kinds id #f)] |
| 306 | + [_ |
| 307 | + (sc-terminal-kind sc)]))))) |
| 308 | + (define (flat-sc? sc) |
| 309 | + (eq? 'flat (sc->kind sc))) |
| 310 | + |
299 | 311 | ;; single-step: reduce and trusted-side-reduce if appropriate |
300 | 312 | (define (single-step sc maybe-weak-side) |
301 | 313 | (define trusted |
|
308 | 320 |
|
309 | 321 | (reduce |
310 | 322 | (if trusted |
311 | | - (trusted-side-reduce sc) |
| 323 | + (trusted-side-reduce sc flat-sc?) |
312 | 324 | sc))) |
313 | 325 |
|
314 | 326 | ;; full-pass: single-step at every static contract subpart |
315 | 327 | (define (full-pass sc) |
316 | 328 | (define ((recur side) sc variance) |
317 | 329 | (define curr-side (combine-variance side variance)) |
318 | | - (define next-side (update-side sc curr-side)) |
| 330 | + (define next-side (update-side sc curr-side flat-sc?)) |
319 | 331 | (single-step (sc-map sc (recur next-side)) curr-side)) |
320 | 332 | ((recur 'positive) sc 'covariant)) |
321 | 333 |
|
|
0 commit comments