summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-10-11 23:05:16 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-10-11 23:05:16 -0700
commit2cda9b946d701faa308b0915c83ea48fb94d94af (patch)
treea546879daba90dfd65fc370ab1e03475f7778d77
parentaa02bc7f31edabb9e09f9756d7ae8fbc41995017 (diff)
downloadtxr-2cda9b946d701faa308b0915c83ea48fb94d94af.tar.gz
txr-2cda9b946d701faa308b0915c83ea48fb94d94af.tar.bz2
txr-2cda9b946d701faa308b0915c83ea48fb94d94af.zip
structs: optional init-exprs now useful in :delegate
* stdlib/struct.tl (:delegate): Handle the two-element form of the optional parameter, which specifies the usual initializing expression for the default value. This is just passed through as-is to the generated method. Diagnose if the three-element form occurs. * tests/012/oop.tl: Some new tests. * txr.1: Documented.
-rw-r--r--stdlib/struct.tl16
-rw-r--r--tests/012/oop.tl12
-rw-r--r--txr.138
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))
diff --git a/txr.1 b/txr.1
index 846c35d4..e3cdf0a5 100644
--- a/txr.1
+++ b/txr.1
@@ -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: