summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/txr/stdlib/struct.tl4
-rw-r--r--struct.c25
-rw-r--r--struct.h1
-rw-r--r--tests/012/oop.expected3
-rw-r--r--tests/012/oop.tl10
-rw-r--r--txr.190
6 files changed, 115 insertions, 18 deletions
diff --git a/share/txr/stdlib/struct.tl b/share/txr/stdlib/struct.tl
index 9f643662..ecd1db5d 100644
--- a/share/txr/stdlib/struct.tl
+++ b/share/txr/stdlib/struct.tl
@@ -230,8 +230,8 @@
(list ,*args)))))
(atom ^(make-lazy-struct ',atom (lambda () (list (list ,*qpairs))))))))
-(defmacro meth (obj slot)
- ^(method ,obj ',slot))
+(defmacro meth (obj slot . bound-args)
+ ^[(fun method) ,obj ',slot ,*bound-args])
(defmacro usl (slot)
^(uslot ',slot))
diff --git a/struct.c b/struct.c
index 61ce4174..559dbb0e 100644
--- a/struct.c
+++ b/struct.c
@@ -151,7 +151,7 @@ void struct_init(void)
reg_fun(intern(lit("static-slot-p"), user_package), func_n2(static_slot_p));
reg_fun(intern(lit("structp"), user_package), func_n1(structp));
reg_fun(intern(lit("struct-type"), user_package), func_n1(struct_type));
- reg_fun(intern(lit("method"), user_package), func_n2(method));
+ reg_fun(intern(lit("method"), user_package), func_n2v(method_args));
reg_fun(intern(lit("super-method"), user_package), func_n2(super_method));
reg_fun(intern(lit("uslot"), user_package), func_n1(uslot));
reg_fun(intern(lit("umethod"), user_package), func_n1v(umethod));
@@ -1106,11 +1106,34 @@ static val method_fun(val env, varg args)
return generic_funcall(fun, args_copy);
}
+static val method_args_fun(val env, varg args)
+{
+ cons_bind (curried_args, fun_strct, env);
+ cons_bind (fun, strct, fun_strct);
+ cnum ca_len = c_num(length(curried_args));
+ args_decl(args_call, max(args->fill + 1 + ca_len, ARGS_MIN));
+ args_add(args_call, strct);
+ args_add_list(args_call, curried_args);
+ args_normalize(args_call, ca_len + 1);
+ args_cat_zap(args_call, args);
+ return generic_funcall(fun, args_call);
+}
+
val method(val strct, val slotsym)
{
return func_f0v(cons(slot(strct, slotsym), strct), method_fun);
}
+val method_args(val strct, val slotsym, struct args *args)
+{
+ if (!args_more(args, 0))
+ return func_f0v(cons(slot(strct, slotsym), strct), method_fun);
+ else
+ return func_f0v(cons(args_get_list(args),
+ cons(slot(strct, slotsym), strct)), method_args_fun);
+}
+
+
val super_method(val strct, val slotsym)
{
val super_slot = static_slot(super(struct_type(strct)), slotsym);
diff --git a/struct.h b/struct.h
index 5d116807..2e3d32cb 100644
--- a/struct.h
+++ b/struct.h
@@ -50,6 +50,7 @@ val static_slot_p(val type, val sym);
val structp(val obj);
val struct_type(val strct);
val method(val strct, val slotsym);
+val method_args(val strct, val slotsym, struct args *);
val super_method(val strct, val slotsym);
val uslot(val slot);
val umethod(val slot, struct args *);
diff --git a/tests/012/oop.expected b/tests/012/oop.expected
index 433a51d2..970434d9 100644
--- a/tests/012/oop.expected
+++ b/tests/012/oop.expected
@@ -12,6 +12,9 @@ canine
collie
poodle
colliecanine
+collie
+collie
+collie
#S(b a 1 b 2 c 3)
#S(d a nil b -2 c 3)
(10 20 300 42 42)
diff --git a/tests/012/oop.tl b/tests/012/oop.tl
index 52fe30bb..34808af2 100644
--- a/tests/012/oop.tl
+++ b/tests/012/oop.tl
@@ -43,6 +43,16 @@
(mapcar (umeth print *stdout*) (list (new collie) (new dog)))
(put-line)
+(let* ((ssl (gun (make-string-output-stream)))
+ (s1 (pop ssl))
+ (s2 (pop ssl))
+ (s3 (pop ssl))
+ (d (new collie)))
+ [(meth d print s1)]
+ [(meth d print s2)]
+ [(meth d print s3)]
+ (tprint [mapcar get-string-from-stream (list s1 s2 s3)]))
+
(defstruct b nil
(:instance a 1)
(:instance b 2)
diff --git a/txr.1 b/txr.1
index 4e9f4b7f..74c832c3 100644
--- a/txr.1
+++ b/txr.1
@@ -20889,11 +20889,16 @@ leftmost argument, so that the function has access to the object.
.coNP Macro @ meth
.synb
-.mets (meth < struct << slot )
+.mets (meth < struct < slot << curried-expr *)
.syne
.desc
The
.code meth
+macro allows indirection upon a method-like function stored
+in a function slot.
+
+The
+.code meth
macro binds
.meta struct
as the leftmost argument of the function stored in
@@ -20903,16 +20908,49 @@ That is to say, it returns a function
.meta f
such that
.cblk
-.meti >> ( f < arg ... )
+.meti >> [ f < arg ... ]
.cble
calls
.cblk
-.meti >> ( struct.slot < struct < arg ... )
+.meti >> [ struct.slot < struct < arg ... ]
.cble
except that
.meta struct
is evaluated only once.
+If one or more
+.meta curried-expr
+expressions are present, their values are bound inside
+.meta f
+also, and when
+.meta f
+is invoked, these are passed to the function stored in the slot.
+Thus if
+.meta f
+is produced by
+.code "(meth struct slot c1 c2 c3 ...)"
+then
+.cblk
+.meti >> [ f < arg ... ]
+.cble
+calls
+.cblk
+.meti >> [ struct.slot < struct < c1v < c2v < c3v ... arg ... ]
+.cble
+.cble
+except that
+.meta struct
+is evaluated only once, and
+.metn c1v ,
+.meta c2v
+and
+.meta c3v
+are the values of expressions
+.codn c1 ,
+.code c2
+and
+.codn c3 .
+
The argument
.meta struct
must be an expression which evaluates to a struct.
@@ -20927,10 +20965,20 @@ function:
(meth a b) <--> (method a 'b)
.cble
-The
-.code meth
-macro allows indirection upon a method-like function stored
-in a function slot.
+If
+.meta curried-arg
+expressions are present, the translation may be be understood
+as:
+
+.cblk
+ (meth a b c1 c2 ...) <--> [(fun method) a 'b c1 c2 ...]
+.cble
+
+In other words the
+.meta curried-arg
+expressions are evaluated under the
+.code dwim
+operator evaluation rules.
.TP* Example:
@@ -21547,14 +21595,20 @@ The return value is
.coNP Function @ method
.synb
-.mets (method < struct-obj << slot-name )
+.mets (method < struct-obj < slot-name << curried-arg *)
.syne
.desc
The
.code method
-function retrieves a function from a structure's slot
-and binds that function's left argument to the
-structure.
+function retrieves a function
+.meta m
+from a structure's slot
+and returns a new function which binds that function's
+left argument. If
+.meta curried-arg
+arguments are present, then they are also stored in
+the returned function. These are the
+.IR "curried arguments" .
The
.meta struct-obj
@@ -21564,13 +21618,19 @@ must be a symbol denoting a slot in that structure.
The slot must hold a function of at least one
argument.
-The
+The function
+.meta f
+which
.code method
-function returns a function which, when invoked,
-calls the function previously retrieved from the object's
+function returns, when invoked,
+calls the function
+.meta m
+previously retrieved from the object's
slot, passing to that function
.meta struct-obj
-as the leftmost argument, followed by the function's
+as the leftmost argument, followed by the curried
+arguments, followed by all of
+.metn f 's
own arguments.
Note: the