|
91 | 91 | (syntax-parse stx |
92 | 92 | [t:typed-struct #'t.type-name])) |
93 | 93 |
|
94 | | -;; a simple wrapper to get proc from a polymorphic or monomorhpic structure |
95 | | -(define/cond-contract (get-struct-proc sty) |
96 | | - (c:-> (c:or/c Struct? Poly?) (c:or/c #f Fun?)) |
97 | | - (Struct-proc (match sty |
98 | | - [(? Struct?) sty] |
99 | | - [(Poly: names (? Struct? sty)) sty]))) |
100 | | - |
101 | 94 |
|
102 | 95 | (define/cond-contract (tc/struct-prop-values st-tname pnames pvals) |
103 | 96 | (c:-> identifier? (c:listof identifier?) (c:listof syntax?) void?) |
|
385 | 378 | (define st-type-alias (mk-type-alias type-name tvars)) |
386 | 379 | (define st-type-alias-maybe-with-proc |
387 | 380 | (let ([maybe-proc-ty (and (or (Poly? sty) (Struct? sty)) |
388 | | - (get-struct-proc sty))]) |
| 381 | + (Struct-proc sty))]) |
389 | 382 | (if maybe-proc-ty (intersect st-type-alias maybe-proc-ty) |
390 | 383 | st-type-alias)) ) |
391 | 384 |
|
|
463 | 456 | (struct-names-type-name (parsed-struct-names parsed-struct)))) |
464 | 457 | (refine-variance! names stys tvarss)) |
465 | 458 |
|
| 459 | + |
| 460 | +(define ((make-extract predicate mismatched-field-type-errors customized-proc property-lambda-rng-chck) |
| 461 | + ty-stx st-name fld-names desc) |
| 462 | + (syntax-parse ty-stx |
| 463 | + #:literals (struct-field-index) |
| 464 | + ;; a field index is provided |
| 465 | + [n_:exact-nonnegative-integer |
| 466 | + (define n (syntax-e #'n_)) |
| 467 | + (define max-idx (sub1 (length (struct-desc-self-fields desc)))) |
| 468 | + (unless (<= n max-idx) |
| 469 | + (tc-error/fields |
| 470 | + "index too large" |
| 471 | + "index" |
| 472 | + n |
| 473 | + "maximum allowed index" |
| 474 | + max-idx |
| 475 | + #:stx ty-stx)) |
| 476 | + (define ty (list-ref (struct-desc-self-fields desc) n)) |
| 477 | + (unless (predicate ty) |
| 478 | + (tc-error/fields |
| 479 | + (format "field ~a is not a ~a" (syntax-e (list-ref fld-names n)) (car mismatched-field-type-errors)) |
| 480 | + "expected" |
| 481 | + (cdr mismatched-field-type-errors) |
| 482 | + "given" |
| 483 | + ty |
| 484 | + #:stx ty-stx)) |
| 485 | + ty] |
| 486 | + |
| 487 | + ;; a field name is provided (via struct-field-index) |
| 488 | + [(struct-field-index fld-nm:id) |
| 489 | + (define idx (index-of fld-names #'fld-nm |
| 490 | + free-identifier=?)) |
| 491 | + ;; fld-nm must be valid, because invalid field names have been reported by |
| 492 | + ;; struct-field-index at this point |
| 493 | + (list-ref (struct-desc-self-fields desc) idx)] |
| 494 | + |
| 495 | + [ty-stx:st-proc-ty^ |
| 496 | + #:do [(define ty (parse-type #'ty-stx))] |
| 497 | + (match ty |
| 498 | + [(Fun: (list arrs ...)) |
| 499 | + (make-Fun |
| 500 | + (map (lambda (arr) |
| 501 | + (Arrow-update |
| 502 | + arr |
| 503 | + dom |
| 504 | + rng |
| 505 | + (lambda (doms rng) |
| 506 | + (match (car doms) |
| 507 | + [(Name/simple: n) |
| 508 | + #:when (free-identifier=? n st-name) |
| 509 | + (void)] |
| 510 | + [(App: (Name/simple: rator) vars) |
| 511 | + #:when (free-identifier=? rator st-name) |
| 512 | + (void)] |
| 513 | + [(Univ:) |
| 514 | + (void)] |
| 515 | + [(or (Name/simple: (app syntax-e n)) n) |
| 516 | + (tc-error/fields "type mismatch in the first parameter of the function for prop:procedure" |
| 517 | + "expected" (syntax-e st-name) |
| 518 | + "got" n |
| 519 | + #:stx (st-proc-ty-property #'ty-stx))]) |
| 520 | + (when property-lambda-rng-chck |
| 521 | + (property-lambda-rng-chck rng)) |
| 522 | + (values (cdr doms) rng)))) |
| 523 | + arrs))] |
| 524 | + [_ |
| 525 | + (tc-error/fields "type mismatch" |
| 526 | + "expected" |
| 527 | + "Procedure" |
| 528 | + "given" |
| 529 | + ty |
| 530 | + #:stx #'ty-stx)])] |
| 531 | + [_ |
| 532 | + (customized-proc ty-stx)])) |
| 533 | + |
| 534 | +(define-syntax-rule (define-property-handling-table (name predicate msg-parts custimized-handling rng-chck) ...) |
| 535 | + (make-immutable-free-id-table (list (cons name (make-extract predicate msg-parts custimized-handling rng-chck)) |
| 536 | + ...))) |
| 537 | + |
| 538 | +(define property-handling-table |
| 539 | + (define-property-handling-table |
| 540 | + (#'prop:procedure Fun? (cons "function" "Procedure") |
| 541 | + (lambda (ty-stx) |
| 542 | + (tc-error/stx ty-stx |
| 543 | + "expected: a nonnegative integer literal or an annotated lambda")) |
| 544 | + #f))) |
| 545 | + |
| 546 | + |
| 547 | + |
466 | 548 | ;; extract the type annotation of prop:procedure value |
467 | | -(define/cond-contract (extract-proc-ty proc-ty-stx desc fld-names st-name) |
| 549 | +(define/cond-contract (extract-proc-ty proc-ty-stx-li desc fld-names st-name) |
468 | 550 | (c:-> (c:listof syntax?) struct-desc? (c:listof identifier?) identifier? Type?) |
469 | 551 |
|
470 | | - (unless (equal? (length proc-ty-stx) 1) |
| 552 | + |
| 553 | + (unless (equal? (length proc-ty-stx-li) 1) |
471 | 554 | (tc-error "prop:procedure can only have one value assigned to it")) |
472 | 555 |
|
473 | | - (let ([proc-ty-stx (car proc-ty-stx)]) |
474 | | - (syntax-parse proc-ty-stx |
475 | | - #:literals (struct-field-index) |
476 | | - ;; a field index is provided |
477 | | - [n_:exact-nonnegative-integer |
478 | | - (define n (syntax-e #'n_)) |
479 | | - (define max-idx (sub1 (length (struct-desc-self-fields desc)))) |
480 | | - (unless (<= n max-idx) |
481 | | - (tc-error/fields |
482 | | - "index too large" |
483 | | - "index" |
484 | | - n |
485 | | - "maximum allowed index" |
486 | | - max-idx |
487 | | - #:stx proc-ty-stx)) |
488 | | - (define ty (list-ref (struct-desc-self-fields desc) n)) |
489 | | - (unless (Fun? ty) |
490 | | - (tc-error/fields |
491 | | - (format "field ~a is not a function" (syntax-e (list-ref fld-names n))) |
492 | | - "expected" |
493 | | - "Procedure" |
494 | | - "given" |
495 | | - ty |
496 | | - #:stx proc-ty-stx)) |
497 | | - ty] |
498 | | - |
499 | | - ;; a field name is provided (via struct-field-index) |
500 | | - [(struct-field-index fld-nm:id) |
501 | | - (define idx (index-of fld-names #'fld-nm |
502 | | - free-identifier=?)) |
503 | | - ;; fld-nm must be valid, because invalid field names have been reported by |
504 | | - ;; struct-field-index at this point |
505 | | - (list-ref (struct-desc-self-fields desc) idx)] |
506 | | - |
507 | | - [ty-stx:st-proc-ty^ |
508 | | - #:do [(define ty (parse-type #'ty-stx))] |
509 | | - (match ty |
510 | | - [(Fun: (list arrs ...)) |
511 | | - (make-Fun |
512 | | - (map (lambda (arr) |
513 | | - (Arrow-update |
514 | | - arr |
515 | | - dom |
516 | | - (lambda (doms) |
517 | | - (match (car doms) |
518 | | - [(Name/simple: n) |
519 | | - #:when (free-identifier=? n st-name) |
520 | | - (void)] |
521 | | - [(App: (Name/simple: rator) vars) |
522 | | - #:when (free-identifier=? rator st-name) |
523 | | - (void)] |
524 | | - [(Univ:) |
525 | | - (void)] |
526 | | - [(or (Name/simple: (app syntax-e n)) n) |
527 | | - (tc-error/fields "type mismatch in the first parameter of the function for prop:procedure" |
528 | | - "expected" (syntax-e st-name) |
529 | | - "got" n |
530 | | - #:stx (st-proc-ty-property #'ty-stx))]) |
531 | | - |
532 | | - (cdr doms)))) |
533 | | - arrs))] |
534 | | - [_ |
535 | | - (tc-error/fields "type mismatch" |
536 | | - "expected" |
537 | | - "Procedure" |
538 | | - "given" |
539 | | - ty |
540 | | - #:stx #'ty-stx)])] |
541 | | - [_ |
542 | | - (tc-error/stx proc-ty-stx |
543 | | - "expected: a nonnegative integer literal or an annotated lambda")]))) |
| 556 | + ;; fixme for/first -> for/list |
| 557 | + (for/first ([proc-ty-stx (in-list proc-ty-stx-li)]) |
| 558 | + (define property-name (assoc-struct-property-name-property proc-ty-stx)) |
| 559 | + ((free-id-table-ref property-handling-table property-name) proc-ty-stx st-name fld-names desc))) |
544 | 560 |
|
545 | 561 | ;; check and register types for a define struct |
546 | 562 | ;; tc/struct : Listof[identifier] (U identifier (list identifier identifier)) |
|
0 commit comments