summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisplib.c2
-rw-r--r--share/txr/stdlib/except.tl14
-rw-r--r--txr.130
3 files changed, 44 insertions, 2 deletions
diff --git a/lisplib.c b/lisplib.c
index a6ef5a2f..6d9dcda7 100644
--- a/lisplib.c
+++ b/lisplib.c
@@ -270,7 +270,7 @@ static val hash_instantiate(val set_fun)
static val except_set_entries(val dlt, val fun)
{
val name[] = {
- lit("catch"), lit("catch*"), lit("handle"), lit("handle*"),
+ lit("catch"), lit("catch*"), lit("catch**"), lit("handle"), lit("handle*"),
lit("ignwarn"), lit("macro-time-ignwarn"),
nil
};
diff --git a/share/txr/stdlib/except.tl b/share/txr/stdlib/except.tl
index a2cc684c..73ba253d 100644
--- a/share/txr/stdlib/except.tl
+++ b/share/txr/stdlib/except.tl
@@ -41,6 +41,20 @@
(let ((catch-syms [mapcar car catch-clauses]))
^(sys:catch ,catch-syms ,try-form nil ,*catch-clauses)))
+(defmacro catch** (try-form . catch-clauses)
+ (let ((catch-syms [mapcar car catch-clauses])
+ sys-catch-clauses descs)
+ (each ((cl catch-clauses))
+ (mac-param-bind cl (type desc args . body) cl
+ (push ^(,type ,args ,*body) sys-catch-clauses)
+ (push desc descs)))
+ (sys:setq sys-catch-clauses (nreverse sys-catch-clauses))
+ (sys:setq descs (nreverse descs))
+ (let ((desc-expr (if [all descs constantp]
+ ^'(,*[mapcar eval descs])
+ ^(list ,*descs))))
+ ^(sys:catch ,catch-syms ,try-form ,desc-expr ,*sys-catch-clauses))))
+
(defun sys:expand-handle (form try-form handle-clauses)
(let* ((oper (car form))
(exc-sym (gensym))
diff --git a/txr.1 b/txr.1
index 9fcfaf13..2a9afa9b 100644
--- a/txr.1
+++ b/txr.1
@@ -38662,6 +38662,8 @@ string and additional arguments.
.mets \ \ >> {( symbol <> ( arg *) << body-form *)}*)
.mets (catch* < try-expression
.mets \ \ >> {( symbol >> ( type-arg << arg *) << body-form *)}*)
+.mets (catch** < try-expression
+.mets \ \ >> {( symbol < desc >> ( type-arg << arg *) << body-form *)}*)
.syne
.desc
The
@@ -38728,6 +38730,19 @@ Then the exception arguments follow. In contrast,
only the exception arguments are passed to the clauses of
.codn catch .
+The
+.code catch**
+macro is a further variant, which differs from
+.code catch*
+by requiring each catch clause to provide a description
+.metn desc ,
+an expression which evaluates to a character string.
+The
+.meta desc
+expressions are evaluated in left-to-right order prior to the
+evaluation of
+.metn try-expression .
+
Also see: the
.code unwind-protect
operator, and the functions
@@ -39297,7 +39312,7 @@ and not a derived representation.
.coNP Structures @, frame @ catch-frame and @ handle-frame
.synb
.mets (defstruct frame nil)
-.mets (defstruct catch-frame frame types jump)
+.mets (defstruct catch-frame frame types desc jump)
.mets (defstruct handle-frame frame types fun)
.syne
.desc
@@ -39341,6 +39356,19 @@ slot. This holds the list of exception type symbols which are matched
by the catch or handler.
The
+.code desc
+slot of a
+.code catch-frame
+holds a list of the descriptions produced by the
+.code catch**
+macro. If there are no descriptions, then this member is
+.codn nil ,
+otherwise it is a list whose elements are in correspondence
+with the list in the
+.code types
+slot.
+
+The
.code jump
slot of a
.code catch-frame