Add support for typechecking contracted functions
This commit is contained in:
parent
6fe2745f55
commit
f844cb8b92
|
@ -9,6 +9,7 @@
|
||||||
"tc-app/tc-app-objects.rkt"
|
"tc-app/tc-app-objects.rkt"
|
||||||
"tc-app/tc-app-special.rkt"
|
"tc-app/tc-app-special.rkt"
|
||||||
"tc-app/tc-app-values.rkt"
|
"tc-app/tc-app-values.rkt"
|
||||||
|
"tc-app/tc-app-contracts.rkt"
|
||||||
"tc-app/tc-app-main.rkt"
|
"tc-app/tc-app-main.rkt"
|
||||||
"signatures.rkt")
|
"signatures.rkt")
|
||||||
|
|
||||||
|
@ -23,4 +24,5 @@
|
||||||
tc-app-hetero@ tc-app-list@ tc-app-apply@
|
tc-app-hetero@ tc-app-list@ tc-app-apply@
|
||||||
(() tc-app-values@)
|
(() tc-app-values@)
|
||||||
tc-app-keywords@
|
tc-app-keywords@
|
||||||
tc-app-objects@ tc-app-eq@ tc-app-lambda@ tc-app-special@))
|
tc-app-objects@ tc-app-eq@ tc-app-lambda@ tc-app-special@
|
||||||
|
tc-app-contracts@))
|
||||||
|
|
|
@ -36,3 +36,6 @@
|
||||||
(define-signature tc-app-special^
|
(define-signature tc-app-special^
|
||||||
([cond-contracted tc/app-special checker/c]))
|
([cond-contracted tc/app-special checker/c]))
|
||||||
|
|
||||||
|
(define-signature tc-app-contracts^
|
||||||
|
([cond-contracted tc/app-contracts checker/c]))
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
#lang racket/unit
|
||||||
|
|
||||||
|
;; This module provides custom type-checking rules for the expansion
|
||||||
|
;; of contracted values
|
||||||
|
|
||||||
|
(require "../../utils/utils.rkt"
|
||||||
|
"signatures.rkt"
|
||||||
|
"utils.rkt"
|
||||||
|
syntax/parse syntax/stx racket/match
|
||||||
|
racket/dict
|
||||||
|
racket/format
|
||||||
|
(env global-env)
|
||||||
|
(typecheck signatures)
|
||||||
|
(types base-abbrev resolve subtype union utils)
|
||||||
|
(rep type-rep)
|
||||||
|
(utils tc-utils)
|
||||||
|
(for-template racket/base
|
||||||
|
;; shift -1 because it's provided +1
|
||||||
|
racket/contract/private/provide))
|
||||||
|
|
||||||
|
(import tc-expr^)
|
||||||
|
(export tc-app-contracts^)
|
||||||
|
|
||||||
|
(define-tc/app-syntax-class (tc/app-contracts expected)
|
||||||
|
(pattern (ctc-id:id blame e ...)
|
||||||
|
;; check that this is an application from the contract system
|
||||||
|
#:when (contract-rename-id-property #'ctc-id)
|
||||||
|
(check-contract #'ctc-id #'(e ...) expected)))
|
||||||
|
|
||||||
|
;; Assume that the contracted thing is of the same type the type
|
||||||
|
;; environment assigned to the exported identifier. Note that this
|
||||||
|
;; is only sound if the contract is a chaperone contract, so don't
|
||||||
|
;; put things in the base type environment if they have impersonator
|
||||||
|
;; contracts installed.
|
||||||
|
(define (check-contract orig-value-id other-args expected)
|
||||||
|
(tc-expr/check #`(#%plain-app
|
||||||
|
#,(contract-rename-id-property orig-value-id)
|
||||||
|
. #,other-args)
|
||||||
|
expected))
|
||||||
|
|
|
@ -10,7 +10,10 @@
|
||||||
(rep type-rep)
|
(rep type-rep)
|
||||||
(utils tc-utils)
|
(utils tc-utils)
|
||||||
(r:infer infer)
|
(r:infer infer)
|
||||||
(for-label racket/base))
|
(for-label racket/base)
|
||||||
|
;; adjusted -1 since it's provided for-syntax
|
||||||
|
(only-in (for-template racket/contract/private/provide)
|
||||||
|
contract-neg-party-property))
|
||||||
|
|
||||||
|
|
||||||
(import tc-expr^)
|
(import tc-expr^)
|
||||||
|
@ -24,10 +27,17 @@
|
||||||
((#%plain-app cpce s-kp fn kpe kws num)
|
((#%plain-app cpce s-kp fn kpe kws num)
|
||||||
kw-list
|
kw-list
|
||||||
(#%plain-app list . kw-arg-list)
|
(#%plain-app list . kw-arg-list)
|
||||||
. pos-args))
|
. *pos-args))
|
||||||
#:declare cpce (id-from 'checked-procedure-check-and-extract 'racket/private/kw)
|
#:declare cpce (id-from 'checked-procedure-check-and-extract 'racket/private/kw)
|
||||||
#:declare s-kp (id-from 'struct:keyword-procedure 'racket/private/kw)
|
#:declare s-kp (id-from 'struct:keyword-procedure 'racket/private/kw)
|
||||||
#:declare kpe (id-from 'keyword-procedure-extract 'racket/private/kw)
|
#:declare kpe (id-from 'keyword-procedure-extract 'racket/private/kw)
|
||||||
|
;; If this application is of a module boundary contract function or not
|
||||||
|
;; If #t, then the contract system has inserted an extra argument which we
|
||||||
|
;; need to ignore
|
||||||
|
#:attr boundary-ctc? (contract-neg-party-property #'fn)
|
||||||
|
#:with pos-args (if (attribute boundary-ctc?)
|
||||||
|
(stx-cdr #'*pos-args)
|
||||||
|
#'*pos-args)
|
||||||
(match (tc-expr #'fn)
|
(match (tc-expr #'fn)
|
||||||
[(tc-result1:
|
[(tc-result1:
|
||||||
(Poly: vars
|
(Poly: vars
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
|
|
||||||
(import tc-expr^ tc-app-keywords^
|
(import tc-expr^ tc-app-keywords^
|
||||||
tc-app-hetero^ tc-app-list^ tc-app-apply^ tc-app-values^
|
tc-app-hetero^ tc-app-list^ tc-app-apply^ tc-app-values^
|
||||||
tc-app-objects^ tc-app-eq^ tc-app-lambda^ tc-app-special^)
|
tc-app-objects^ tc-app-eq^ tc-app-lambda^ tc-app-special^
|
||||||
|
tc-app-contracts^)
|
||||||
(export tc-app^)
|
(export tc-app^)
|
||||||
|
|
||||||
(define-tc/app-syntax-class (tc/app-regular* expected)
|
(define-tc/app-syntax-class (tc/app-regular* expected)
|
||||||
|
@ -34,6 +35,7 @@
|
||||||
tc/app-objects
|
tc/app-objects
|
||||||
tc/app-lambda
|
tc/app-lambda
|
||||||
tc/app-special
|
tc/app-special
|
||||||
|
tc/app-contracts
|
||||||
tc/app-regular*)
|
tc/app-regular*)
|
||||||
|
|
||||||
;; the main dispatching function
|
;; the main dispatching function
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
(only-in racket/list split-at)
|
(only-in racket/list split-at)
|
||||||
(typecheck internal-forms tc-envops)
|
(typecheck internal-forms tc-envops)
|
||||||
;; Needed for current implementation of typechecking letrec-syntax+values
|
;; Needed for current implementation of typechecking letrec-syntax+values
|
||||||
(for-template (only-in racket/base letrec-values))
|
(for-template (only-in racket/base letrec-values)
|
||||||
|
;; see tc-app-contracts.rkt
|
||||||
|
racket/contract/private/provide)
|
||||||
|
|
||||||
(for-label (only-in '#%paramz [parameterization-key pz:pk])
|
(for-label (only-in '#%paramz [parameterization-key pz:pk])
|
||||||
(only-in racket/private/class-internal find-method/who)))
|
(only-in racket/private/class-internal find-method/who)))
|
||||||
|
@ -35,7 +37,9 @@
|
||||||
;; tc-id : identifier -> tc-results
|
;; tc-id : identifier -> tc-results
|
||||||
(define/cond-contract (tc-id id)
|
(define/cond-contract (tc-id id)
|
||||||
(--> identifier? full-tc-results/c)
|
(--> identifier? full-tc-results/c)
|
||||||
(let* ([ty (lookup-type/lexical id)])
|
(define rename-id (contract-rename-id-property id))
|
||||||
|
(define id* (or rename-id id))
|
||||||
|
(let* ([ty (lookup-type/lexical id*)])
|
||||||
(ret ty
|
(ret ty
|
||||||
(make-FilterSet (-not-filter (-val #f) id)
|
(make-FilterSet (-not-filter (-val #f) id)
|
||||||
(-filter (-val #f) id))
|
(-filter (-val #f) id))
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
(for-template
|
(for-template
|
||||||
(only-in syntax/location quote-module-name)
|
(only-in syntax/location quote-module-name)
|
||||||
racket/base
|
racket/base
|
||||||
|
racket/contract/private/provide
|
||||||
(env env-req)))
|
(env env-req)))
|
||||||
|
|
||||||
(provide/cond-contract
|
(provide/cond-contract
|
||||||
|
@ -103,6 +104,10 @@
|
||||||
(register-scoped-tvars #'t.id (parse-literal-alls #'t.type))
|
(register-scoped-tvars #'t.id (parse-literal-alls #'t.type))
|
||||||
(list)]
|
(list)]
|
||||||
|
|
||||||
|
;; definitions lifted from contracts should be ignored
|
||||||
|
[(define-values (lifted) expr)
|
||||||
|
#:when (contract-lifted-property #'expr)
|
||||||
|
(list)]
|
||||||
|
|
||||||
;; values definitions
|
;; values definitions
|
||||||
[(define-values (var ...) expr)
|
[(define-values (var ...) expr)
|
||||||
|
@ -150,6 +155,11 @@
|
||||||
#:literals (define-values begin)
|
#:literals (define-values begin)
|
||||||
[(~or _:ignore^ _:ignore-some^) (list)]
|
[(~or _:ignore^ _:ignore-some^) (list)]
|
||||||
|
|
||||||
|
;; definitions lifted from contracts should be ignored
|
||||||
|
[(define-values (lifted) expr)
|
||||||
|
#:when (contract-lifted-property #'expr)
|
||||||
|
(list)]
|
||||||
|
|
||||||
[(define-values (var ...) expr)
|
[(define-values (var ...) expr)
|
||||||
(define vars (syntax->list #'(var ...)))
|
(define vars (syntax->list #'(var ...)))
|
||||||
(syntax-parse vars
|
(syntax-parse vars
|
||||||
|
@ -211,6 +221,11 @@
|
||||||
;; module* is not expanded, so it doesn't have a `#%plain-module-begin`
|
;; module* is not expanded, so it doesn't have a `#%plain-module-begin`
|
||||||
[(module* n spec body ...) 'no-type]
|
[(module* n spec body ...) 'no-type]
|
||||||
|
|
||||||
|
;; definitions lifted from contracts should be ignored
|
||||||
|
[(define-values (lifted) expr)
|
||||||
|
#:when (contract-lifted-property #'expr)
|
||||||
|
'no-type]
|
||||||
|
|
||||||
;; definitions just need to typecheck their bodies
|
;; definitions just need to typecheck their bodies
|
||||||
[(define-values () expr)
|
[(define-values () expr)
|
||||||
(tc-expr/check #'expr (ret empty))
|
(tc-expr/check #'expr (ret empty))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user