misc small improvements to racket/surrogate
(generate less code in macro, add some basic test cases, small improvement to syntax errors, and small docs clarification)
This commit is contained in:
parent
02a267fdb2
commit
3e191fef04
|
@ -13,9 +13,9 @@ its surrogate object. Each host has a dynamically assigned surrogate,
|
||||||
so an object can completely change its behavior merely by changing the
|
so an object can completely change its behavior merely by changing the
|
||||||
surrogate.
|
surrogate.
|
||||||
|
|
||||||
@defform/subs[#:literals (override override-final)
|
@defform/subs[#:literals (augment override override-final)
|
||||||
(surrogate method-spec ...)
|
(surrogate method-spec ...)
|
||||||
([method-spec (method-id arg-spec ...)
|
([method-spec (augment method-id arg-spec ...)
|
||||||
(override method-id arg-spec ...)
|
(override method-id arg-spec ...)
|
||||||
(override-final method-id (lambda () default-expr)
|
(override-final method-id (lambda () default-expr)
|
||||||
arg-spec ...)]
|
arg-spec ...)]
|
||||||
|
@ -40,7 +40,8 @@ new value of the field. The @racket[get-surrogate] method returns the
|
||||||
current value of the field.
|
current value of the field.
|
||||||
|
|
||||||
The host mixin has a single overriding method for each
|
The host mixin has a single overriding method for each
|
||||||
@racket[method-id] in the @racket[surrogate] form. Each of these
|
@racket[method-id] in the @racket[surrogate] form (even the ones
|
||||||
|
specified with @racket[augment]. Each of these
|
||||||
methods is defined with a @racket[case-lambda] with one arm for each
|
methods is defined with a @racket[case-lambda] with one arm for each
|
||||||
@racket[arg-spec]. Each arm has the variables as arguments in the
|
@racket[arg-spec]. Each arm has the variables as arguments in the
|
||||||
@racket[arg-spec]. The body of each method tests the
|
@racket[arg-spec]. The body of each method tests the
|
||||||
|
|
66
pkgs/racket-test/tests/racket/surrogate.rkt
Normal file
66
pkgs/racket-test/tests/racket/surrogate.rkt
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#lang racket
|
||||||
|
(require rackunit racket/surrogate)
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define-values (host-mixin host<%> surrogate% surrogate<%>)
|
||||||
|
(surrogate (override m (x))))
|
||||||
|
|
||||||
|
(define o
|
||||||
|
(new (host-mixin
|
||||||
|
(class object%
|
||||||
|
(define/public (m x) (+ x 1))
|
||||||
|
(super-new)))))
|
||||||
|
|
||||||
|
(check-equal? (send o m 2) 3)
|
||||||
|
|
||||||
|
(send o set-surrogate
|
||||||
|
(new (class surrogate%
|
||||||
|
(define/override (m that that-m x)
|
||||||
|
x)
|
||||||
|
(super-new))))
|
||||||
|
|
||||||
|
(check-equal? (send o m 2) 2)
|
||||||
|
|
||||||
|
(send o set-surrogate
|
||||||
|
(new (class surrogate%
|
||||||
|
(define/override (m that that-m x)
|
||||||
|
(that-m (* x x)))
|
||||||
|
(super-new))))
|
||||||
|
|
||||||
|
(check-equal? (send o m 4) 17)
|
||||||
|
|
||||||
|
(send o set-surrogate #f)
|
||||||
|
|
||||||
|
(check-equal? (send o m 2) 3))
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define-values (host-mixin host<%> surrogate% surrogate<%>)
|
||||||
|
(surrogate (augment 0 m (x))))
|
||||||
|
|
||||||
|
(define o
|
||||||
|
(new (host-mixin
|
||||||
|
(class object%
|
||||||
|
(define/pubment (m x) (inner (+ x 1) m x))
|
||||||
|
(super-new)))))
|
||||||
|
|
||||||
|
(check-equal? (send o m 2) 0)
|
||||||
|
|
||||||
|
(send o set-surrogate
|
||||||
|
(new (class surrogate%
|
||||||
|
(define/override (m that that-m x)
|
||||||
|
x)
|
||||||
|
(super-new))))
|
||||||
|
|
||||||
|
(check-equal? (send o m 2) 2)
|
||||||
|
|
||||||
|
(send o set-surrogate
|
||||||
|
(new (class surrogate%
|
||||||
|
(define/override (m that that-m x)
|
||||||
|
(that-m (* x x)))
|
||||||
|
(super-new))))
|
||||||
|
|
||||||
|
(check-equal? (send o m 4) 0)
|
||||||
|
|
||||||
|
(send o set-surrogate #f)
|
||||||
|
|
||||||
|
(check-equal? (send o m 2) 0))
|
|
@ -87,11 +87,31 @@
|
||||||
[(augment result-expr name argspec ...)
|
[(augment result-expr name argspec ...)
|
||||||
(identifier? #'name)
|
(identifier? #'name)
|
||||||
(syntax name)]
|
(syntax name)]
|
||||||
[else (raise-syntax-error
|
[(override . whatever)
|
||||||
#f
|
(raise-syntax-error
|
||||||
"bad method specification"
|
#f
|
||||||
stx
|
"bad override method specification"
|
||||||
method-spec)]))
|
stx
|
||||||
|
method-spec)]
|
||||||
|
[(augment . whatever)
|
||||||
|
(raise-syntax-error
|
||||||
|
#f
|
||||||
|
"bad augment method specification"
|
||||||
|
stx
|
||||||
|
method-spec)]
|
||||||
|
[(id . whatever)
|
||||||
|
(identifier? #'id)
|
||||||
|
(raise-syntax-error
|
||||||
|
#f
|
||||||
|
"bad method specification, expected either override or augment"
|
||||||
|
stx
|
||||||
|
#'id)]
|
||||||
|
[whatever
|
||||||
|
(raise-syntax-error
|
||||||
|
#f
|
||||||
|
"bad method specification"
|
||||||
|
stx
|
||||||
|
method-spec)]))
|
||||||
|
|
||||||
(define (make-super-proc-case name def-expr)
|
(define (make-super-proc-case name def-expr)
|
||||||
(lambda (spec)
|
(lambda (spec)
|
||||||
|
@ -120,15 +140,15 @@
|
||||||
(syntax-case spec ()
|
(syntax-case spec ()
|
||||||
;; Not a rest arg: normal mode for super-call
|
;; Not a rest arg: normal mode for super-call
|
||||||
[(id ...) (syntax [(id ...)
|
[(id ...) (syntax [(id ...)
|
||||||
(if surrogate
|
(if the-surrogate
|
||||||
(send surrogate name this super-call id ...)
|
(send the-surrogate name this super-call id ...)
|
||||||
(super-call id ...))])]
|
(super-call id ...))])]
|
||||||
;; A rest arg: super-class takes args as a list
|
;; A rest arg: super-class takes args as a list
|
||||||
[id
|
[id
|
||||||
(identifier? (syntax id))
|
(identifier? (syntax id))
|
||||||
(syntax [name
|
(syntax [name
|
||||||
(if surrogate
|
(if the-surrogate
|
||||||
(send surrogate name this (lambda args (super-call args)) . id)
|
(send the-surrogate name this (lambda args (super-call args)) . id)
|
||||||
(super-call id))])]))))
|
(super-call id))])]))))
|
||||||
|
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
|
@ -142,7 +162,7 @@
|
||||||
(map make-empty-method
|
(map make-empty-method
|
||||||
(syntax->list
|
(syntax->list
|
||||||
(syntax (method-spec ...))))])
|
(syntax (method-spec ...))))])
|
||||||
(syntax/loc stx
|
(quasisyntax/loc stx
|
||||||
(let ([surrogate<%>
|
(let ([surrogate<%>
|
||||||
(interface ()
|
(interface ()
|
||||||
on-disable-surrogate
|
on-disable-surrogate
|
||||||
|
@ -154,37 +174,47 @@
|
||||||
get-surrogate
|
get-surrogate
|
||||||
ids ...)])
|
ids ...)])
|
||||||
(values
|
(values
|
||||||
(lambda (super%)
|
(λ (super%)
|
||||||
(class* super% (host<%>)
|
(class* super% (host<%>)
|
||||||
(field [surrogate #f])
|
(define the-surrogate #f)
|
||||||
(define/public (set-surrogate d)
|
(define/public-final (set-surrogate new-surrogate)
|
||||||
(when surrogate
|
(do-set-surrogate (λ (s) (set! the-surrogate s))
|
||||||
(send surrogate on-disable-surrogate this))
|
the-surrogate
|
||||||
|
this
|
||||||
;; error checking
|
new-surrogate
|
||||||
(when d
|
'(ids ...)))
|
||||||
(unless (object? d)
|
(define/public-final (get-surrogate) the-surrogate)
|
||||||
(error 'set-surrogate "expected an object, got: ~e" d))
|
|
||||||
(let ([methods-to-impl '(on-enable-surrogate on-disable-surrogate ids ...)]
|
|
||||||
[i (object-interface d)])
|
|
||||||
(for-each (lambda (x)
|
|
||||||
(unless (method-in-interface? x i)
|
|
||||||
(error 'set-surrogate "expected object to implement an ~s method" x)))
|
|
||||||
methods-to-impl)))
|
|
||||||
|
|
||||||
(set! surrogate d)
|
|
||||||
(when surrogate
|
|
||||||
(send surrogate on-enable-surrogate this)))
|
|
||||||
(define/public (get-surrogate) surrogate)
|
|
||||||
|
|
||||||
overriding-methods ...
|
overriding-methods ...
|
||||||
|
|
||||||
(super-new)))
|
(super-new)))
|
||||||
|
|
||||||
host<%>
|
host<%>
|
||||||
|
|
||||||
(class* object% (surrogate<%>)
|
#,(syntax/loc stx
|
||||||
(define/public (on-enable-surrogate x) (void))
|
(class* object% (surrogate<%>)
|
||||||
(define/public (on-disable-surrogate x) (void))
|
(define/public (on-enable-surrogate x) (void))
|
||||||
empty-methods ...
|
(define/public (on-disable-surrogate x) (void))
|
||||||
(super-new))
|
empty-methods ...
|
||||||
|
(super-new)))
|
||||||
surrogate<%>))))]))
|
surrogate<%>))))]))
|
||||||
|
|
||||||
|
(define (do-set-surrogate set-the-surrogate the-surrogate this new-surrogate ids)
|
||||||
|
(when the-surrogate
|
||||||
|
(send the-surrogate on-disable-surrogate this))
|
||||||
|
|
||||||
|
;; error checking
|
||||||
|
(when new-surrogate
|
||||||
|
(unless (object? new-surrogate)
|
||||||
|
(raise-argument-error 'set-surrogate "object?" new-surrogate))
|
||||||
|
(let ([methods-to-impl (list* 'on-enable-surrogate 'on-disable-surrogate ids)]
|
||||||
|
[i (object-interface new-surrogate)])
|
||||||
|
(for ([x (in-list methods-to-impl)])
|
||||||
|
(unless (method-in-interface? x i)
|
||||||
|
(raise-argument-error 'set-surrogate
|
||||||
|
(format "object with method ~s" x)
|
||||||
|
new-surrogate)))))
|
||||||
|
|
||||||
|
(set-the-surrogate new-surrogate)
|
||||||
|
(when new-surrogate
|
||||||
|
(send new-surrogate on-enable-surrogate this)))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user