diff options
-rw-r--r-- | stdlib/struct.tl | 16 | ||||
-rw-r--r-- | tests/012/oop.tl | 12 | ||||
-rw-r--r-- | txr.1 | 38 |
3 files changed, 53 insertions, 13 deletions
diff --git a/stdlib/struct.tl b/stdlib/struct.tl index d373c330..10b07710 100644 --- a/stdlib/struct.tl +++ b/stdlib/struct.tl @@ -427,9 +427,19 @@ (pp (new (fun-param-parser (cdr params) form))) (opt pp.(opt-syms)) (args (append pp.req opt pp.rest))) - ^((:method ,meth-name (,obj ,*pp.req - ,*(if opt (cons : (mapcar (lop list :) opt))) - ,*pp.rest) + ^((:method ,meth-name + (,obj ,*pp.req + ,*(if opt + (cons : (collect-each ((o pp.opt)) + (tree-case o + ((sym) ^(,sym :)) + ((sym init) o) + ((sym init sym-p) + (compile-error form + "~s: three-element optional \ \ + parameter ~s not supported" + o)))))) + ,*pp.rest) (qref ,delegate-expr (,target-method ,*args)))))) (define-struct-clause :mass-delegate (:form form self-var delegate-expr diff --git a/tests/012/oop.tl b/tests/012/oop.tl index b786e0b7..5cdd3ec3 100644 --- a/tests/012/oop.tl +++ b/tests/012/oop.tl @@ -102,12 +102,20 @@ (defstruct contractor () sub (:delegate work (me) me.sub.sub) - (:delegate break (me : min) me.sub.sub relax)) + (:delegate break (me : min) me.sub.sub relax) + (:delegate break20 (me : (min 20)) me.sub.sub relax)) (let ((co (new contractor sub (new contractor sub (new worker name "foo"))))) (mtest co.(work) "worker foo works" co.(break) "worker foo relaxes for 15 min" - co.(break 5) "worker foo relaxes for 5 min")) + co.(break 5) "worker foo relaxes for 5 min" + co.(break20 5) "worker foo relaxes for 5 min" + co.(break20) "worker foo relaxes for 20 min")) + +(test + (defstruct bad-delegate () + (:delegate del (x : (y z w)))) + :error) (defstruct api-x () (:method get (x a b : c . d) ^(api-x get ,x ,a ,b ,c ,d)) @@ -32025,16 +32025,38 @@ must be an expression which the delegate method can evaluate to produce a delegate object. The delegate method then passes its arguments to the target method, given by the .meta target-name -argument, invoked on the delegate object. If the delegate method has optional -parameters which have not received an argument value, those parameters -are treated as if they had received the colon symbol +argument, invoked on the delegate object. + +If the delegate method specifies an optional parameter without a default +initializing expression, and that optional parameter +is not given an argument value, it receives the colon symbol .code : -as their value, and that value is passed on. If the delegate method has -variadic parameters, they are applied to the target. If optional parameters -specified in +as its argument. That value is passed on to the corresponding parameter +of the delegate target method. Thus, if the target method has +an optional parameter in that same parameter position, that colon symbol +argument then has the effect of requesting the default value. +If the target method has an ordinary parameter in that position, then +the colon symbol is received as an ordinary argument value. + +If the delegate method specifies an optional parameter with a default +initializing expression, and that optional parameter is not given +an argument value, then the expression is evaluated to produce a value +for that parameter, in the usual manner, and that value is passed as +an argument to the corresponding parameter of the delegate target. +Thus, delegates are able to specify different optional argument defaulting +from their targets. + +A delegate may have an optional parameter in a position where the target +has a required parameter and vice versa. + +The three-element optional parameter expression, specifying a Boolean variable +which indicates whether the optional parameter has been given an argument, is +not supported by the .code :delegate -are given argument values, those are discarded, playing no role in the -delegation. +clause, and is diagnosed. + +If the delegate method has variadic parameters, they are passed on to the +target after the fixed parameters. .TP* Example: |