Adjust contract generation for provides in TR

Use the same mechanism as ordinary require/typed to generate
contracts for provide forms.

original commit: 34076af389b717cb9840b960adb9a8761bd05db7
This commit is contained in:
Asumu Takikawa 2014-11-03 21:36:44 -05:00
parent aba90ebcff
commit b6d98917f5
4 changed files with 61 additions and 26 deletions

View File

@ -6,6 +6,7 @@
(private with-types type-contract)
(except-in syntax/parse id)
racket/match racket/syntax
syntax/flatten-begin
(types utils abbrev generalize type-table)
(typecheck provide-handling tc-toplevel tc-app-helper)
(rep type-rep)
@ -26,7 +27,7 @@
(parameterize ([optimize? (or (and (not (attribute opt?)) (optimize?))
(and (attribute opt?) (syntax-e (attribute opt?))))])
(tc-module/full stx pmb-form
(λ (new-mod before-code after-code)
(λ (new-mod before-code pre-after-code)
(with-syntax*
(;; pmb = #%plain-module-begin
[(pmb . body2) new-mod]
@ -34,6 +35,8 @@
[transformed-body (begin0 (remove-provides #'body2) (do-time "Removed provides"))]
;; add the real definitions of contracts on requires
[transformed-body (begin0 (change-contract-fixups #'transformed-body) (do-time "Fixed contract ids"))]
;; add the real definitions of contracts on the after-code
[(after-code ...) (change-provide-fixups (flatten-all-begins pre-after-code))]
;; potentially optimize the code based on the type information
[(optimized-body ...) (maybe-optimize #'transformed-body)] ;; has own call to do-time
;; add in syntax property on useless expression to draw check-syntax arrows
@ -48,7 +51,7 @@
#,(if (unbox include-extra-requires?)
extra-requires
#'(begin))
#,before-code optimized-body ... #,after-code check-syntax-help)))))))]))
#,before-code optimized-body ... after-code ... check-syntax-help)))))))]))
(define did-I-suggest-:print-type-already? #f)
(define :print-type-message " ... [Use (:print-type <expr>) to see more.]")

View File

@ -52,6 +52,7 @@
(ignore-some-expr typechecker:ignore-some)
(contract-def/maker typechecker:contract-def/maker)
(contract-def typechecker:contract-def)
(contract-def/provide typechecker:contract-def/provide)
(flat-contract-def typechecker:flat-contract-def)
(external-check typechecker:external-check)
(with-type typechecker:with-type #:mark)

View File

@ -9,7 +9,7 @@
(utils tc-utils)
(env type-name-env type-alias-env)
(rep rep-utils)
(types resolve union utils kw-types)
(types resolve union utils kw-types printer)
(prefix-in t: (types abbrev numeric-tower))
(private parse-type syntax-properties)
racket/match racket/syntax racket/list
@ -31,8 +31,14 @@
(c:parametric->/c (a) ((Type/c (c:-> #:reason (c:or/c #f string?) a))
(#:typed-side boolean?) . c:->* . (c:or/c a static-contract?)))]))
(provide type->contract define/fixup-contract? change-contract-fixups
type->contract-fail any-wrap/sc extra-requires include-extra-requires?)
(provide type->contract
define/fixup-contract?
change-contract-fixups
change-provide-fixups
type->contract-fail
any-wrap/sc
extra-requires
include-extra-requires?)
;; These check if either the define form or the body form has the syntax
;; property. Normally the define form will have the property but lifting an
@ -95,6 +101,38 @@
[_ (int-err "should never happen - not a define-values: ~a"
(syntax->datum stx))]))
;; Generate a contract for a TR provide form
(define (generate-contract-def/provide stx)
(match-define (list type untyped-id orig-id blame-id)
(contract-def/provide-property stx))
(define failure-reason #f)
(define ctc
(type->contract type
#:typed-side #t
#:kind 'impersonator
;; FIXME: get rid of this interface, make it functional
(λ (#:reason [reason #f]) (set! failure-reason reason))))
(syntax-parse stx
#:literal-sets (kernel-literals)
[(define-values ctc-id _)
;; no need for ignore, the optimizer doesn't run on this code
(if failure-reason
#`(define-syntax (#,untyped-id stx)
(tc-error/fields #:stx stx
"could not convert type to a contract"
#:more #,failure-reason
"identifier" #,(symbol->string (syntax-e orig-id))
"type" #,(pretty-format-type type #:indent 8)))
#`(begin (define ctc-id #,ctc)
(define-module-boundary-contract #,untyped-id
#,orig-id ctc-id
#:pos-source #,blame-id
#:srcloc (vector (quote #,(syntax-source orig-id))
#,(syntax-line orig-id)
#,(syntax-column orig-id)
#,(syntax-position orig-id)
#,(syntax-span orig-id)))))]))
(define extra-requires
#'(require
;; the below requires are needed since they provide identifiers
@ -116,6 +154,13 @@
(begin (set-box! include-extra-requires? #t)
(generate-contract-def e)))))
(define (change-provide-fixups forms)
(for/list ([form (in-list forms)])
(cond [(contract-def/provide-property form)
(set-box! include-extra-requires? #t)
(generate-contract-def/provide form)]
[else form])))
;; To avoid misspellings
(define impersonator-sym 'impersonator)
(define chaperone-sym 'chaperone)

View File

@ -4,6 +4,7 @@
unstable/list unstable/sequence syntax/id-table racket/dict racket/syntax
racket/struct-info racket/match syntax/parse
(only-in (private type-contract) type->contract include-extra-requires?)
(private syntax-properties)
(types printer)
(typecheck renamer def-binding)
(utils tc-utils)
@ -132,35 +133,20 @@
new-id
(list (list #'export-id #'id)))))
;; mk-value-triple : identifier? identifier? (or/c syntax? #f) -> triple/c
;; mk-value-triple : identifier? identifier? (or/c Type #f) -> triple/c
(define (mk-value-triple internal-id new-id ty)
(define contract (type->contract ty (λ (#:reason [reason #f]) reason)))
(with-syntax* ([id internal-id]
[untyped-id (freshen-id #'id)]
[export-id new-id])
(define/with-syntax ctc (generate-temporary 'generated-contract))
(define/with-syntax definitions
(if (syntax? contract)
(with-syntax* ([module-source pos-blame-id]
[the-contract (generate-temporary 'generated-contract)])
#`(define-module-boundary-contract untyped-id
id #,contract
#:pos-source module-source
#:srcloc (vector '#,(syntax-source #'id)
#,(syntax-line #'id)
#,(syntax-column #'id)
#,(syntax-position #'id)
#,(syntax-span #'id))))
#`(define-syntax (untyped-id stx)
(tc-error/fields #:stx stx
"could not convert type to a contract"
#:more #,contract
"for identifier" #,(symbol->string (syntax-e #'id))
"type" #,(pretty-format-type ty #:indent 8)))))
(contract-def/provide-property
#'(define-values (ctc) #f)
(list ty #'untyped-id #'id pos-blame-id)))
(values
#'(begin
definitions
(def-export export-id id untyped-id))
#'(begin definitions (def-export export-id id untyped-id))
new-id
null)))