|
22 | 22 | "signatures.rkt" "fail.rkt" |
23 | 23 | "promote-demote.rkt" |
24 | 24 | racket/match |
| 25 | + ;racket/trace |
25 | 26 | (contract-req) |
26 | 27 | (for-syntax |
27 | 28 | racket/base |
|
175 | 176 | ;; of them. |
176 | 177 | (struct seq (types end) #:transparent) |
177 | 178 | (struct null-end () #:transparent) |
178 | | -(struct uniform-end (type) #:transparent) |
| 179 | +(define -null-end (null-end)) |
| 180 | +;; cycle is the pattern of the rest of the seq, |
| 181 | +;; e.g. a rest argument of Num would just be (list Num) |
| 182 | +;; a rest arg of (Num Str) would be (list Num Str) |
| 183 | +(struct cycle-end (cycle) #:transparent) |
179 | 184 | (struct dotted-end (type bound) #:transparent) |
180 | 185 |
|
181 | 186 | (define (Values->seq v) |
182 | 187 | (match v |
183 | | - [(Values: ts) (seq ts (null-end))] |
| 188 | + [(Values: ts) (seq ts -null-end)] |
184 | 189 | [(ValuesDots: ts dty dbound) (seq ts (dotted-end (-result dty) dbound))] |
185 | 190 | [_ #f])) |
186 | 191 |
|
187 | 192 |
|
188 | 193 | (define (List->end v) |
189 | 194 | (match v |
190 | | - [(== -Null) (null-end)] |
191 | | - [(Listof: t) (uniform-end t)] |
| 195 | + [(== -Null) -null-end] |
| 196 | + [(Listof: t) (cycle-end (list t))] |
192 | 197 | [(ListDots: t dbound) (dotted-end t dbound)] |
193 | 198 | [_ #f])) |
194 | 199 |
|
|
256 | 261 | [((seq ss (null-end)) |
257 | 262 | (seq ts (null-end))) |
258 | 263 | (cgen/list context ss ts)] |
259 | | - ;; One is null-end the other is uniform-end |
| 264 | + ;; One is null-end the other is cycle-end |
260 | 265 | [((seq ss (null-end)) |
261 | | - (seq ts (uniform-end t-rest))) |
262 | | - (cgen/list context ss (list-extend ss ts t-rest))] |
263 | | - [((seq ss (uniform-end s-rest)) |
| 266 | + (seq ts (cycle-end t-rest))) |
| 267 | + (define ss-len (length ss)) |
| 268 | + (define ts-len (length ts)) |
| 269 | + #:return-unless (<= ts-len ss-len) #f |
| 270 | + (define fewer-args (- ss-len ts-len)) |
| 271 | + (define cycle-len (length t-rest)) |
| 272 | + #:return-unless (eqv? 0 (remainder fewer-args cycle-len)) #f |
| 273 | + (define repetitions (quotient fewer-args cycle-len)) |
| 274 | + (define new-ts (append ts (repeat-list t-rest repetitions))) |
| 275 | + (cgen/list context ss new-ts)] |
| 276 | + [((seq ss (cycle-end _)) |
264 | 277 | (seq ts (null-end))) |
265 | 278 | #f] |
266 | | - ;; Both are uniform-end |
267 | | - [((seq ss (uniform-end s-rest)) |
268 | | - (seq ts (uniform-end t-rest))) |
269 | | - (cgen/list context |
270 | | - (cons s-rest ss) |
271 | | - (cons t-rest (list-extend ss ts t-rest)))] |
| 279 | + ;; Both are cycle-end |
| 280 | + [((seq ss (cycle-end s-rest)) |
| 281 | + (seq ts (and t-end (cycle-end t-rest)))) |
| 282 | + (cgen/seq context |
| 283 | + (seq (append s-rest ss) -null-end) |
| 284 | + (seq (append t-rest ts) t-end))] |
272 | 285 | ;; dotted below, nothing above |
273 | 286 | [((seq ss (dotted-end dty dbound)) |
274 | 287 | (seq ts (null-end))) |
|
326 | 339 | (% move-dotted-rest-to-dmap (cgen (context-add-var context dbound*) s-dty t-dty) dbound* dbound)))] |
327 | 340 |
|
328 | 341 | ;; * <: ... |
329 | | - [((seq ss (uniform-end s-rest)) |
| 342 | + [((seq ss (cycle-end (list s-rest-ty))) |
330 | 343 | (seq ts (dotted-end t-dty dbound))) |
331 | 344 | #:return-unless (inferable-index? context dbound) |
332 | 345 | #f |
333 | 346 | #:return-unless (<= (length ts) (length ss)) |
334 | 347 | #f |
335 | 348 | (define new-bound (gensym dbound)) |
336 | | - (define-values (vars new-tys) (generate-dbound-prefix dbound t-dty (- (length ss) (length ts)) |
337 | | - new-bound)) |
| 349 | + (define-values (vars new-tys) |
| 350 | + (generate-dbound-prefix dbound t-dty (- (length ss) (length ts)) |
| 351 | + new-bound)) |
338 | 352 | (define-values (ss-front ss-back) (split-at ss (length ts))) |
339 | 353 | (% cset-meet |
340 | 354 | (cgen/list context ss-front ts) |
341 | 355 | (% move-vars+rest-to-dmap |
342 | 356 | (% cset-meet |
343 | | - (cgen/list (context-add context #:bounds (list new-bound) #:vars vars #:indices (list new-bound)) |
344 | | - ss-back new-tys) |
345 | | - (cgen (context-add-var context dbound) s-rest t-dty)) |
| 357 | + (cgen/list (context-add context |
| 358 | + #:bounds (list new-bound) |
| 359 | + #:vars vars |
| 360 | + #:indices (list new-bound)) |
| 361 | + ss-back |
| 362 | + new-tys) |
| 363 | + (cgen (context-add-var context dbound) s-rest-ty t-dty)) |
346 | 364 | vars dbound #:exact #t))] |
| 365 | + ;; TODO figure out how above code could be modified to support |
| 366 | + ;; cycle-end w/ a cycle of len > 1 |
| 367 | + [((seq ss (cycle-end _)) |
| 368 | + (seq ts (dotted-end _ _))) |
| 369 | + #f] |
347 | 370 |
|
348 | 371 | [((seq ss (dotted-end s-dty dbound)) |
349 | | - (seq ts (uniform-end t-rest))) |
| 372 | + (seq ts (cycle-end (list t-rest-ty)))) |
350 | 373 | (cond |
351 | 374 | [(inferable-index? context dbound) |
352 | 375 | (define new-bound (gensym dbound)) |
|
356 | 379 | (% cset-meet |
357 | 380 | (cgen/list context ss (if (positive? length-delta) |
358 | 381 | (drop-right ts length-delta) |
359 | | - (list-extend ss ts t-rest))) |
| 382 | + (list-extend ss ts t-rest-ty))) |
360 | 383 | (% move-vars+rest-to-dmap |
361 | 384 | (% cset-meet |
362 | 385 | (cgen/list (context-add context #:bounds (list new-bound) #:vars vars #:indices (list new-bound)) |
363 | 386 | new-tys (take-right ts (max 0 length-delta))) |
364 | | - (cgen (context-add-var context dbound) s-dty t-rest)) |
| 387 | + (cgen (context-add-var context dbound) s-dty t-rest-ty)) |
365 | 388 | vars dbound))] |
366 | 389 | [else |
367 | 390 | (extend-tvars (list dbound) |
368 | | - (cgen/seq (context-add context #:bounds (list dbound)) (seq ss (uniform-end s-dty)) t-seq))])])) |
| 391 | + (cgen/seq (context-add context #:bounds (list dbound)) |
| 392 | + (seq ss (cycle-end (list s-dty))) |
| 393 | + t-seq))])] |
| 394 | + [((seq ts (dotted-end _ _)) |
| 395 | + (seq ss (cycle-end _))) |
| 396 | + #f])) |
369 | 397 |
|
370 | 398 | (define/cond-contract (cgen/arrow context s-arr t-arr) |
371 | 399 | (context? Arrow? Arrow? . -> . (or/c #f cset?)) |
|
374 | 402 | (Arrow: ts t-rest t-kws t)) |
375 | 403 | (define (rest->end rest) |
376 | 404 | (match rest |
377 | | - [(? Type?) (uniform-end rest)] |
| 405 | + [(Rest: rst-ts) (cycle-end rst-ts)] |
378 | 406 | [(RestDots: ty dbound) |
379 | 407 | (dotted-end ty dbound)] |
380 | | - [_ (null-end)])) |
| 408 | + [_ -null-end])) |
381 | 409 |
|
382 | 410 | (define s-seq (seq ss (rest->end s-rest))) |
383 | 411 | (define t-seq (seq ts (rest->end t-rest))) |
|
947 | 975 | ;; like infer, but T-var is the vararg type: |
948 | 976 | (define (infer/vararg X Y S T T-var R [expected #f] |
949 | 977 | #:objs [objs '()]) |
950 | | - (define new-T (if T-var (list-extend S T T-var) T)) |
951 | 978 | (and ((length S) . >= . (length T)) |
952 | | - (infer X Y S new-T R expected #:objs objs))) |
| 979 | + (let* ([fewer-ts (- (length S) (length T))] |
| 980 | + [new-T (match T-var |
| 981 | + [(? Type? var-t) (list-extend S T var-t)] |
| 982 | + [(Rest: rst-ts) |
| 983 | + #:when (eqv? 0 (remainder fewer-ts (length rst-ts))) |
| 984 | + (append T (repeat-list rst-ts |
| 985 | + (quotient fewer-ts (length rst-ts))))] |
| 986 | + [_ T])]) |
| 987 | + (infer X Y S new-T R expected #:objs objs)))) |
953 | 988 |
|
954 | 989 | ;; like infer, but dotted-var is the bound on the ... |
955 | 990 | ;; and T-dotted is the repeated type |
|
988 | 1023 | ;(trace substs-gen) |
989 | 1024 | ;(trace cgen) |
990 | 1025 | ;(trace cgen/list) |
991 | | -;(trace cgen/arr) |
| 1026 | +;(trace cgen/arrow) |
992 | 1027 | ;(trace cgen/seq) |
993 | 1028 |
|
0 commit comments