(module datatype mzscheme
(require (lib "contract.ss"))
(require (lib "struct.ss"))
(require-for-syntax "private/datatype-registry.ss")
(require-for-syntax "private/datatype-registry-data.ss")
(define-syntax (define-datatype stx)
(syntax-case stx ()
[(_ (type (prop ...)) [variant (field ...) extra ...] ...)
(with-syntax ([build-static-info (parse-datatype #'(type [variant (field ...)] ...))])
#'(begin
(begin-for-syntax (register-datatype! #'type build-static-info))
(define-struct/properties type () (prop ...))
(define-variant type variant (field ...) extra ...)
...))]
[(_ type [variant (field ...) extra ...] ...)
(with-syntax ([build-static-info (parse-datatype #'(type [variant (field ...)] ...))])
#'(begin
(begin-for-syntax (register-datatype! #'type build-static-info))
(define-struct type ())
(define-variant type variant (field ...) extra ...)
...))]))
(define-syntax define-variant
(syntax-rules ()
[(_ type variant (field ...))
(define-variant type variant (field ...) ())]
[(_ type variant (field ...) ([prop prop-val] ...))
(define-struct/properties (variant type) (field ...) ([prop prop-val] ...))]))
(define-syntax (provide-datatype stx)
(syntax-case stx ()
[(_ type)
(let ([static-info (lookup-datatype #'type)])
(with-syntax ([(type [variant (arg ...)] ...) (unparse-datatype static-info)]
[predicate (list-ref (syntax-local-value #'type) 2)])
#'(begin
(provide predicate)
(provide (struct variant (arg ...)))
...)))]))
(define-syntax (provide-datatype/contract stx)
(syntax-case stx ()
[(_ type [variant (contract ...)] ...)
(let ([static-info (lookup-datatype #'type)])
(with-syntax ([(type [variant (arg ...)] ...) (unparse-datatype static-info)]
[predicate (list-ref (syntax-local-value #'type) 2)])
#'(begin
(provide predicate)
(provide/contract (struct (variant type) ([arg contract] ...)))
...)))]))
(provide define-datatype provide-datatype provide-datatype/contract))