Simplify contract generation code

Don't export type->contract except for testing. This
discourages direct use of type->contract in favor of
using the change-contract-fixup approach.

Also consolidate most of the contract-related syntax
properties into a single property containing a prefab
struct instance.
This commit is contained in:
Asumu Takikawa 2014-11-04 17:04:02 -05:00
parent 7b6ae09a2d
commit b374902bf3
7 changed files with 39 additions and 61 deletions

View File

@ -212,13 +212,10 @@ This file defines two sorts of primitives. All of them are provided into any mod
(define/with-syntax sm (if (attribute parent) (define/with-syntax sm (if (attribute parent)
#'(#:struct-maker parent) #'(#:struct-maker parent)
#'())) #'()))
(define property
(if (attribute parent)
contract-def/maker-property
contract-def-property))
;; define `cnt*` to be fixed up later by the module type-checking ;; define `cnt*` to be fixed up later by the module type-checking
(define cnt* (define cnt*
(syntax-local-lift-expression (property #'#f #'ty))) (syntax-local-lift-expression
(make-contract-def-rhs #'ty #f (attribute parent))))
(quasisyntax/loc stx (quasisyntax/loc stx
(begin (begin
#,(internal #'(require/typed-internal hidden ty . sm)) #,(internal #'(require/typed-internal hidden ty . sm))
@ -268,6 +265,10 @@ This file defines two sorts of primitives. All of them are provided into any mod
;; make-predicate ;; make-predicate
;; cast ;; cast
;; Helper to construct syntax for contract definitions
(define-for-syntax (make-contract-def-rhs type flat? maker?)
(contract-def-property #'#f `#s(contract-def ,type ,flat? ,maker? untyped)))
(define-syntax (define-predicate stx) (define-syntax (define-predicate stx)
(syntax-parse stx (syntax-parse stx
[(_ name:id ty:expr) [(_ name:id ty:expr)
@ -285,7 +286,7 @@ This file defines two sorts of primitives. All of them are provided into any mod
(syntax-parse stx (syntax-parse stx
[(_ ty:expr) [(_ ty:expr)
(define name (syntax-local-lift-expression (define name (syntax-local-lift-expression
(flat-contract-def-property #'#f #'ty))) (make-contract-def-rhs #'ty #t #f)))
(define (check-valid-type _) (define (check-valid-type _)
(define type (parse-type #'ty)) (define type (parse-type #'ty))
(define vars (fv type)) (define vars (fv type))
@ -320,7 +321,7 @@ This file defines two sorts of primitives. All of them are provided into any mod
#'v] #'v]
[else [else
(define ctc (syntax-local-lift-expression (define ctc (syntax-local-lift-expression
(contract-def-property #'#f #'ty))) (make-contract-def-rhs #'ty #f #f)))
(define (check-valid-type _) (define (check-valid-type _)
(define type (parse-type #'ty)) (define type (parse-type #'ty))
(define vars (fv type)) (define vars (fv type))

View File

@ -50,12 +50,8 @@
(ignore typechecker:ignore #:mark) (ignore typechecker:ignore #:mark)
(ignore-some typechecker:ignore-some #:mark) (ignore-some typechecker:ignore-some #:mark)
(ignore-some-expr typechecker:ignore-some) (ignore-some-expr typechecker:ignore-some)
(contract-def/maker typechecker:contract-def/maker)
(contract-def typechecker:contract-def) (contract-def typechecker:contract-def)
;; for exporting from a with-type expression
(contract-def/with-type typechecker:contract-def/with-type)
(contract-def/provide typechecker:contract-def/provide) (contract-def/provide typechecker:contract-def/provide)
(flat-contract-def typechecker:flat-contract-def)
(external-check typechecker:external-check) (external-check typechecker:external-check)
(with-type typechecker:with-type #:mark) (with-type typechecker:with-type #:mark)
(type-ascription type-ascription) (type-ascription type-ascription)

View File

@ -31,39 +31,24 @@
(c:parametric->/c (a) ((Type/c (c:-> #:reason (c:or/c #f string?) a)) (c:parametric->/c (a) ((Type/c (c:-> #:reason (c:or/c #f string?) a))
(#:typed-side boolean?) . c:->* . (c:or/c a static-contract?)))])) (#:typed-side boolean?) . c:->* . (c:or/c a static-contract?)))]))
(provide type->contract (provide change-contract-fixups
define/fixup-contract?
change-contract-fixups
change-provide-fixups change-provide-fixups
type->contract-fail
any-wrap/sc any-wrap/sc
extra-requires extra-requires
include-extra-requires?) include-extra-requires?)
;; These check if either the define form or the body form has the syntax ;; submod for testing
;; property. Normally the define form will have the property but lifting an (module* test-exports #f (provide type->contract))
;; expression to the module level will put the property on the body.
(define-syntax (contract-finders stx)
(define-syntax-class clause
(pattern name:id
#:with external-name (format-id #'name "typechecker:~a" #'name)
#:with syntax-class-name (format-id #'name "~a^" #'name)))
(syntax-parse stx
[(_ #:union union-name:id :clause ... )
#'(begin
(define external-name
(syntax-parser
#:literal-sets (kernel-literals)
[(~or (~var v syntax-class-name)
(define-values (_) (~var v syntax-class-name)))
(attribute v.value)]
[_ #f])) ...
(define (union-name stx)
(or (external-name stx) ...)))]))
(contract-finders (struct contract-def (type flat? maker? typed-side) #:prefab)
#:union define/fixup-contract?
contract-def flat-contract-def contract-def/maker contract-def/with-type) ;; Checks if the given syntax needs to be fixed up for contract generation
;; and if yes it returns the information stored in the property
(define (get-contract-def-property stx)
(syntax-parse stx
#:literal-sets (kernel-literals)
[(define-values (_) e) (contract-def-property #'e)]
[_ #f]))
;; type->contract-fail : Syntax Type #:ctc-str String ;; type->contract-fail : Syntax Type #:ctc-str String
;; -> #:reason (Option String) -> Void ;; -> #:reason (Option String) -> Void
@ -80,11 +65,9 @@
to-check)) to-check))
(define (generate-contract-def stx) (define (generate-contract-def stx)
(define prop (define/fixup-contract? stx)) (define prop (get-contract-def-property stx))
(define maker? (typechecker:contract-def/maker stx)) (match-define (contract-def type-stx flat? maker? typed-side) prop)
(define flat? (typechecker:flat-contract-def stx)) (define typ (parse-type type-stx))
(define typed? (and (typechecker:contract-def/with-type stx) #t))
(define typ (parse-type prop))
(define kind (if flat? 'flat 'impersonator)) (define kind (if flat? 'flat 'impersonator))
(syntax-parse stx #:literals (define-values) (syntax-parse stx #:literals (define-values)
[(define-values (n) _) [(define-values (n) _)
@ -95,10 +78,10 @@
typ typ
;; this value is from the typed side (require/typed, make-predicate, etc) ;; this value is from the typed side (require/typed, make-predicate, etc)
;; unless it's used for with-type ;; unless it's used for with-type
#:typed-side typed? #:typed-side (from-typed? typed-side)
#:kind kind #:kind kind
(type->contract-fail (type->contract-fail
typ prop typ type-stx
#:ctc-str (if flat? "predicate" "contract")))]) #:ctc-str (if flat? "predicate" "contract")))])
(ignore ; should be ignored by the optimizer (ignore ; should be ignored by the optimizer
(quasisyntax/loc stx (define-values (n) cnt)))))] (quasisyntax/loc stx (define-values (n) cnt)))))]
@ -153,7 +136,7 @@
(define (change-contract-fixups forms) (define (change-contract-fixups forms)
(for/list ((e (in-list forms))) (for/list ((e (in-list forms)))
(if (not (define/fixup-contract? e)) (if (not (get-contract-def-property e))
e e
(begin (set-box! include-extra-requires? #t) (begin (set-box! include-extra-requires? #t)
(generate-contract-def e))))) (generate-contract-def e)))))

View File

@ -43,8 +43,6 @@
(define old-context (unbox typed-context?)) (define old-context (unbox typed-context?))
(unless (not old-context) (unless (not old-context)
(tc-error/stx stx "with-type cannot be used in a typed module.")) (tc-error/stx stx "with-type cannot be used in a typed module."))
(define (no-contract t [stx stx])
(type->contract-fail t stx))
(set-box! typed-context? #t) (set-box! typed-context? #t)
(do-standard-inits) (do-standard-inits)
(define fv-types (for/list ([t (in-syntax fvtys)]) (define fv-types (for/list ([t (in-syntax fvtys)])
@ -52,13 +50,12 @@
(define ex-types (for/list ([t (in-syntax extys)]) (define ex-types (for/list ([t (in-syntax extys)])
(parse-type t))) (parse-type t)))
(define-values (fv-ctc-ids fv-ctc-defs) (define-values (fv-ctc-ids fv-ctc-defs)
(type-stxs->ids+defs (syntax->list fvtys) contract-def-property)) (type-stxs->ids+defs (syntax->list fvtys) 'untyped))
(define-values (ex-ctc-ids ex-ctc-defs) (define-values (ex-ctc-ids ex-ctc-defs)
(type-stxs->ids+defs (syntax->list extys) contract-def/with-type-property)) (type-stxs->ids+defs (syntax->list extys) 'typed))
(define-values (region-ctc-ids region-ctc-defs) (define-values (region-ctc-ids region-ctc-defs)
(if expr? (if expr?
(type-stxs->ids+defs (values-stx->type-stxs resty) (type-stxs->ids+defs (values-stx->type-stxs resty) 'typed)
contract-def/with-type-property)
(values null null))) (values null null)))
(define region-tc-result (define region-tc-result
(and expr? (parse-tc-results resty))) (and expr? (parse-tc-results resty)))
@ -153,12 +150,15 @@
(syntax->list #'(t ...))] (syntax->list #'(t ...))]
[t (list #'t)])) [t (list #'t)]))
;; type-stxs->ids+defs : (Listof Syntax) Procedure -> (Listof Id Syntax) ;; type-stxs->ids+defs : (Listof Syntax) Symbol -> (Listof Id Syntax)
;; Create identifiers and definition syntaxes for contract generation ;; Create identifiers and definition syntaxes for contract generation
(define (type-stxs->ids+defs type-stxs property) (define (type-stxs->ids+defs type-stxs typed-side)
(for/lists (_1 _2) ([t (in-list type-stxs)]) (for/lists (_1 _2) ([t (in-list type-stxs)])
(define ctc-id (generate-temporary)) (define ctc-id (generate-temporary))
(values ctc-id #`(define-values (#,ctc-id) #,(property #'#f t))))) (values ctc-id
#`(define-values (#,ctc-id)
#,(contract-def-property
#'#f `#s(contract-def ,t #f #f ,typed-side))))))
(define (wt-core stx) (define (wt-core stx)
(define-syntax-class typed-id (define-syntax-class typed-id

View File

@ -3,7 +3,7 @@
(require "../utils/utils.rkt" (require "../utils/utils.rkt"
unstable/list unstable/sequence syntax/id-table racket/dict racket/syntax unstable/list unstable/sequence syntax/id-table racket/dict racket/syntax
racket/struct-info racket/match syntax/parse racket/struct-info racket/match syntax/parse
(only-in (private type-contract) type->contract include-extra-requires?) (only-in (private type-contract) include-extra-requires?)
(private syntax-properties) (private syntax-properties)
(types printer) (types printer)
(typecheck renamer def-binding) (typecheck renamer def-binding)
@ -135,8 +135,6 @@
;; mk-value-triple : identifier? identifier? (or/c Type #f) -> triple/c ;; mk-value-triple : identifier? identifier? (or/c Type #f) -> triple/c
(define (mk-value-triple internal-id new-id ty) (define (mk-value-triple internal-id new-id ty)
(define contract (type->contract ty (λ (#:reason [reason #f]) reason)))
(with-syntax* ([id internal-id] (with-syntax* ([id internal-id]
[untyped-id (freshen-id #'id)] [untyped-id (freshen-id #'id)]
[export-id new-id]) [export-id new-id])

View File

@ -275,15 +275,14 @@
(define (type-check forms0) (define (type-check forms0)
(define forms (syntax->list forms0)) (define forms (syntax->list forms0))
(do-time "before form splitting") (do-time "before form splitting")
(define-values (type-aliases struct-defs stx-defs0 val-defs0 provs reqs) (define-values (type-aliases struct-defs stx-defs0 val-defs0 provs)
(filter-multiple (filter-multiple
forms forms
type-alias? type-alias?
(lambda (e) (or (typed-struct? e) (typed-struct/exec? e))) (lambda (e) (or (typed-struct? e) (typed-struct/exec? e)))
parse-syntax-def parse-syntax-def
parse-def parse-def
provide? provide?))
define/fixup-contract?))
(do-time "Form splitting done") (do-time "Form splitting done")
(define-values (type-alias-names type-alias-map) (define-values (type-alias-names type-alias-map)

View File

@ -9,6 +9,7 @@
(types abbrev numeric-tower union) (types abbrev numeric-tower union)
(static-contracts combinators optimize) (static-contracts combinators optimize)
(submod typed-racket/private/type-contract numeric-contracts) (submod typed-racket/private/type-contract numeric-contracts)
(submod typed-racket/private/type-contract test-exports)
(only-in racket/contract contract) (only-in racket/contract contract)
rackunit) rackunit)
(provide tests) (provide tests)