Added contract→type
This commit is contained in:
parent
41f7dc0f50
commit
c89285f39b
44
contracts-to-types.rkt
Normal file
44
contracts-to-types.rkt
Normal file
|
@ -0,0 +1,44 @@
|
|||
#lang type-expander
|
||||
|
||||
(provide :contract→type
|
||||
(rename-out [c→t contract→type]
|
||||
[c→t contract->type]
|
||||
[:contract→type :contract->type]))
|
||||
(require racket/contract/base
|
||||
(for-syntax syntax/parse
|
||||
type-expander/expander))
|
||||
|
||||
(define-type-expander c→t
|
||||
(syntax-parser
|
||||
[(_ ({~literal or/c} alt ...)) #'(U (c→t alt) ...)]
|
||||
[(_ ({~literal and/c} alt ...)) #'(∩ (c→t alt) ...)]
|
||||
[(_ ({~literal listof} c)) #'(Listof (c→t c))]
|
||||
[(_ ({~literal list/c} c ...)) #'(List (c→t c) ...)]
|
||||
[(_ ({~literal *list/c} prefix suffix ...)) #'(Rec R (U (Pairof prefix R)
|
||||
(List suffix ...)))]
|
||||
[(_ ({~literal vectorof} c)) #'(Vectorof (c→t c))]
|
||||
[(_ ({~literal vector/c} c ...)) #'(Vector (c→t c) ...)]
|
||||
[(_ ({~literal cons/c} a d)) #'(Pairof (c→t a) (c→t d))]
|
||||
[(_ {~literal integer?}) #'Integer]
|
||||
[(_ {~literal string?}) #'String]
|
||||
[(_ {~literal symbol?}) #'Symbol]
|
||||
[(_ {~literal exact-nonnegative-integer?}) #'Exact-Nonnegative-Integer]
|
||||
[(_ {~literal exact-positive-integer?}) #'Exact-Positive-Integer]
|
||||
[(_ {~and τ ({~literal quote} _)}) #'τ]
|
||||
[(_ {~and τ {~or :number :str :id}}) #''τ]
|
||||
[(_ {~and τ ({~literal quasiquote} _)}) #'τ]
|
||||
[(_ ({~literal unquote} τ)) #'τ]
|
||||
[(_ c) (raise-syntax-error
|
||||
'contract→type
|
||||
(string-append
|
||||
"I cannot convert this contract to a type automatically."
|
||||
" Please fill in an issue at"
|
||||
" https://github.com/jsmaniac/type-expander/issues if the translation"
|
||||
" can easily be done automatically, or do the translation manually "
|
||||
" otherwise. "
|
||||
(format "~a" (syntax->datum #'c)))
|
||||
#'c)]))
|
||||
|
||||
(define-syntax (:contract→type stx)
|
||||
(syntax-case stx ()
|
||||
[(_ c) #`(writeln '#,(expand-type #`(c→t c)))]))
|
37
scribblings/contracts-to-types.scrbl
Normal file
37
scribblings/contracts-to-types.scrbl
Normal file
|
@ -0,0 +1,37 @@
|
|||
#lang scribble/manual
|
||||
|
||||
@require[(for-label racket/contract/base)
|
||||
scribble/example]
|
||||
@title{Using contract syntax to specify types}
|
||||
|
||||
@defmodule[type-expander/contracts-to-types]
|
||||
|
||||
@defform*[{(contract→type contract)
|
||||
(contract->type contract)}]{
|
||||
|
||||
This is a simple type expander which translates common contracts to types.
|
||||
Note that it only supports a limited number of contract constructors. The
|
||||
following are supported: @racket[or/c], @racket[and/c] (the translation may
|
||||
produce a type too complex for Typed/Racket to understand properly, though),
|
||||
@racket[listof], @racket[list/c], @racket[*list/c], @racket[vectorof],
|
||||
@racket[vector/c], @racket[cons/c], @racket[integer?], @racket[string?],
|
||||
@racket[symbol?], @racket[exact-nonnegative-integer?],
|
||||
@racket[exact-positive-integer?], @racket['quoted-datum],
|
||||
@racket[`quasiquoted-datum-with-unquoted-types].
|
||||
|
||||
Furthermore, using @racket[,_τ] anywhere outside of a quoted datum will leave
|
||||
the type @racket[_τ] unchaged, allowing the user to manually convert to types
|
||||
only the parts which cannot be converted automatically.}
|
||||
|
||||
@defform*[{(:contract→type contract)
|
||||
(:contract->type contract)}]{
|
||||
|
||||
Prints a representation of the contract translated as a type. It is then
|
||||
possible to copy-paste that result into the code.
|
||||
|
||||
@examples[
|
||||
(require type-expander/lang
|
||||
racket/contract/base
|
||||
type-expander/contracts-to-types)
|
||||
(:contract→type (list/c 1 2 "str" (or/c integer? string?)))]
|
||||
}
|
|
@ -842,3 +842,5 @@ arguments to a type expander.
|
|||
define-struct/exec:]
|
||||
|
||||
@include-section{deprecated-colon.scrbl}
|
||||
|
||||
@include-section{contracts-to-types.scrbl}
|
Loading…
Reference in New Issue
Block a user