polish and extend reference

- mention key in inf-elem
- specify phase of bindings
- add type=? examples
This commit is contained in:
Stephen Chang 2016-09-30 12:09:37 -04:00
parent 577f47f46a
commit 383634e14f

View File

@ -1,6 +1,7 @@
#lang scribble/manual
@(require (for-label racket/base
@(require scribble/example racket/sandbox
(for-label racket/base
(except-in turnstile/turnstile ⊢))
"doc-utils.rkt" "common.rkt")
@ -8,10 +9,16 @@
@section{Typing Unicode Characters}
@(define the-eval
(parameterize ([sandbox-output 'string]
[sandbox-error-output 'string]
[sandbox-eval-limits #f])
(make-base-eval #:lang 'turnstile)))
@; insert link?
@; https://docs.racket-lang.org/drracket/Keyboard_Shortcuts.html
Turnstile utilizes unicode. Here are DrRacket keyboard shortcuts for the
relevant characters. Type the following (or any unique prefix of the following)
relevant characters. Type (any unique prefix of) the following
and then press Control-@litchar{\}.
@itemlist[
@ -43,7 +50,7 @@ and then press Control-@litchar{\}.
premise ...
--------
⇐-conclusion]
[expr-pattern ⇐ : type-pattern ≫
[expr-pattern ⇐ key type-pattern ≫
premise ...
--------
⇐-conclusion]]
@ -51,6 +58,7 @@ and then press Control-@litchar{\}.
[type-pattern (code:line @#,racket[syntax-parse] @#,tech:stx-pat)]
[expr-template (code:line @#,racket[quasisyntax] @#,tech:template)]
[type-template (code:line @#,racket[quasisyntax] @#,tech:template)]
[key identifier?]
[premise (code:line [⊢ inf ...] ooo ...)
(code:line [ctx ⊢ inf ...] ooo ...)
(code:line [ctx-elem ... ⊢ inf ...] ooo ...)
@ -65,11 +73,16 @@ and then press Control-@litchar{\}.
[ctx-elem (code:line [id ≫ id : type-template] ooo ...)]
[inf (code:line inf-elem ooo ...)]
[inf-elem [expr-template ≫ expr-pattern ⇒ type-pattern]
[expr-template ≫ expr-pattern ⇐ type-template]]
[expr-template ≫ expr-pattern ⇒ key type-pattern]
[expr-template ≫ expr-pattern (⇒ key type-pattern) ooo ...]
[expr-template ≫ expr-pattern ⇐ type-template]
[expr-template ≫ expr-pattern ⇐ key type-template]
[expr-template ≫ expr-pattern (⇐ key type-template) ooo ...]]
[type-relation (code:line [type-template τ⊑ type-template] ooo ...)
(code:line [type-template τ⊑ type-template #:for expr-template] ooo ...)]
[conclusion [⊢ expr-template ⇒ type-template]
[conclusion [⊢ expr-template ⇒ key type-template]
[⊢ [_ ≫ expr-template ⇒ type-template]]
[⊢ [_ ≫ expr-template (⇒ key type-template) ooo ...]]
[≻ expr-template]
[_ ≻ expr-template]]
[⇐-conclusion [⊢ expr-template]
@ -89,6 +102,8 @@ Type checking is computed as part of macro expansion and the resulting type is
and has type @racket[τ], where @racket[e] is the input and, @racket[e-] and
@racket[τ] outputs. Syntactically, @racket[e] is a syntax template position
and @racket[e-] @racket[τ] are syntax pattern positions.
A programmer may use the generalized form @racket[[⊢ e ≫ e- (⇒ key τ) ...]] to specify propagation of arbitrary values, associated with any number of keys. For example, a type and effect system may wish to additionally propagate source locations of allocations and mutations. When no key is specified, @litchar{:}, i.e., the "type" key, is used.
Dually, one may write @racket[[⊢ e ≫ e- ⇐ τ]] to check that @racket[e] has type
@racket[τ]. Here, both @racket[e] and @racket[τ] are inputs (templates) and only
@ -101,7 +116,7 @@ A @racket[define-typed-syntax] definition is automatically provided, either usin
@defform[(define-primop op-id : τ)]{
Attaches type @racket[τ] to identifier @racket[op-id], e.g.
@racket[(define-primop + : (→ Int Int))].
Automatically provides @racket[op-id].}
Automatically provides the new @racket[op-id].}
@defform[(define-syntax-category name-id)]{
Defines a new "category" of syntax by defining a series of forms and functions.
@ -110,13 +125,16 @@ Turnstile pre-declares @racket[(define-syntax-category type)], which in turn
Note: It's typically not necessary to
use any forms other than @racket[define-base-type] and
@racket[define-type-constructor] in conjunction with @racket[define-typed-syntax].
@racket[define-type-constructor] in conjunction with @racket[define-typed-syntax]. The other forms are considered "low-level" and are automatically used by @racket[define-typed-syntax].
@itemlist[
@item{@defform[(define-base-type base-type-name-id)]{
@item{@defform[(define-base-type base-type-name-id option ...)
#:grammar
([option (code:line #:no-provide)])]{
Defines a base type. A @racket[(define-base-type τ)] additionally defines:
@itemlist[@item{@racket[τ], an identifier macro representing type @racket[τ].}
@item{@racket[τ?], a predicate recognizing type @racket[τ].}
@item{@racket[~τ], a @tech:pat-expander recognizing type @racket[τ].}]}}
@item{@racket[~τ], a @tech:pat-expander recognizing type @racket[τ].}]
Automatically provides the defined type unless @racket[#:no-provide] is specified.}}
@item{@defform[(define-base-types base-type-name-id ...)]{Defines multiple base types.}}
@item{
@defform[(define-type-constructor name-id option ...)
@ -125,7 +143,8 @@ Turnstile pre-declares @racket[(define-syntax-category type)], which in turn
(code:line #:bvs op n)
(code:line #:arr tycon)
(code:line #:arg-variances expr)
(code:line #:extra-info stx)])]{
(code:line #:extra-info stx)
(code:line #:no-provide)])]{
Defines a type constructor. Defining a type constructor @racket[τ] defines:
@itemlist[@item{@racket[τ], a macro for constructing an instance of type
@racket[τ], with the specified arity.}
@ -137,29 +156,56 @@ Turnstile pre-declares @racket[(define-syntax-category type)], which in turn
The default arity is @racket[= 1].
Use the @racket[#:bvs] argument to define binding types, eg
@racket[(define-type-constructor ∀ #:bvs = 1 #:arity = 1)] defines a type with
@racket[(define-type-constructor ∀ #:arity = 1 #:bvs = 1)] defines a type with
shape @racket[(∀ (X) τ)], where @racket[τ] may reference @racket[X].
The @racket[#:extra-info] argument is useful for attaching additional metainformation
to types, for example to implement pattern matching.
Automatically provides the defined type, unless @racket[#:no-provide] is specified.
}}
@item{@defproc[(type=? [τ1 type?] [τ2 type?]) boolean?]{An equality predicate for types that computes
structural, @racket[free-identifier=?] equality.}}
@item{@defproc[(type=? [τ1 type?] [τ2 type?]) boolean?]{A phase 1 equality
predicate for types that computes structural, @racket[free-identifier=?]
equality, but includes alpha-equivalence.
@examples[#:eval the-eval
(define-base-type Int #:no-provide)
(define-base-type String #:no-provide)
(begin-for-syntax (displayln (type=? #'Int #'Int)))
(begin-for-syntax (displayln (type=? #'Int #'String)))
(define-type-constructor → #:arity > 0 #:no-provide)
(define-type-constructor ∀ #:arity = 1 #:bvs = 1 #:no-provide)
(begin-for-syntax
(displayln
(type=? ((current-type-eval) #'(∀ (X) X))
((current-type-eval) #'(∀ (Y) Y)))))
(begin-for-syntax
(displayln
(type=? ((current-type-eval) #'(∀ (X) (∀ (Y) (→ X Y))))
((current-type-eval) #'(∀ (Y) (∀ (X) (→ Y X)))))))
(begin-for-syntax
(displayln
(type=? ((current-type-eval) #'(∀ (Y) (∀ (X) (→ Y X))))
((current-type-eval) #'(∀ (X) (∀ (X) (→ X X)))))))
]
}}
@item{@defproc[(types=? [τs1 (listof type?)][τs2 (listof type?)]) boolean?]{
Checks that @racket[τs1] and @racket[τs2] are equivalent, pairwise. Thus,
A phase 1 predicate checking that @racket[τs1] and @racket[τs2] are equivalent, pairwise. Thus,
@racket[τs1] and @racket[τs2] must have the same length.}}
@item{@defproc[(same-types? [τs (listof type?)]) boolean?]{
A predicate for checking if a list of types are all the same.}}
A phase 1 predicate for checking if a list of types are all the same.}}
@item{@defparam[current-type=? binary-type-pred binary-type-pred]{
A parameter for computing type equality. Is initialized to @racket[type=?].}}
@item{@defidform[#%type]{A "kind" used to validate types.}}
@item{@defproc[(#%type? [x Any]) boolean?]{Recognizes @racket[#%type].}}
@item{@defproc[(type? [x Any]) boolean?]{A predicate used to validate types.
A phase 1 parameter for computing type equality. Is initialized to @racket[type=?].}}
@item{@defidform[#%type]{The default "kind" used to validate types.}}
@item{@defproc[(#%type? [x Any]) boolean?]{Phase 1 predicate recognizing @racket[#%type].}}
@item{@defproc[(type? [x Any]) boolean?]{A phase 1 predicate used to validate types.
Checks that @racket[x] is a syntax object and has syntax propety @racket[#%type].}}
@item{@defparam[current-type? type-pred type-pred]{A parameter, initialized to @racket[type?],
@item{@defparam[current-type? type-pred type-pred]{A phase 1 parameter, initialized to @racket[type?],
used to validate types. Useful when reusing type rules in different languages.}}
@item{@defproc[(mk-type [stx syntax?]) type?]{
Marks a syntax object as a type by attaching @racket[#%type].
Phase 1 function that marks a syntax object as a type by attaching @racket[#%type].
Useful for defining your own type with arbitrary syntax that does not fit with
@racket[define-base-type] or @racket[define-type-constructor].}}
@item{@defthing[type stx-class]{A syntax class that calls @racket[current-type?]
@ -196,35 +242,38 @@ This section describes lower-level functions. It's usually not necessary to call
since @racket[define-typed-syntax] and other forms already do so.
@defparam[current-type-eval type-eval type-eval]{
Parameter for controlling "type evaluation". A @racket[type-eval] function consumes and
produces syntax and defaults to @racket[syntax-local-expand-expression],
extended to store extra surface syntax information used for error reporting.
A phase 1 parameter for controlling "type evaluation". A @racket[type-eval] function consumes and
produces syntax.
It defaults to full expansion, i.e., @racket[(lambda (stx) (local-expand stx 'expression null))];
the default also stores extra surface syntax information used for error reporting.
This is called before a type is attached to a syntax object,
i.e., by @racket[assign-type].}
@defparam[current-typecheck-relation type-pred type-pred]{
Parameter for controlling type checking. A @racket[type-pred] function consumes
two types and returns true if they "type check". Not necessarily a symmetric relation.
A phase 1 parameter for controlling type checking. A @racket[type-pred] function consumes
two types and returns true if they "type check". It defaults to @racket[type=?] though it does not have to be a symmetric relation.
Useful for reusing rules that differ only in the type check operation, e.g.,
equality vs subtyping.}
@defproc[(typecheck? [τ1 type?] [τ2 type?]) boolean?]{A function that calls
@defproc[(typecheck? [τ1 type?] [τ2 type?]) boolean?]{A phase 1 function that calls
@racket[current-typecheck-relation].}
@defproc[(typechecks? [τs1 (list/c type?)] [τs2 (list/c type?)]) boolean?]{
Maps @racket[typecheck?] over lists of types, pairwise. @racket[τs1] and @racket[τs2]
@defproc[(typechecks? [τs1 (or/c (list/c type?) (stx-list/c type?))]
[τs2 (or/c (list/c type?) (stx-list/c type?))]) boolean?]{
Phase 1 function mapping @racket[typecheck?] over lists of types, pairwise. @racket[τs1] and @racket[τs2]
must have the same length.}
@defproc[(assign-type [e syntax?] [τ syntax?]) syntax?]{
Calls @racket[current-type-eval] on @racket[τ] and attaches it to @racket[e]}
Phase 1 function that calls @racket[current-type-eval] on @racket[τ] and attaches it to @racket[e]}
@defproc[(typeof [e expr-stx]) type-stx]{
Returns type of @racket[e].}
Phase 1 function returning type of @racket[e].}
@defproc[(infer [es (listof expr-stx)]
[#:ctx ctx (listof bindings) null]
[#:tvctx tvctx (listof tyvar-bindings) null]) (list tvs xs es τs)]{
Expands a list of expressions, in the given contexts and computes their types.
Phase 1 function expanding a list of expressions, in the given contexts and computes their types.
Returns the expanded expressions, their types, and expanded identifiers from the
contexts, e.g. @racket[(infer (list #'(+ x 1)) #:ctx ([x : Int]))].}
@ -232,20 +281,22 @@ Expands a list of expressions, in the given contexts and computes their types.
[x id]
[e expr-stx]
[cmp (-> identifier? identifier? boolean?) bound-identifier=?]) expr-stx]{
Replaces occurrences of @racket[x], as determined by @racket[cmp], with
Phase 1 function that replaces occurrences of @racket[x], as determined by @racket[cmp], with
@racket[τ] in @racket[e].}
@defproc[(substs [τs (listof type-stx)]
[xs (listof id)]
[e expr-stx]
[cmp (-> identifier? identifier? boolean?) bound-identifier=?]) expr-stx]{
Folds @racket[subst] over the given @racket[τs] and @racket[xs].}
Phase 1 function folding @racket[subst] over the given @racket[τs] and @racket[xs].}
@defform[(type-error #:src srx-stx #:msg msg args ...)]{
Throws a type error using the specified information. @racket[msg] is a format string that references @racket[args].}
Phase 1 form that throws a type error using the specified information. @racket[msg] is a format string that references @racket[args].}
@section{Miscellaneous Syntax Object Functions}
These are all phase 1 functions.
@defproc[(stx-length [stx syntax?]) Nat]{Analogous to @racket[length].}
@defproc[(stx-length=? [stx1 syntax?] [stx2 syntax?]) boolean?]{
Returns true if two syntax objects are of equal length.}