Adding cstruct, which is like the struct signature form but with contracts.
svn: r13647 original commit: 340035bef7544d1bb868c98e5fb28a18a4214222
This commit is contained in:
commit
cf063bd01f
|
@ -1,5 +1,6 @@
|
|||
(module unit mzscheme
|
||||
(require-for-syntax mzlib/list
|
||||
scheme/pretty
|
||||
stxclass
|
||||
syntax/boundmap
|
||||
syntax/context
|
||||
|
@ -19,7 +20,7 @@
|
|||
"private/unit-runtime.ss"
|
||||
"private/unit-utils.ss")
|
||||
|
||||
(provide define-signature-form struct open
|
||||
(provide define-signature-form struct cstruct open
|
||||
define-signature provide-signature-elements
|
||||
only except rename import export prefix link tag init-depend extends contracted
|
||||
unit?
|
||||
|
@ -124,6 +125,90 @@
|
|||
(raise-stx-err "missing fields"))
|
||||
((_)
|
||||
(raise-stx-err "missing name and fields")))))
|
||||
|
||||
(define-signature-form (cstruct stx)
|
||||
(parameterize ((error-syntax stx))
|
||||
(syntax-case stx ()
|
||||
((_ name ([field ctc] ...) . omissions)
|
||||
(let ([omit-selectors #f]
|
||||
[omit-setters #f]
|
||||
[omit-constructor #f]
|
||||
[omit-type #f])
|
||||
(define (remove-ctor&type-info l)
|
||||
(define new-type
|
||||
(if omit-type
|
||||
#f
|
||||
(cadr l)))
|
||||
(define new-ctor
|
||||
(if omit-constructor
|
||||
#f
|
||||
(caddr l)))
|
||||
(cons (car l)
|
||||
(cons new-type
|
||||
(cons new-ctor
|
||||
(cdddr l)))))
|
||||
(define (add-contracts l)
|
||||
(let* ([pred (caddr l)]
|
||||
[ctor-ctc #`(-> ctc ... #,pred)]
|
||||
[pred-ctc #`(-> any/c boolean?)]
|
||||
[field-ctcs (apply append
|
||||
(map (λ (c)
|
||||
(append (if omit-selectors
|
||||
null
|
||||
(list #`(-> #,pred #,c)))
|
||||
(if omit-setters
|
||||
null
|
||||
(list #`(-> #,pred #,c void?)))))
|
||||
(syntax->list #'(ctc ...))))])
|
||||
(list* (car l)
|
||||
(list (cadr l) ctor-ctc)
|
||||
(list pred pred-ctc)
|
||||
(map list (cdddr l) field-ctcs))))
|
||||
(check-id #'name)
|
||||
(for-each check-id (syntax->list #'(field ...)))
|
||||
(for-each
|
||||
(lambda (omission)
|
||||
(cond
|
||||
((and (identifier? omission)
|
||||
(module-identifier=? omission #'-selectors))
|
||||
(set! omit-selectors #t))
|
||||
((and (identifier? omission)
|
||||
(module-identifier=? omission #'-setters))
|
||||
(set! omit-setters #t))
|
||||
((and (identifier? omission)
|
||||
(module-identifier=? omission #'-constructor))
|
||||
(set! omit-constructor #t))
|
||||
((and (identifier? omission)
|
||||
(module-identifier=? omission #'-type))
|
||||
(set! omit-type #t))
|
||||
(else
|
||||
(raise-stx-err
|
||||
"expected \"-selectors\" or \"-setters\" or \"-constructor\" or \"-type\""
|
||||
omission))))
|
||||
(checked-syntax->list #'omissions))
|
||||
(cons
|
||||
#`(define-syntaxes (name)
|
||||
#,(remove-ctor&type-info
|
||||
(build-struct-expand-info
|
||||
#'name (syntax->list #'(field ...))
|
||||
omit-selectors omit-setters
|
||||
#f '(#f) '(#f))))
|
||||
(let* ([res (add-contracts
|
||||
(build-struct-names #'name (syntax->list #'(field ...))
|
||||
omit-selectors omit-setters #f))]
|
||||
[cpairs (cons 'contracted (if omit-constructor (cddr res) (cdr res)))])
|
||||
(if omit-type
|
||||
(list cpairs)
|
||||
(list (car res) cpairs))))))
|
||||
((_ name (x . y) . omissions)
|
||||
;; Will fail
|
||||
(checked-syntax->list (stx-car (stx-cdr (stx-cdr stx)))))
|
||||
((_ name fields . omissions)
|
||||
(raise-stx-err "expected syntax matching (identifier ...)" #'fields))
|
||||
((_ name)
|
||||
(raise-stx-err "missing fields"))
|
||||
((_)
|
||||
(raise-stx-err "missing name and fields")))))
|
||||
|
||||
|
||||
;; build-val+macro-defs : sig -> (list syntax-object^3)
|
||||
|
|
Loading…
Reference in New Issue
Block a user