|
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