add support to struct/dc to name the selector directly
and use that in struct/c closes PR 13054 closes PR 13461 related to PR 13050
This commit is contained in:
parent
44e26d493d
commit
5c109946c2
|
@ -533,6 +533,9 @@
|
||||||
[sel-id
|
[sel-id
|
||||||
(identifier? #'sel-id)
|
(identifier? #'sel-id)
|
||||||
#t]
|
#t]
|
||||||
|
[(#:selector sel-id)
|
||||||
|
(identifier? #'sel-id)
|
||||||
|
#t]
|
||||||
[(sel-id #:parent struct-id)
|
[(sel-id #:parent struct-id)
|
||||||
(and (identifier? #'sel-id)
|
(and (identifier? #'sel-id)
|
||||||
(identifier? #'struct-id))
|
(identifier? #'struct-id))
|
||||||
|
@ -547,8 +550,6 @@
|
||||||
[(sel-name (dep-name ...) stuff1 . stuff) ;; need stuff1 here so that things like [a (>=/c x)] do not fall into this case
|
[(sel-name (dep-name ...) stuff1 . stuff) ;; need stuff1 here so that things like [a (>=/c x)] do not fall into this case
|
||||||
(sel-name? #'sel-name)
|
(sel-name? #'sel-name)
|
||||||
(let ()
|
(let ()
|
||||||
(unless (sel-name? #'sel-name)
|
|
||||||
(raise-syntax-error 'struct/dc not-field-name-str stx #'sel-name))
|
|
||||||
(for ([name (in-list (syntax->list #'(dep-name ...)))])
|
(for ([name (in-list (syntax->list #'(dep-name ...)))])
|
||||||
(unless (sel-name? name)
|
(unless (sel-name? name)
|
||||||
(raise-syntax-error 'struct/dc not-field-name-str stx name)))
|
(raise-syntax-error 'struct/dc not-field-name-str stx name)))
|
||||||
|
@ -668,6 +669,9 @@
|
||||||
[x
|
[x
|
||||||
(identifier? #'x)
|
(identifier? #'x)
|
||||||
(combine struct-id id)]
|
(combine struct-id id)]
|
||||||
|
[(#:selector sel-id)
|
||||||
|
(identifier? #'sel-id)
|
||||||
|
#'sel-id]
|
||||||
[(sel-id #:parent parent-id)
|
[(sel-id #:parent parent-id)
|
||||||
(combine #'parent-id #'sel-id)]))
|
(combine #'parent-id #'sel-id)]))
|
||||||
|
|
||||||
|
@ -1069,7 +1073,7 @@
|
||||||
(string->symbol (regexp-replace strip-reg (symbol->string (syntax-e sel)) ""))))
|
(string->symbol (regexp-replace strip-reg (symbol->string (syntax-e sel)) ""))))
|
||||||
(cond
|
(cond
|
||||||
[(free-identifier=? #'struct-name struct-id)
|
[(free-identifier=? #'struct-name struct-id)
|
||||||
field-name]
|
#`(#:selector #,sel)]
|
||||||
[else
|
[else
|
||||||
#`(#,field-name #:parent #,struct-id)])]
|
#`(#,field-name #:parent #,struct-id)])]
|
||||||
[else #f])])]
|
[else #f])])]
|
||||||
|
@ -1085,8 +1089,8 @@
|
||||||
(do-struct/dc
|
(do-struct/dc
|
||||||
#t
|
#t
|
||||||
(with-syntax ([(fields ...) (for/list ([selector-id (in-list selector-ids)]
|
(with-syntax ([(fields ...) (for/list ([selector-id (in-list selector-ids)]
|
||||||
[i (in-naturals)])
|
[i (in-naturals)])
|
||||||
(selector-id->field selector-id i))])
|
(selector-id->field selector-id i))])
|
||||||
#`(-struct/dc struct-name [fields args] ...))))]
|
#`(-struct/dc struct-name [fields args] ...))))]
|
||||||
[(_ struct-name anything ...)
|
[(_ struct-name anything ...)
|
||||||
(raise-syntax-error 'struct/c "expected a struct identifier" stx (syntax struct-name))]))
|
(raise-syntax-error 'struct/c "expected a struct identifier" stx (syntax struct-name))]))
|
||||||
|
|
|
@ -418,6 +418,7 @@ produced. Otherwise, an impersonator contract is produced.
|
||||||
maybe-dep-state
|
maybe-dep-state
|
||||||
contract-expr]]
|
contract-expr]]
|
||||||
[field-name field-id
|
[field-name field-id
|
||||||
|
(#:selector selector-id)
|
||||||
(field-id #:parent struct-id)]
|
(field-id #:parent struct-id)]
|
||||||
[maybe-lazy (code:line) #:lazy]
|
[maybe-lazy (code:line) #:lazy]
|
||||||
[maybe-flat-or-impersonator (code:line) #:flat #:impersonator]
|
[maybe-flat-or-impersonator (code:line) #:flat #:impersonator]
|
||||||
|
@ -432,13 +433,19 @@ expression is evaluated each time a selector is applied, building a new contract
|
||||||
for the fields based on the values of the @racket[dep-field-name] fields (the
|
for the fields based on the values of the @racket[dep-field-name] fields (the
|
||||||
@racket[dep-field-name] syntax is the same as the @racket[field-name] syntax).
|
@racket[dep-field-name] syntax is the same as the @racket[field-name] syntax).
|
||||||
If the field is a dependent field, then it is assumed that the contract is
|
If the field is a dependent field, then it is assumed that the contract is
|
||||||
a chaperone, but not always a flat contract (and theus the entire @racket[struct/dc]
|
a chaperone, but not always a flat contract (and thus the entire @racket[struct/dc]
|
||||||
contract is not a flat contract).
|
contract is not a flat contract).
|
||||||
If this is not the case, and the contract is
|
If this is not the case, and the contract is
|
||||||
always flat then the field must be annotated with
|
always flat then the field must be annotated with
|
||||||
the @racket[#:flat], or the field must be annotated with
|
the @racket[#:flat], or the field must be annotated with
|
||||||
@racket[#:chaperone] (in which case, it must be a mutable field).
|
@racket[#:chaperone] (in which case, it must be a mutable field).
|
||||||
|
|
||||||
|
A @racket[field-name] is either an identifier naming a field in the first
|
||||||
|
case, an identifier naming a selector in the second case indicated
|
||||||
|
by the @racket[#:selector] keyword, or
|
||||||
|
a field id for a struct that is a parent of @racket[struct-id], indicated
|
||||||
|
by the @racket[#:parent] keyword.
|
||||||
|
|
||||||
If the @racket[#:lazy] keyword appears, then the contract
|
If the @racket[#:lazy] keyword appears, then the contract
|
||||||
on the field is check lazily (only when a selector is applied);
|
on the field is check lazily (only when a selector is applied);
|
||||||
@racket[#:lazy] contracts cannot be put on mutable fields.
|
@racket[#:lazy] contracts cannot be put on mutable fields.
|
||||||
|
|
|
@ -14402,6 +14402,45 @@ so that propagation occurs.
|
||||||
(eval '(require 'provide/contract42-m2))
|
(eval '(require 'provide/contract42-m2))
|
||||||
(eval 'provide/contract42-x))
|
(eval 'provide/contract42-x))
|
||||||
10)
|
10)
|
||||||
|
|
||||||
|
(test/spec-passed/result
|
||||||
|
'provide/contract43
|
||||||
|
'(begin
|
||||||
|
(eval '(module provide/contract43-m1 racket/base
|
||||||
|
(require racket/contract)
|
||||||
|
(struct spider (legs))
|
||||||
|
(provide (contract-out (struct spider ([legs number?]))))))
|
||||||
|
|
||||||
|
(eval '(module provide/contract43-m2 racket/base
|
||||||
|
(require racket/contract 'provide/contract43-m1)
|
||||||
|
(provide provide/contract43-x)
|
||||||
|
(define provide/contract43-x
|
||||||
|
(spider-legs
|
||||||
|
(contract (struct/c spider integer?)
|
||||||
|
(spider 121)
|
||||||
|
'pos
|
||||||
|
'neg)))))
|
||||||
|
|
||||||
|
(eval '(require 'provide/contract43-m2))
|
||||||
|
(eval 'provide/contract43-x))
|
||||||
|
121)
|
||||||
|
|
||||||
|
(test/spec-passed
|
||||||
|
'provide/contract44
|
||||||
|
'(begin
|
||||||
|
(eval '(module provide/contract44-m1 racket/base
|
||||||
|
(require racket/contract)
|
||||||
|
(struct heap (v) #:transparent)
|
||||||
|
(provide (rename-out (heap new-heap)))))
|
||||||
|
|
||||||
|
(eval '(module provide/contract44-m2 racket/base
|
||||||
|
(require racket/contract 'provide/contract44-m1)
|
||||||
|
(contract (struct/c new-heap any/c)
|
||||||
|
(new-heap 121)
|
||||||
|
'pos
|
||||||
|
'neg)))
|
||||||
|
|
||||||
|
(eval '(require 'provide/contract44-m2))))
|
||||||
|
|
||||||
(contract-error-test
|
(contract-error-test
|
||||||
'contract-error-test8
|
'contract-error-test8
|
||||||
|
|
Loading…
Reference in New Issue
Block a user