;; ============================================================================= ;; ;; datatype.ss - by Dave Herman ;; version 4, 2005-2-18 ;; ;; An implementation of algebraic datatypes that work with the contract system, ;; somewhat similar to the define-datatype construct from EoPL. ;; ;; ============================================================================= (module datatype mzscheme (require (lib "contract.ss")) (require-for-syntax (lib "boundmap.ss" "syntax")) ;; The global table of defined datatypes. (define-for-syntax datatypes (make-module-identifier-mapping)) (define-syntax (define-datatype stx) (syntax-case stx () [(_ (type ([prop prop-val] ...)) [variant (field ...) [(_ type [variant (field ...)] ...) (let ([datatype-info (list #'type (syntax->list #'([variant (field ...)] ...)))]) (module-identifier-mapping-put! datatypes #'type datatype-info) #'(begin (define-struct type ()) (define-struct (variant type) (field ...)) ...))])) (define-syntax (provide-datatype stx) (syntax-case stx () [(_ type) (let ([static-info (module-identifier-mapping-get datatypes #'type)] [predicate-id (list-ref (syntax-local-value #'type) 2)]) (with-syntax ([([variant (arg ...)] ...) (cadr static-info)]) #`(begin (provide #,predicate-id) (provide (struct variant (arg ...))) ...)))])) (define-syntax (provide-datatype/contract stx) (syntax-case stx () [(_ type [variant (contract ...)] ...) (let ([static-info (module-identifier-mapping-get datatypes #'type)] [predicate-id (list-ref (syntax-local-value #'type) 2)]) (with-syntax ([([variant (arg ...)] ...) (cadr static-info)]) #`(begin (provide #,predicate-id) (provide/contract (struct (variant type) ([arg contract] ...))) ...)))])) (provide define-datatype provide-datatype provide-datatype/contract))