summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-10-10 07:58:00 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-10-10 07:58:00 -0700
commit6aa141253aa8a9c0b8f93b38ac225eacfb93566c (patch)
tree9cbc351c56f4653333ba47293b56b1e3226dcd13
parent35c830aa764e6e456530ed9d18ff5a686d10d96c (diff)
downloadtxr-6aa141253aa8a9c0b8f93b38ac225eacfb93566c.tar.gz
txr-6aa141253aa8a9c0b8f93b38ac225eacfb93566c.tar.bz2
txr-6aa141253aa8a9c0b8f93b38ac225eacfb93566c.zip
New macro: with-objects.
* lisplib.c (with_resources_set_entries): "with-objects" added to name table. * share/txr/stdlib/with-resources.tl (with-objects): New macro. * txr.1: Documented with-objects. Added note to :fini specifier of defstruct pointing to call-finalizers and with-objects.
-rw-r--r--lisplib.c6
-rw-r--r--share/txr/stdlib/with-resources.tl8
-rw-r--r--txr.149
3 files changed, 62 insertions, 1 deletions
diff --git a/lisplib.c b/lisplib.c
index 122256f3..81240da3 100644
--- a/lisplib.c
+++ b/lisplib.c
@@ -130,7 +130,11 @@ static val txr_case_instantiate(val set_fun)
static val with_resources_set_entries(val dlt, val fun)
{
- val name[] = { lit("with-resources"), nil };
+ val name[] = {
+ lit("with-resources"),
+ lit("with-objects"),
+ nil
+ };
set_dlt_entries(dlt, name, fun);
return nil;
}
diff --git a/share/txr/stdlib/with-resources.tl b/share/txr/stdlib/with-resources.tl
index 50fc62a7..28cdd6fb 100644
--- a/share/txr/stdlib/with-resources.tl
+++ b/share/txr/stdlib/with-resources.tl
@@ -40,3 +40,11 @@
(nil
^(progn ,*body))
(other (error "with-resources: bad syntax"))))
+
+(defmacro with-objects (var-init-forms . body)
+ (let ((gens (mapcar (ret (gensym)) var-init-forms)))
+ ^(let ,gens
+ (unwind-protect
+ (let* ,(mapcar (aret ^(,@2 (set ,@1 ,@3))) gens var-init-forms)
+ ,*body)
+ ,*(reverse (mapcar (ret ^(call-finalizers ,@1)) gens))))))
diff --git a/txr.1 b/txr.1
index c0dd1ce3..c7321f75 100644
--- a/txr.1
+++ b/txr.1
@@ -18052,6 +18052,13 @@ specifier are not surrounded by an implicit
.RE
.PP
+Note that an object's finalizers can be called explicitly with
+.codn call-finalizers .
+The
+.code with-objects
+macro arranges for finalizers to be called on objects when the execution
+of a scope terminates by any means.
+
The slot names given in a
.code defstruct
must all be unique among themselves, but they
@@ -19089,6 +19096,48 @@ must name a static slot of that structure type.
The object retrieved from that static slot must be
callable as a function, and accept the arguments.
+.coNP Macro @ with-objects
+.synb
+.mets (with-objects >> ({( sym << init-form )}*) << body-form *)
+.syne
+The
+.code with-objects
+macro provides a binding construct very similar to
+.codn let* .
+
+Each
+.meta sym
+must be a symbol suitable for use as a variable name.
+
+Each
+.meta init-form
+is evaluated in sequence, and a binding is established for its
+corresponding
+.meta sym
+which is initialized with the value of that form. The binding
+is visible to subsequent
+.metn init-form -s.
+
+Additionally, the values of the
+.meta init-form -s
+are noted as they are produced. When the
+.code with-objects
+form terminates, by any means, the
+.code call-finalizers
+function is invoked on each value which was returned by an
+.meta init-form
+and had been noted. These calls are performed in the
+reverse order relative to the original evaluation of the forms.
+
+After the variables are established and initialized, the
+.metn body-form -s
+are evaluated in the scope of the variables. The value of the
+last form is returned, or else
+.code nil
+if there are no forms. The invocations of
+.code call-finalizers
+take place just before the value of the last form is returned.
+
.SS* Sequence Manipulation
.coNP Function @ seqp
.synb