summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--match.c43
-rw-r--r--txr.19
3 files changed, 53 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 009873c2..2ecfa3d1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
2011-11-17 Kaz Kylheku <kaz@kylheku.com>
+ * match.c (h_fun, v_fun): Bugfix! copy_list should be used for copying
+ the bindings, not copy_alist. Otherwise functions cannot destructively
+ update a binding, which is useless. We want a function not to
+ manipulate the binding list, but to be able to manipulate the
+ contents of bindings.
+ (match_files_ctx): Declaration moved ahead of match_line.
+ (v_fun): Forward declaration added.
+ (match_line): Allow vertical functions to be called from
+ a horizontal context, in a limited way.
+
+ * txr.1: Mention the possibility of a call from a horizontal
+ context falling back on a vertical function.
+
+2011-11-17 Kaz Kylheku <kaz@kylheku.com>
+
* parser.y: Bugfix: precedence of { } must be low, close to that of
IDENT, otherwise @{var}@(foo) doesn't parse.
diff --git a/match.c b/match.c
index 3e10b9bb..a4efdf4b 100644
--- a/match.c
+++ b/match.c
@@ -941,7 +941,7 @@ static val h_fun(match_line_ctx c, match_line_ctx *cout)
val ub_p_a_pairs = nil;
val body = cdr(func);
val piter, aiter;
- val bindings_cp = copy_alist(c.bindings);
+ val bindings_cp = copy_list(c.bindings);
if (!equal(length(args), length(params)))
sem_error(elem, lit("function ~a takes ~a argument(s)"),
@@ -1031,6 +1031,15 @@ static val h_eol(match_line_ctx c, match_line_ctx *cout)
return nil;
}
+typedef struct {
+ val spec, files, bindings, data, data_lineno;
+} match_files_ctx;
+
+static match_files_ctx mf_all(val spec, val files, val bindings,
+ val data, val data_lineno);
+
+static val v_fun(match_files_ctx *c);
+
static val match_line(match_line_ctx c)
{
for (;;) {
@@ -1095,12 +1104,26 @@ static val match_line(match_line_ctx c)
c = nc;
continue;
} else if (result == decline_k) {
- if (gethash(v_directive_table, directive))
- sem_error(elem, lit("~a only exists as a vertical directive"),
- directive, nao);
- else
- sem_error(elem, lit("no such function or directive: ~a"),
- directive, nao);
+ val spec = rlcp(cons(cons(elem, nil), nil), elem);
+ match_files_ctx vc = mf_all(spec, nil, c.bindings, nil, num(0));
+ val vresult = v_fun(&vc);
+
+ if (vresult == next_spec_k) {
+ c.bindings = vc.bindings;
+ break;
+ } else if (vresult == repeat_spec_k) {
+ c.bindings = vc.bindings;
+ continue;
+ } else if (vresult == decline_k) {
+ if (gethash(v_directive_table, directive))
+ sem_error(elem, lit("~a only exists as a vertical directive"),
+ directive, nao);
+ else
+ sem_error(elem, lit("no such function or directive: ~a"),
+ directive, nao);
+ } else {
+ return vresult;
+ }
} else {
return result;
}
@@ -1539,10 +1562,6 @@ static void do_output(val bindings, val specs, val filter, val out)
}
}
-typedef struct {
- val spec, files, bindings, data, data_lineno;
-} match_files_ctx;
-
static match_files_ctx mf_all(val spec, val files, val bindings,
val data, val data_lineno)
{
@@ -2889,7 +2908,7 @@ static val v_fun(match_files_ctx *c)
val ub_p_a_pairs = nil;
val body = cdr(func);
val piter, aiter;
- val bindings_cp = copy_alist(c->bindings);
+ val bindings_cp = copy_list(c->bindings);
debug_check(specline, c->bindings, if2(consp(c->data), car(c->data)), c->data_lineno, nil);
diff --git a/txr.1 b/txr.1
index ed5832c5..f8197650 100644
--- a/txr.1
+++ b/txr.1
@@ -3021,8 +3021,13 @@ Example:
Output: fun="horizontal"
-A call made in a clearly horizontal context will ignore
-the vertical definition, if any, and require the horizontal function.
+A call made in a clearly horizontal context will prefer the
+horizontal function, and only fall back on the vertical one
+if the horizontal one doesn't exist. (In this fall-back case,
+the vertical function is called with empty data; it is useful
+for calling vertical functions which process arguments and
+produce values.)
+
In the next example, the call is followed by trailing material,
placing it in a horizontal context. Leading material will
do the same thing: