Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support prop:evt #1229

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion typed-racket-lib/typed-racket/base-env/base-env.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -1553,7 +1553,7 @@
[system-idle-evt (-> (-evt -Void))]
[alarm-evt (-> -Real (-mu x (-evt x)))]
[handle-evt? (asym-pred Univ B (-PS (-is-type 0 (-evt Univ)) -tt))]
[prop:evt (-struct-property (Un (-evt Univ) (-> -Self ManyUniv) -Nat) #'evt?)]
[prop:evt (-struct-property (Un (-evt Univ) (-> -Self Univ) -Nat) #'evt?)]
[current-evt-pseudo-random-generator
(-Param -Pseudo-Random-Generator -Pseudo-Random-Generator)]

Expand Down
8 changes: 5 additions & 3 deletions typed-racket-lib/typed-racket/base-env/prims-struct.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,15 @@
([val (attribute prop-val)]
[name (attribute prop)])
(cond
[(free-identifier=? name #'prop:procedure)
[(or (free-identifier=? name #'prop:procedure)
(free-identifier=? name #'prop:evt))
(define tname (or (attribute type) st-name))
(define sty-stx (if (null? type-vars)
tname
(quasisyntax/loc tname
(#,tname #,@type-vars))))
(maybe-extract-prop-proc-ty-ann sty-stx val)]
(define-values (val^ ty^) (maybe-extract-prop-proc-ty-ann sty-stx val))
capfredf marked this conversation as resolved.
Show resolved Hide resolved
(values val^ (assoc-struct-property-name-property ty^ name))]
[else (values val #f)])))]
#:attr proc-ty (if (null? proc-tys) #f
proc-tys)
Expand Down Expand Up @@ -200,7 +202,7 @@


;; This function tries to extract the type annotation on a lambda
;; expression for prop:precedure.
;; expression for prop:procedure.
;;
;; sty-stx: the syntax that represents a structure type. For a monomorhpic
;; structure type, sty-stx is the identifier for its name. For a polymorphic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
(type-inst type-inst)
(row-inst row-inst)
(st-proc-ty st-proc-ty)
(assoc-struct-property-name assoc-struct-property-name)
(type-label type-label)
(optional-non-immediate-arg optional-non-immediate-arg)
(optional-immediate-arg optional-immediate-arg)
Expand Down
7 changes: 5 additions & 2 deletions typed-racket-lib/typed-racket/rep/type-rep.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -806,8 +806,11 @@


(define/cond-contract (Struct-proc* sty)
(-> Struct? (or/c #f Fun?))
(define b (Struct-proc sty))
(-> (or/c Poly? Struct?) (or/c #f Type?))
(define sty^ (match sty
[(? Struct?) sty]
[(Poly: _ (? Struct? sty)) sty]))
(define b (Struct-proc sty^))
(and b (unbox b)))

(define (make-Struct* name parent flds proc poly? pred-id properties)
Expand Down
137 changes: 86 additions & 51 deletions typed-racket-lib/typed-racket/typecheck/tc-structs.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,6 @@
(syntax-parse stx
[t:typed-struct #'t.type-name]))

;; a simple wrapper to get proc from a polymorphic or monomorhpic structure
(define/cond-contract (get-struct-proc sty)
(c:-> (c:or/c Struct? Poly?) (c:or/c #f Fun?))
(Struct-proc (match sty
[(? Struct?) sty]
[(Poly: names (? Struct? sty)) sty])))


(define/cond-contract (tc/struct-prop-values st-tname pnames pvals)
(c:-> identifier? (c:listof identifier?) (c:listof syntax?) void?)
Expand Down Expand Up @@ -385,8 +378,9 @@
(define st-type-alias (mk-type-alias type-name tvars))
(define st-type-alias-maybe-with-proc
(let ([maybe-proc-ty (and (or (Poly? sty) (Struct? sty))
(get-struct-proc sty))])
(if maybe-proc-ty (intersect st-type-alias maybe-proc-ty)
(Struct-proc sty))])
(if maybe-proc-ty
(intersect st-type-alias maybe-proc-ty)
st-type-alias)) )

;; simple abstraction for handling field getters or setters
Expand Down Expand Up @@ -463,49 +457,58 @@
(struct-names-type-name (parsed-struct-names parsed-struct))))
(refine-variance! names stys tvarss))

;; extract the type annotation of prop:procedure value
(define/cond-contract (extract-proc-ty proc-ty-stx desc fld-names st-name)
(c:-> (c:listof syntax?) struct-desc? (c:listof identifier?) identifier? Type?)

(unless (equal? (length proc-ty-stx) 1)
(tc-error "prop:procedure can only have one value assigned to it"))

(let ([proc-ty-stx (car proc-ty-stx)])
(syntax-parse proc-ty-stx
#:literals (struct-field-index)
;; a field index is provided
[n_:exact-nonnegative-integer
(define n (syntax-e #'n_))
(define max-idx (sub1 (length (struct-desc-self-fields desc))))
(unless (<= n max-idx)
(tc-error/fields
"index too large"
"index"
n
"maximum allowed index"
max-idx
#:stx proc-ty-stx))
(define ty (list-ref (struct-desc-self-fields desc) n))
(define ((make-extract check-field-type check-doms-rng error-msg)
ty-stx st-name fld-names desc)
(syntax-parse ty-stx
#:literals (struct-field-index)
;; a field index is provided
[n_:exact-nonnegative-integer
(define n (syntax-e #'n_))
(define max-idx (sub1 (length (struct-desc-self-fields desc))))
(unless (<= n max-idx)
(tc-error/fields
"index too large"
"index"
n
"maximum allowed index"
max-idx
#:stx ty-stx))
(define ty (list-ref (struct-desc-self-fields desc) n))
(check-field-type ty-stx (list-ref fld-names n) ty)]

;; a field name is provided (via struct-field-index)
[(struct-field-index fld-nm:id)
(define idx (index-of fld-names #'fld-nm
free-identifier=?))
;; fld-nm must be valid, because invalid field names have been reported by
;; struct-field-index at this point
(list-ref (struct-desc-self-fields desc) idx)]

[ty-stx:st-proc-ty^
#:do [(define ty (parse-type #'ty-stx))]
(check-doms-rng #'ty-stx ty st-name)
]
[_ (tc-error/stx ty-stx error-msg)]))

(define-syntax-rule (define-property-handling-table (name check-field-type rng-chck error-msg) ...)
(make-immutable-free-id-table (list (cons name (make-extract check-field-type rng-chck error-msg))
...)))

(define property-handling-table
(define-property-handling-table
(#'prop:procedure
(lambda (ty-stx fld-name ty)
(unless (Fun? ty)
(tc-error/fields
(format "field ~a is not a function" (syntax-e (list-ref fld-names n)))
(format "field ~a is not a function" (syntax-e fld-name))
"expected"
"Procedure"
"given"
ty
#:stx proc-ty-stx))
ty]

;; a field name is provided (via struct-field-index)
[(struct-field-index fld-nm:id)
(define idx (index-of fld-names #'fld-nm
free-identifier=?))
;; fld-nm must be valid, because invalid field names have been reported by
;; struct-field-index at this point
(list-ref (struct-desc-self-fields desc) idx)]

[ty-stx:st-proc-ty^
#:do [(define ty (parse-type #'ty-stx))]
#:stx ty-stx))
ty)
(lambda (ty-stx ty st-name)
(match ty
[(Fun: (list arrs ...))
(make-Fun
Expand All @@ -527,8 +530,7 @@
(tc-error/fields "type mismatch in the first parameter of the function for prop:procedure"
"expected" (syntax-e st-name)
"got" n
#:stx (st-proc-ty-property #'ty-stx))])

#:stx (st-proc-ty-property ty-stx))])
(cdr doms))))
arrs))]
[_
Expand All @@ -537,10 +539,43 @@
"Procedure"
"given"
ty
#:stx #'ty-stx)])]
[_
(tc-error/stx proc-ty-stx
"expected: a nonnegative integer literal or an annotated lambda")])))
#:stx ty-stx)]))
"expected: a nonnegative integer literal or an annotated lambda")
(#'prop:evt
(lambda (ty-stx field-name ty)
(if (Evt? ty)
capfredf marked this conversation as resolved.
Show resolved Hide resolved
ty
(make-Evt (Un))))
(lambda (ty-stx ty st-name)
(match ty
[(Fun: (list (Arrow: doms _ _ (Values: (list (Result: rng_t _ _))))))
(unless (= (length doms) 1)
(tc-error/stx ty-stx
"expected: a function that takes only one argument"))
(if (Evt? rng_t)
rng_t
;; fixme: return struct type alias, not always ready
capfredf marked this conversation as resolved.
Show resolved Hide resolved
(-mu x (make-Evt x)))]
[_ (if (Evt? ty)
ty
(tc-error/stx ty-stx
"expected: a nonnegative integer literal, an annotated lambda that returns an event, or an event"))]))
"expected: a nonnegative integer literal, an annotated lambda that returns an event, or an event")))



;; extract the type annotation of prop:procedure value
(define/cond-contract (extract-proc-ty proc-ty-stx-li desc fld-names st-name)
(c:-> (c:listof syntax?) struct-desc? (c:listof identifier?) identifier? Type?)


(unless (equal? (length proc-ty-stx-li) 1)
(tc-error "prop:procedure can only have one value assigned to it"))

;; fixme for/first -> for/list
capfredf marked this conversation as resolved.
Show resolved Hide resolved
(for/first ([proc-ty-stx (in-list proc-ty-stx-li)])
(define property-name (assoc-struct-property-name-property proc-ty-stx))
((free-id-table-ref property-handling-table property-name) proc-ty-stx st-name fld-names desc)))

;; check and register types for a define struct
;; tc/struct : Listof[identifier] (U identifier (list identifier identifier))
Expand Down
39 changes: 39 additions & 0 deletions typed-racket-test/succeed/prop-evt.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#lang typed/racket/base

(define ch ((inst make-channel Number)))


(struct aaa0 ((evt : (Evtof Number)))
#:property prop:evt (struct-field-index evt))

(thread (lambda ()
(channel-put ch 10)))

(ann (sync (aaa0 ch)) Number)


(struct aaa1 ([evt : (Evtof Number)])
#:property prop:evt 0)

(thread (lambda ()
(channel-put ch 10)))

(ann (sync (aaa1 ch)) Number)

(struct aaa2 ([evt : (Evtof Number)])
#:property prop:evt (lambda ([self : aaa2]) : (Evtof Number)
(aaa2-evt self)))

(thread (lambda ()
(channel-put ch 10)))
(ann (sync (aaa2 ch)) Number)


(define ch2 ((inst make-channel String)))
(struct aaa3 ()
#:property prop:evt (ann ch2 (Evtof String)))

(thread (lambda ()
(channel-put ch2 "10")))

(ann (sync (aaa3)) String)
4 changes: 1 addition & 3 deletions typed-racket-test/succeed/struct-props.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@
#:property prop:custom-write
(lambda ([self : foo] [p : Output-Port] [m : (U Boolean 1 0)]) : Void
(displayln (+ (foo-x self) 20) p))
#:property prop:evt 0
capfredf marked this conversation as resolved.
Show resolved Hide resolved

#:property prop:custom-print-quotable 'always)

(struct foobar^ foo ([y : Number])
#:property prop:custom-write
(lambda ([self : foobar^] [p : Output-Port] [m : (U Boolean 1 0)]) : Void
(displayln (+ (foobar^-y self) 20) p))

#:property prop:evt (make-channel)
#:property prop:evt (ann (make-channel) (Evtof Any))

#:property prop:custom-print-quotable 'self)

Expand Down