Changes to define-generics: added #:defined-predicate; improved generated code.
The #:defined-predicate option is like #:defined-table, but it defines a two-argument predicate that only processes the requested method name and doesn't allocate a hash table each time it is called. Method implementations provided via #:fallbacks, #:defaults, and #:fast-defaults are now called directly by method procedures rather than stored in a vector and extracted by index. This should hopefully improve inlining for methods.
This commit is contained in:
parent
1f267d479c
commit
d9890b843a
|
@ -19,7 +19,7 @@
|
||||||
prop:ordered-dict
|
prop:ordered-dict
|
||||||
ordered-methods
|
ordered-methods
|
||||||
ordered-dict?
|
ordered-dict?
|
||||||
dict-def-table)
|
ordered-dict-supports?)
|
||||||
#:fast-defaults ()
|
#:fast-defaults ()
|
||||||
#:defaults ()
|
#:defaults ()
|
||||||
#:fallbacks ()
|
#:fallbacks ()
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
(require racket/generic)
|
(require racket/generic)
|
||||||
|
|
||||||
(define-generics numeric
|
(define-generics numeric
|
||||||
#:defined-table numeric-support
|
#:defined-predicate numeric-supports?
|
||||||
(decrement numeric)
|
(decrement numeric)
|
||||||
(is-zero? numeric)
|
(is-zero? numeric)
|
||||||
(is-even? numeric)
|
(is-even? numeric)
|
||||||
|
@ -19,19 +19,16 @@
|
||||||
|
|
||||||
(define (is-even?-fallback x)
|
(define (is-even?-fallback x)
|
||||||
(cond
|
(cond
|
||||||
[(supports? x 'is-odd?) (not (is-odd? x))]
|
[(numeric-supports? x 'is-odd?) (not (is-odd? x))]
|
||||||
[(is-zero? x) #true]
|
[(is-zero? x) #true]
|
||||||
[else (is-odd? (decrement x))]))
|
[else (is-odd? (decrement x))]))
|
||||||
|
|
||||||
(define (is-odd?-fallback x)
|
(define (is-odd?-fallback x)
|
||||||
(cond
|
(cond
|
||||||
[(supports? x 'is-even?) (not (is-even? x))]
|
[(numeric-supports? x 'is-even?) (not (is-even? x))]
|
||||||
[(is-zero? x) #false]
|
[(is-zero? x) #false]
|
||||||
[else (is-even? (decrement x))]))
|
[else (is-even? (decrement x))]))
|
||||||
|
|
||||||
(define (supports? x sym)
|
|
||||||
(hash-ref (numeric-support x) sym #f))
|
|
||||||
|
|
||||||
(struct peano-zero []
|
(struct peano-zero []
|
||||||
#:transparent
|
#:transparent
|
||||||
#:methods gen:numeric
|
#:methods gen:numeric
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
(local-require racket/private/generic)
|
(local-require racket/private/generic)
|
||||||
|
|
||||||
(define-primitive-generics
|
(define-primitive-generics
|
||||||
(foo gen:foo prop:foo foo-methods foo? dummy)
|
(foo gen:foo prop:foo foo-methods foo? foo-supports?)
|
||||||
#:fast-defaults ([number? (define (meth foo #:kw kw) kw)])
|
#:fast-defaults ([number? (define (meth foo #:kw kw) kw)])
|
||||||
#:defaults ()
|
#:defaults ()
|
||||||
#:fallbacks ()
|
#:fallbacks ()
|
||||||
|
|
|
@ -17,6 +17,14 @@
|
||||||
|
|
||||||
(define (parse stx [options (hasheq)])
|
(define (parse stx [options (hasheq)])
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
|
[(#:defined-predicate name . args)
|
||||||
|
(identifier? #'name)
|
||||||
|
(if (hash-ref options 'support #f)
|
||||||
|
(wrong-syntax (stx-car stx)
|
||||||
|
"duplicate #:defined-predicate specification")
|
||||||
|
(parse #'args (hash-set options 'support #'name)))]
|
||||||
|
[(#:defined-predicate . other)
|
||||||
|
(wrong-syntax (stx-car stx) "invalid #:defined-predicate specification")]
|
||||||
[(#:defined-table name . args)
|
[(#:defined-table name . args)
|
||||||
(identifier? #'name)
|
(identifier? #'name)
|
||||||
(if (hash-ref options 'table #f)
|
(if (hash-ref options 'table #f)
|
||||||
|
@ -69,7 +77,8 @@
|
||||||
(wrong-syntax #'other
|
(wrong-syntax #'other
|
||||||
"expected a method identifier with formal arguments")]
|
"expected a method identifier with formal arguments")]
|
||||||
[() (values (hash-ref options 'methods '())
|
[() (values (hash-ref options 'methods '())
|
||||||
(hash-ref options 'table generate-temporary)
|
(hash-ref options 'support generate-temporary)
|
||||||
|
(hash-ref options 'table #f)
|
||||||
(hash-ref options 'fast-defaults '())
|
(hash-ref options 'fast-defaults '())
|
||||||
(hash-ref options 'defaults '())
|
(hash-ref options 'defaults '())
|
||||||
(hash-ref options 'fallbacks '())
|
(hash-ref options 'fallbacks '())
|
||||||
|
@ -84,9 +93,9 @@
|
||||||
(parameterize ([current-syntax-context stx])
|
(parameterize ([current-syntax-context stx])
|
||||||
(unless (identifier? #'name)
|
(unless (identifier? #'name)
|
||||||
(wrong-syntax #'name "expected an identifier"))
|
(wrong-syntax #'name "expected an identifier"))
|
||||||
(define-values (methods table fast-defaults defaults fallbacks derived)
|
(define-values (methods support table fasts defaults fallbacks derived)
|
||||||
(parse #'rest))
|
(parse #'rest))
|
||||||
(define/with-syntax [fast-default ...] fast-defaults)
|
(define/with-syntax [fast-default ...] fasts)
|
||||||
(define/with-syntax [default ...] defaults)
|
(define/with-syntax [default ...] defaults)
|
||||||
(define/with-syntax [fallback ...] fallbacks)
|
(define/with-syntax [fallback ...] fallbacks)
|
||||||
(define/with-syntax [derive ...] derived)
|
(define/with-syntax [derive ...] derived)
|
||||||
|
@ -100,17 +109,25 @@
|
||||||
(define/with-syntax gen-name (format-id #'name "gen:~a" #'name))
|
(define/with-syntax gen-name (format-id #'name "gen:~a" #'name))
|
||||||
(define/with-syntax prop-name (generate-temporary #'name))
|
(define/with-syntax prop-name (generate-temporary #'name))
|
||||||
(define/with-syntax get-name (generate-temporary #'name))
|
(define/with-syntax get-name (generate-temporary #'name))
|
||||||
(define/with-syntax table-name table)
|
(define/with-syntax support-name support)
|
||||||
(define/with-syntax original stx)
|
(define/with-syntax original stx)
|
||||||
|
(define/with-syntax table-defn
|
||||||
|
(if table
|
||||||
|
(with-syntax ([table-name table])
|
||||||
|
#'(define (table-name name)
|
||||||
|
(for/hasheq ([sym (in-list '(method ...))])
|
||||||
|
(values sym (support-name name sym)))))
|
||||||
|
#'(begin)))
|
||||||
#'(begin
|
#'(begin
|
||||||
(define-primitive-generics/derived
|
(define-primitive-generics/derived
|
||||||
original
|
original
|
||||||
(name gen-name prop-name get-name pred-name table-name)
|
(name gen-name prop-name get-name pred-name support-name)
|
||||||
#:fast-defaults [fast-default ...]
|
#:fast-defaults [fast-default ...]
|
||||||
#:defaults [default ...]
|
#:defaults [default ...]
|
||||||
#:fallbacks [fallback ...]
|
#:fallbacks [fallback ...]
|
||||||
#:derive-properties [derive ...]
|
#:derive-properties [derive ...]
|
||||||
method ...)
|
method ...)
|
||||||
|
table-defn
|
||||||
(define-generics-contract name pred-name get-name
|
(define-generics-contract name pred-name get-name
|
||||||
[method-name method-index]
|
[method-name method-index]
|
||||||
...)))]))
|
...)))]))
|
||||||
|
|
|
@ -19,21 +19,21 @@
|
||||||
(define (mutable-vector? v)
|
(define (mutable-vector? v)
|
||||||
(and (vector? v) (not (immutable? v))))
|
(and (vector? v) (not (immutable? v))))
|
||||||
|
|
||||||
(define (dict-supports? who d . whats)
|
|
||||||
(unless (dict? d)
|
|
||||||
(raise-argument-error who "dict?" d))
|
|
||||||
(define table (dict-def-table d))
|
|
||||||
(for/or ([what (in-list whats)])
|
|
||||||
(hash-ref table what #f)))
|
|
||||||
|
|
||||||
(define (dict-mutable? d)
|
(define (dict-mutable? d)
|
||||||
(dict-supports? 'dict-mutable? d 'dict-set!))
|
(unless (dict? d)
|
||||||
|
(raise-argument-error 'dict-mutable? "dict?" d))
|
||||||
|
(dict-supports? d 'dict-set!))
|
||||||
|
|
||||||
(define (dict-can-remove-keys? d)
|
(define (dict-can-remove-keys? d)
|
||||||
(dict-supports? 'dict-can-remove-keys? d 'dict-remove! 'dict-remove))
|
(unless (dict? d)
|
||||||
|
(raise-argument-error 'dict-can-remove-keys? "dict?" d))
|
||||||
|
(or (dict-supports? d 'dict-remove!)
|
||||||
|
(dict-supports? d 'dict-remove)))
|
||||||
|
|
||||||
(define (dict-can-functional-set? d)
|
(define (dict-can-functional-set? d)
|
||||||
(dict-supports? 'dict-can-functional-set? d 'dict-set))
|
(unless (dict? d)
|
||||||
|
(raise-argument-error 'dict-can-functional-set? "dict?" d))
|
||||||
|
(dict-supports? d 'dict-set))
|
||||||
|
|
||||||
(define (dict-has-key? d k)
|
(define (dict-has-key? d k)
|
||||||
(define not-there (gensym))
|
(define not-there (gensym))
|
||||||
|
@ -178,7 +178,7 @@
|
||||||
i)))
|
i)))
|
||||||
|
|
||||||
(define-primitive-generics
|
(define-primitive-generics
|
||||||
(dict gen:dict prop:gen:dict prop:gen:dict-methods dict? dict-def-table)
|
(dict gen:dict prop:gen:dict prop:gen:dict-methods dict? dict-supports?)
|
||||||
#:fast-defaults
|
#:fast-defaults
|
||||||
([mutable-hash?
|
([mutable-hash?
|
||||||
(define dict-ref hash-ref)
|
(define dict-ref hash-ref)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(#%provide define/generic
|
(#%provide define/generic
|
||||||
generic-property
|
generic-property
|
||||||
|
generic-methods
|
||||||
generic-method-table
|
generic-method-table
|
||||||
(for-syntax generic-info?
|
(for-syntax generic-info?
|
||||||
make-generic-info
|
make-generic-info
|
||||||
|
@ -72,11 +73,11 @@
|
||||||
[(_ gen)
|
[(_ gen)
|
||||||
(generic-info-property (get-info 'generic-property stx #'gen))]))
|
(generic-info-property (get-info 'generic-property stx #'gen))]))
|
||||||
|
|
||||||
(define-syntax (generic-method-table stx)
|
(define-syntax (generic-methods stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ gen def ...)
|
[(_ gen def ...)
|
||||||
(let ()
|
(let ()
|
||||||
(define info (get-info 'generic-method-table stx #'gen))
|
(define info (get-info 'generic-methods stx #'gen))
|
||||||
(define delta (syntax-local-make-delta-introducer #'gen))
|
(define delta (syntax-local-make-delta-introducer #'gen))
|
||||||
(define methods (map delta (generic-info-methods info)))
|
(define methods (map delta (generic-info-methods info)))
|
||||||
(with-syntax ([(method ...) methods])
|
(with-syntax ([(method ...) methods])
|
||||||
|
@ -86,7 +87,12 @@
|
||||||
([(method) (make-unimplemented 'method)] ...)
|
([(method) (make-unimplemented 'method)] ...)
|
||||||
()
|
()
|
||||||
def ...
|
def ...
|
||||||
(vector (implementation method) ...))))))]))
|
(values (implementation method) ...))))))]))
|
||||||
|
|
||||||
|
(define-syntax (generic-method-table stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ gen def ...)
|
||||||
|
#'(call-with-values (lambda () (generic-methods gen def ...)) vector)]))
|
||||||
|
|
||||||
(define-syntax (define/generic stx)
|
(define-syntax (define/generic stx)
|
||||||
(define gen-id (syntax-parameter-value #'generic-method-context))
|
(define gen-id (syntax-parameter-value #'generic-method-context))
|
||||||
|
|
|
@ -49,31 +49,43 @@
|
||||||
(check-identifier! #'self-name)
|
(check-identifier! #'self-name)
|
||||||
(define methods (syntax->list #'(method-name ...)))
|
(define methods (syntax->list #'(method-name ...)))
|
||||||
(for-each check-identifier! methods)
|
(for-each check-identifier! methods)
|
||||||
|
|
||||||
(define n (length methods))
|
(define n (length methods))
|
||||||
(define method-indices (for/list ([i (in-range n)]) i))
|
(define method-indices (for/list ([i (in-range n)]) i))
|
||||||
|
(define fast-preds (syntax->list #'(fast-pred ...)))
|
||||||
|
(define default-preds (syntax->list #'(default-pred ...)))
|
||||||
|
(define (generate-methods . ignore) (generate-temporaries methods))
|
||||||
|
(define (transpose-methods names)
|
||||||
|
(map cdr (apply map list methods names)))
|
||||||
|
|
||||||
|
(define fasts-by-type (map generate-methods fast-preds))
|
||||||
|
(define fasts-by-method (transpose-methods fasts-by-type))
|
||||||
|
(define defaults-by-type (map generate-methods default-preds))
|
||||||
|
(define defaults-by-method (transpose-methods defaults-by-type))
|
||||||
|
|
||||||
(define/with-syntax size n)
|
(define/with-syntax size n)
|
||||||
(define/with-syntax [method-index ...] method-indices)
|
(define/with-syntax [method-index ...] method-indices)
|
||||||
(define/with-syntax contract-str
|
(define/with-syntax contract-str
|
||||||
(format "~s" (syntax-e #'predicate-name)))
|
(format "~s" (syntax-e #'predicate-name)))
|
||||||
(define/with-syntax (default-pred-name ...)
|
(define/with-syntax (default-pred-name ...)
|
||||||
(generate-temporaries #'(default-pred ...)))
|
(generate-temporaries default-preds))
|
||||||
(define/with-syntax (default-impl-name ...)
|
|
||||||
(generate-temporaries #'(default-pred ...)))
|
|
||||||
(define/with-syntax (fast-pred-name ...)
|
(define/with-syntax (fast-pred-name ...)
|
||||||
(generate-temporaries #'(fast-pred ...)))
|
(generate-temporaries fast-preds))
|
||||||
(define/with-syntax (fast-impl-name ...)
|
(define/with-syntax ([fast-by-method ...] ...) fasts-by-method)
|
||||||
(generate-temporaries #'(fast-pred ...)))
|
(define/with-syntax ([fast-by-type ...] ...) fasts-by-type)
|
||||||
(define/with-syntax fallback-name
|
(define/with-syntax ([default-by-method ...] ...) defaults-by-method)
|
||||||
(generate-temporary #'self-name))
|
(define/with-syntax ([default-by-type ...] ...) defaults-by-type)
|
||||||
|
(define/with-syntax [fallback ...] (generate-methods))
|
||||||
(define/with-syntax forward-declaration
|
(define/with-syntax forward-declaration
|
||||||
(if (eq? (syntax-local-context) 'top-level)
|
(if (eq? (syntax-local-context) 'top-level)
|
||||||
#'(define-syntaxes (fast-pred-name ...
|
#'(define-syntaxes (fast-pred-name ...
|
||||||
fast-impl-name ...
|
|
||||||
default-pred-name ...
|
default-pred-name ...
|
||||||
default-impl-name ...
|
fast-by-method ... ...
|
||||||
fallback-name)
|
default-by-method ... ...
|
||||||
|
fallback ...)
|
||||||
(values))
|
(values))
|
||||||
#'(begin)))
|
#'(begin)))
|
||||||
|
|
||||||
#'(begin
|
#'(begin
|
||||||
(define-syntax generic-name
|
(define-syntax generic-name
|
||||||
(make-generic-info (quote-syntax property-name)
|
(make-generic-info (quote-syntax property-name)
|
||||||
|
@ -103,74 +115,78 @@
|
||||||
...)
|
...)
|
||||||
#t))
|
#t))
|
||||||
forward-declaration
|
forward-declaration
|
||||||
|
(define fast-pred-name fast-pred)
|
||||||
|
...
|
||||||
|
(define default-pred-name default-pred)
|
||||||
|
...
|
||||||
(define (predicate-name self-name)
|
(define (predicate-name self-name)
|
||||||
(or (fast-pred-name self-name)
|
(or (fast-pred-name self-name)
|
||||||
...
|
...
|
||||||
(prop:pred self-name)
|
(prop:pred self-name)
|
||||||
(default-pred-name self-name)
|
(default-pred-name self-name)
|
||||||
...))
|
...))
|
||||||
(define (table-name self-name [who 'table-name])
|
(define (supported-name self-name . syms)
|
||||||
|
(define (bad-sym sym)
|
||||||
|
(raise-argument-error 'supported-name
|
||||||
|
(format "~s" '(or/c 'method-name ...))
|
||||||
|
sym))
|
||||||
(cond
|
(cond
|
||||||
[(fast-pred-name self-name) fast-impl-name]
|
[(fast-pred-name self-name)
|
||||||
|
(for/and ([sym (in-list syms)])
|
||||||
|
(case sym
|
||||||
|
[(method-name) (procedure? fast-by-type)]
|
||||||
|
...
|
||||||
|
[else (bad-sym sym)]))]
|
||||||
...
|
...
|
||||||
[(prop:pred self-name) (accessor-name self-name)]
|
[(prop:pred self-name)
|
||||||
[(default-pred-name self-name) default-impl-name]
|
(define table (accessor-name self-name))
|
||||||
|
(for/and ([sym (in-list syms)])
|
||||||
|
(case sym
|
||||||
|
[(method-name)
|
||||||
|
(procedure? (vector-ref table 'method-index))]
|
||||||
|
...
|
||||||
|
[else (bad-sym sym)]))]
|
||||||
|
[(default-pred-name self-name)
|
||||||
|
(for/and ([sym (in-list syms)])
|
||||||
|
(case sym
|
||||||
|
[(method-name) (procedure? default-by-type)]
|
||||||
|
...
|
||||||
|
[else (bad-sym sym)]))]
|
||||||
...
|
...
|
||||||
[else (raise-argument-error who 'contract-str self-name)]))
|
[else (raise-argument-error 'supported-name
|
||||||
(define fast-pred-name fast-pred)
|
'contract-str
|
||||||
...
|
self-name)]))
|
||||||
(define default-pred-name default-pred)
|
|
||||||
...
|
|
||||||
(define-generic-support supported-name
|
|
||||||
self-name
|
|
||||||
[method-name ...]
|
|
||||||
(table-name self-name 'supported-name)
|
|
||||||
original)
|
|
||||||
(define-generic-method
|
(define-generic-method
|
||||||
method-name
|
method-name
|
||||||
method-signature
|
method-signature
|
||||||
self-name
|
self-name
|
||||||
(or (vector-ref (table-name self-name 'method-name) 'method-index)
|
(or (cond
|
||||||
(vector-ref fallback-name 'method-index))
|
[(fast-pred-name self-name) fast-by-method]
|
||||||
|
...
|
||||||
|
[(prop:pred self-name)
|
||||||
|
(vector-ref (accessor-name self-name) 'method-index)]
|
||||||
|
[(default-pred-name self-name) default-by-method]
|
||||||
|
...
|
||||||
|
[else (raise-argument-error 'method-name
|
||||||
|
'contract-str
|
||||||
|
self-name)])
|
||||||
|
fallback)
|
||||||
original)
|
original)
|
||||||
...
|
...
|
||||||
(define fast-impl-name
|
(define-values (fast-by-type ...)
|
||||||
(generic-method-table generic-name fast-defn ...))
|
(generic-methods generic-name fast-defn ...))
|
||||||
...
|
...
|
||||||
(define default-impl-name
|
(define-values (default-by-type ...)
|
||||||
(generic-method-table generic-name default-defn ...))
|
(generic-methods generic-name default-defn ...))
|
||||||
...
|
...
|
||||||
(define fallback-name
|
(define-values (fallback ...)
|
||||||
(generic-method-table generic-name fallback-defn ...))))]))
|
(generic-methods generic-name fallback-defn ...))))]))
|
||||||
|
|
||||||
(define-syntax (define-primitive-generics stx)
|
(define-syntax (define-primitive-generics stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ . args)
|
[(_ . args)
|
||||||
#`(define-primitive-generics/derived #,stx . args)]))
|
#`(define-primitive-generics/derived #,stx . args)]))
|
||||||
|
|
||||||
(define-syntax (define-generic-support stx)
|
|
||||||
(syntax-case stx ()
|
|
||||||
[(_ supported-name
|
|
||||||
self-name
|
|
||||||
[method-name ...]
|
|
||||||
table
|
|
||||||
original)
|
|
||||||
(parameterize ([current-syntax-context #'original])
|
|
||||||
(check-identifier! #'supported-name)
|
|
||||||
(check-identifier! #'self-name)
|
|
||||||
(for-each check-identifier! (syntax->list #'(method-name ...)))
|
|
||||||
(define/with-syntax (index ...)
|
|
||||||
(for/list ([idx (in-naturals)]
|
|
||||||
[stx (in-list (syntax->list #'(method-name ...)))])
|
|
||||||
idx))
|
|
||||||
#'(define (supported-name self-name)
|
|
||||||
(define v table)
|
|
||||||
(make-immutable-hasheqv
|
|
||||||
(list
|
|
||||||
(cons 'method-name
|
|
||||||
(procedure? (vector-ref v 'index)))
|
|
||||||
...))))]))
|
|
||||||
|
|
||||||
(begin-for-syntax
|
(begin-for-syntax
|
||||||
|
|
||||||
(define (method-formals/application name-stx proc-stx self-id sig-stx)
|
(define (method-formals/application name-stx proc-stx self-id sig-stx)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user