Added a #:fallbacks option to define-generics.
The #:fallbacks option specifies a set of method definitions. Each definition is used for any value that does not support the specific method. Like allows define/generic and absent method definitions. If neither a specific implementation or the #:fallbacks clause defines a given method, the normal runtime error is raised. The #:defined-table option reports whether a value's specific implementation supports a method; the presence of a #:fallbacks implementation for a method does not change this result.
This commit is contained in:
parent
fc4c8dd53e
commit
c6532131a0
|
@ -15,9 +15,13 @@
|
|||
;; i.e., exporting prop:ordered-dict as opposed to using a
|
||||
;; generated hidden property.
|
||||
(define-primitive-generics
|
||||
(ordered-dict gen:ordered-dict prop:ordered-dict ordered-methods ordered-dict?
|
||||
#:defined-table dict-def-table
|
||||
#:defaults ())
|
||||
(ordered-dict gen:ordered-dict
|
||||
prop:ordered-dict
|
||||
ordered-methods
|
||||
ordered-dict?
|
||||
dict-def-table)
|
||||
#:defaults ()
|
||||
#:fallbacks ()
|
||||
(dict-iterate-least ordered-dict)
|
||||
(dict-iterate-greatest ordered-dict)
|
||||
(dict-iterate-least/>? ordered-dict key)
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
(local-require racket/private/generic)
|
||||
|
||||
(define-primitive-generics
|
||||
(foo gen:foo prop:foo foo-methods foo?
|
||||
#:defined-table dummy
|
||||
#:defaults ([number? (define (meth foo #:kw kw) kw)]))
|
||||
(foo gen:foo prop:foo foo-methods foo? dummy)
|
||||
#:defaults ([number? (define (meth foo #:kw kw) kw)])
|
||||
#:fallbacks ()
|
||||
(meth foo #:kw kw))
|
||||
|
||||
(check-equal? (meth 3 #:kw 5) 5))
|
||||
|
|
|
@ -15,22 +15,28 @@
|
|||
|
||||
(begin-for-syntax
|
||||
|
||||
(define (parse stx methods table defaults)
|
||||
(define (parse stx methods table defaults fallbacks)
|
||||
(syntax-case stx ()
|
||||
[(#:defined-table name . args)
|
||||
(identifier? #'name)
|
||||
(if table
|
||||
(wrong-syntax (stx-car stx)
|
||||
"duplicate #:defined-table specification")
|
||||
(parse #'args methods #'name defaults))]
|
||||
(parse #'args methods #'name defaults fallbacks))]
|
||||
[(#:defined-table . other)
|
||||
(wrong-syntax (stx-car stx) "invalid #:defined-table specification")]
|
||||
[(#:defaults ([pred defn ...] ...) . args)
|
||||
(if defaults
|
||||
(wrong-syntax (stx-car stx) "duplicate #:defaults specification")
|
||||
(parse #'args methods table #'([pred defn ...] ...)))]
|
||||
(parse #'args methods table #'([pred defn ...] ...) fallbacks))]
|
||||
[(#:defaults . other)
|
||||
(wrong-syntax (stx-car stx) "invalid #:defaults specification")]
|
||||
[(#:fallbacks [fallback ...] . args)
|
||||
(if fallbacks
|
||||
(wrong-syntax (stx-car stx) "duplicate #:fallbacks specification")
|
||||
(parse #'args methods table defaults #'[fallback ...]))]
|
||||
[(#:fallbacks . other)
|
||||
(wrong-syntax (stx-car stx) "invalid #:fallbacks specification")]
|
||||
[(kw . args)
|
||||
(keyword? (syntax-e #'kw))
|
||||
(wrong-syntax #'kw "invalid keyword argument")]
|
||||
|
@ -40,13 +46,14 @@
|
|||
(let loop ([methods (list (stx-car stx))] [stx #'args])
|
||||
(syntax-case stx ()
|
||||
[((_ . _) . args) (loop (cons (stx-car stx) methods) #'args)]
|
||||
[_ (parse stx (reverse methods) table defaults)])))]
|
||||
[_ (parse stx (reverse methods) table defaults fallbacks)])))]
|
||||
[(other . args)
|
||||
(wrong-syntax #'other
|
||||
"expected a method identifier with formal arguments")]
|
||||
[() (values (or methods '())
|
||||
(or table (generate-temporary 'table))
|
||||
(or defaults '()))]
|
||||
(or defaults '())
|
||||
(or fallbacks '()))]
|
||||
[other
|
||||
(wrong-syntax #'other
|
||||
"expected a list of arguments with no dotted tail")])))
|
||||
|
@ -57,9 +64,10 @@
|
|||
(parameterize ([current-syntax-context stx])
|
||||
(unless (identifier? #'name)
|
||||
(wrong-syntax #'name "expected an identifier"))
|
||||
(define-values (methods table defaults)
|
||||
(parse #'rest #f #f #f))
|
||||
(define-values (methods table defaults fallbacks)
|
||||
(parse #'rest #f #f #f #f))
|
||||
(define/with-syntax [default ...] defaults)
|
||||
(define/with-syntax [fallback ...] fallbacks)
|
||||
(define/with-syntax [method ...] methods)
|
||||
(define/with-syntax [method-name ...] (map stx-car methods))
|
||||
(define/with-syntax [method-index ...]
|
||||
|
@ -75,9 +83,9 @@
|
|||
#'(begin
|
||||
(define-primitive-generics/derived
|
||||
original
|
||||
(name gen-name prop-name get-name pred-name
|
||||
#:defined-table table-name
|
||||
#:defaults [default ...])
|
||||
(name gen-name prop-name get-name pred-name table-name)
|
||||
#:defaults [default ...]
|
||||
#:fallbacks [fallback ...]
|
||||
method ...)
|
||||
(define-generics-contract name pred-name get-name
|
||||
[method-name method-index]
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
(require racket/private/generic ; to avoid circular dependencies
|
||||
(for-syntax racket/base))
|
||||
|
||||
(define-primitive-generics (dict gen:dict prop:dict dict-methods dict?
|
||||
#:defined-table dict-def-table
|
||||
#:defaults ())
|
||||
(define-primitive-generics
|
||||
(dict gen:dict prop:dict dict-methods dict? dict-def-table)
|
||||
#:defaults ()
|
||||
#:fallbacks ()
|
||||
(dict-ref dict key [default])
|
||||
(dict-set! dict key val)
|
||||
(dict-set dict key val)
|
||||
|
|
|
@ -29,9 +29,13 @@
|
|||
(define-syntax (define-primitive-generics/derived stx)
|
||||
(syntax-case stx ()
|
||||
[(_ original
|
||||
(self-name generic-name property-name accessor-name predicate-name
|
||||
#:defined-table supported-name
|
||||
#:defaults ([default-pred default-defn ...] ...))
|
||||
(self-name generic-name
|
||||
property-name
|
||||
accessor-name
|
||||
predicate-name
|
||||
supported-name)
|
||||
#:defaults ([default-pred default-defn ...] ...)
|
||||
#:fallbacks [fallback-defn ...]
|
||||
[method-name . method-signature]
|
||||
...)
|
||||
(parameterize ([current-syntax-context #'original])
|
||||
|
@ -53,6 +57,8 @@
|
|||
(generate-temporaries #'(default-pred ...)))
|
||||
(define/with-syntax (default-impl-name ...)
|
||||
(generate-temporaries #'(default-pred ...)))
|
||||
(define/with-syntax fallback-name
|
||||
(generate-temporary #'self-name))
|
||||
#'(begin
|
||||
(define-syntax generic-name
|
||||
(make-generic-info (quote-syntax property-name)
|
||||
|
@ -85,6 +91,8 @@
|
|||
(define default-impl-name
|
||||
(generic-method-table generic-name default-defn ...))
|
||||
...
|
||||
(define fallback-name
|
||||
(generic-method-table generic-name fallback-defn ...))
|
||||
(define-generic-support supported-name
|
||||
self-name
|
||||
[method-name ...]
|
||||
|
@ -94,7 +102,8 @@
|
|||
method-name
|
||||
method-signature
|
||||
self-name
|
||||
(vector-ref (table-name self-name 'method-name) 'method-index)
|
||||
(or (vector-ref (table-name self-name 'method-name) 'method-index)
|
||||
(vector-ref fallback-name 'method-index))
|
||||
original)
|
||||
...))]))
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user