Add vector signatures, and `vector-of' to the HtDP signature syntax.

This commit is contained in:
Mike Sperber 2010-12-19 11:20:51 +01:00
parent 3751452530
commit fa854f62fc
3 changed files with 91 additions and 2 deletions

View File

@ -25,6 +25,7 @@
make-predicate-signature make-predicate-signature
make-type-variable-signature make-type-variable-signature
make-list-signature make-list-signature
make-vector-signature
make-mixed-signature make-mixed-signature
make-combined-signature make-combined-signature
make-case-signature make-case-signature
@ -177,6 +178,52 @@
(apply proc arbitraries) (apply proc arbitraries)
#f))) #f)))
(define vectors-table (make-weak-hasheq)) ; #### ought to do ephemerons, too
(define (make-vector-signature name arg-signature syntax)
(make-signature
name
(lambda (self obj)
(define (check old-sigs)
(let ((old-sigs (cons arg-signature old-sigs)))
(hash-set! vectors-table obj old-sigs)
(let* ((orig (vector->list obj))
(els (map (lambda (x)
(apply-signature arg-signature x))
orig)))
(if (andmap eq? orig els)
obj
(let ((new (list->vector els)))
(hash-set! vectors-table obj new old-sigs)
obj)))))
(cond
((not (vector? obj))
(signature-violation obj self #f #f)
obj)
((hash-ref vectors-table obj #f)
=> (lambda (old-sigs)
(if (ormap (lambda (old-sig)
(signature<=? old-sig arg-signature))
old-sigs)
obj
(check old-sigs))))
(else
(check '()))))
syntax
#:arbitrary-promise
(delay
(lift->arbitrary arbitrary-vector arg-signature))
#:info-promise
(delay (make-vector-info arg-signature))
#:=?-proc
(lambda (this-info other-info)
(and (vector-info? other-info)
(signature=? arg-signature (vector-info-arg-signature other-info))))))
(define-struct vector-info (arg-signature) #:transparent)
(define (make-mixed-signature name alternative-signatures syntax) (define (make-mixed-signature name alternative-signatures syntax)
(letrec ((alternative-signatures-promise (letrec ((alternative-signatures-promise
(delay (delay

View File

@ -3,7 +3,7 @@
(provide : (provide :
signature signature/arbitrary signature signature/arbitrary
define/signature define-values/signature define/signature define-values/signature
-> mixed one-of predicate combined property list-of) -> mixed one-of predicate combined property list-of vector-of)
(require deinprogramm/signature/signature (require deinprogramm/signature/signature
deinprogramm/signature/signature-english deinprogramm/signature/signature-english
@ -20,7 +20,7 @@
(define-for-syntax (parse-signature name stx) (define-for-syntax (parse-signature name stx)
(syntax-case* stx (syntax-case* stx
(mixed one-of predicate list-of -> combined property reference at signature) (mixed one-of predicate list-of vector-of -> combined property reference at signature)
module-or-top-identifier=? module-or-top-identifier=?
((mixed ?signature ...) ((mixed ?signature ...)
(with-syntax ((?stx (phase-lift stx)) (with-syntax ((?stx (phase-lift stx))
@ -63,6 +63,15 @@
(raise-syntax-error #f (raise-syntax-error #f
"list-of signature accepts only a single operand" "list-of signature accepts only a single operand"
(syntax ?signature1))) (syntax ?signature1)))
((vector-of ?signature)
(with-syntax ((?stx (phase-lift stx))
(?name name)
(?signature-expr (parse-signature #f #'?signature)))
#'(make-vector-signature '?name ?signature-expr ?stx)))
((vector-of ?signature1 ?rest ...)
(raise-syntax-error #f
"vector-of signature accepts only a single operand"
(syntax ?signature1)))
((?arg-signature ... -> ?return-signature) ((?arg-signature ... -> ?return-signature)
(with-syntax ((?stx (phase-lift stx)) (with-syntax ((?stx (phase-lift stx))
(?name name) (?name name)
@ -249,3 +258,4 @@
(define-syntax combined within-signature-syntax-transformer) (define-syntax combined within-signature-syntax-transformer)
(define-syntax property within-signature-syntax-transformer) (define-syntax property within-signature-syntax-transformer)
(define-syntax list-of within-signature-syntax-transformer) (define-syntax list-of within-signature-syntax-transformer)
(define-syntax vector-of within-signature-syntax-transformer)

View File

@ -86,6 +86,38 @@
(check-equal? (say-no (proc no2)) 'no)) (check-equal? (say-no (proc no2)) 'no))
) )
(test-case
"vector"
(define integer-vector (make-vector-signature 'integer-list integer #f))
(check-equal? (say-no (apply-signature integer-vector '#(1 2 3)))
'#(1 2 3))
(check-equal? (say-no (apply-signature integer-vector '#f))
'no)
(check-eq? (failed-signature (apply-signature integer-vector '#(1 #f 3)))
integer))
(test-case
"vector/cached"
(let ((count 0))
(define counting-integer
(make-predicate-signature 'counting-integer
(lambda (obj)
(set! count (+ 1 count))
(integer? obj))
'integer-marker))
(define integer-vector (make-vector-signature 'integer-list counting-integer #f))
(define v1 '#(1 2 3))
(check-eq? (say-no (apply-signature integer-vector v1))
v1)
(check-equal? count 3)
(check-eq? (say-no (apply-signature integer-vector v1))
v1)
(check-equal? count 3)))
(test-case (test-case
"mixed" "mixed"
(define int-or-bool (make-mixed-signature 'int-or-bool (define int-or-bool (make-mixed-signature 'int-or-bool