summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--match.c22
-rw-r--r--txr.129
3 files changed, 55 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 9abf2bd2..42bf46af 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,14 @@
says: until/last clause has visibility to uncollated bindings from
collect.
+ * txr.1: Document behavior.
+
+2011-10-21 Kaz Kylheku <kaz@kylheku.com>
+
+ * match.c (v_collect): Regression bugfix. Make it work like the comment
+ says: until/last clause has visibility to uncollated bindings from
+ collect.
+
2011-10-21 Kaz Kylheku <kaz@kylheku.com>
Implementing @(set) directive for assigning to variables
diff --git a/match.c b/match.c
index 894f6d73..174c2a1c 100644
--- a/match.c
+++ b/match.c
@@ -776,6 +776,17 @@ next_coll:
c.bindings = nappend2(last_bindings, c.bindings);
}
+ /* If nothing was collected, but vars were specified,
+ then bind empty lists for the vars. */
+ if (!bindings_coll && vars) {
+ for (iter = vars; iter; iter = cdr(iter)) {
+ val sym = car(car(iter));
+ val exists = assoc(c.bindings, sym);
+ if (!exists)
+ c.bindings = acons(c.bindings, sym, nil);
+ }
+ }
+
*cout = c;
return next_spec_k;
}
@@ -2043,6 +2054,17 @@ next_collect:
c.bindings = nappend2(last_bindings, c.bindings);
}
+ /* If nothing was collected, but vars were specified,
+ then bind empty lists for the vars. */
+ if (!bindings_coll && vars) {
+ for (iter = vars; iter; iter = cdr(iter)) {
+ val sym = car(car(iter));
+ val exists = assoc(c.bindings, sym);
+ if (!exists)
+ c.bindings = acons(c.bindings, sym, nil);
+ }
+ }
+
*cout = c;
return next_spec_k;
}
diff --git a/txr.1 b/txr.1
index 9b47039c..a7941a93 100644
--- a/txr.1
+++ b/txr.1
@@ -1753,9 +1753,11 @@ There is one more keyword, :vars, discussed in the following section.
Normally, any variable for which a new binding occurs in a collect is
collected. A collect clause may be sloppy: it can neglect to collect some
variables on some iterations, or bind some variables which behave like
-local temporaries, but end up collated into lists.
+local temporaries, but end up collated into lists. Another issue is that
+the collect clause might not match anything at all, and then none of
+the variables are bound.
-The :vars keyword allows the query writer to tame the collect body.
+The :vars keyword allows the query writer to add discipline the collect body.
The argument to :vars is a list of variable specs. A variable spec is either a
symbol, or a (<symbol> <expression>) pair, where the expression specifies a
@@ -1769,11 +1771,17 @@ Furthermore, for any variable which is not specified with a default value, the
collect body, whenever it matches successfully, must bind that variable. If it
neglects to bind the variable, an exception of type query_error is thrown.
-For any variable which has a default value, if the collect body neglects to
-bind that variable, the behavior is as if the collect did bind that variable to that default value.
+For any variable which does have a default value, if the collect body neglects
+to bind that variable, the behavior is as if the collect did bind that variable
+to that default value.
The default values are expressions, and so can be quasiliterals.
+Lastly, if in the event that the collect does not match anything, the variables
+specified in vars (whether or not they have a default value) are all bound to
+empty lists. (These bindings are established after the processing of the
+until/last clause, if present.)
+
Example:
@(collect :vars (a b (c "foo")))
@@ -1794,6 +1802,19 @@ in the variable list. Furthermore, because there is no binding for c in the
body, a binding is created with the value "foo", exactly as if c matched
such a piece of text.
+In the following example, the assumption is that THIS NEVER MATCHES
+is not found anywhere in the input but the line THIS DOES MATCH is
+found and has a successor which is bound to a. Because the body did not
+match, the :vars a and b should be bound to empty lists. But a is bound
+by the last clause to some text, so this takes precedence. Only b is bound to a
+an empty list.
+
+ @(collect :vars (a b)
+ THIS NEVER MATCHES
+ @(last)
+ THIS DOES MATCH
+ @a
+ @(end)
.SS The Coll Directive