diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | match.c | 22 | ||||
-rw-r--r-- | txr.1 | 29 |
3 files changed, 55 insertions, 4 deletions
@@ -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 @@ -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; } @@ -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 |