summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-02-22 09:03:49 -0800
committerKaz Kylheku <kaz@kylheku.com>2021-02-22 09:03:49 -0800
commit0a716217822fc2e74500ce935f5d4276c6a29eaf (patch)
tree4185052bce47ca38a59277212bbf7b658ce1f5dc
parent54c3c4929abf062717f36712cd20dc4873c8d04c (diff)
downloadtxr-0a716217822fc2e74500ce935f5d4276c6a29eaf.tar.gz
txr-0a716217822fc2e74500ce935f5d4276c6a29eaf.tar.bz2
txr-0a716217822fc2e74500ce935f5d4276c6a29eaf.zip
txr: bugfix: give @(call) same semantics as direct call.
The @(call) directive is buggy in the following ways, which cause an indirect call to behave differently from a direct call. It creates a new context, and so if the opening of a data source is deferred into the indirectly called function, that data source is lost when the indirect call terminates. Furthermore, if a data source is already established, there is no progress through the data: two consecutive @(call ...) directives operate on the same data. It also fails to implement vertical to horizontal fallback; if a function is not vertically defined, the directive fails. * match.c (v_call): Rewrite the core logic in the following way: we rewrite the indirect @(call) syntax into direct call syntax, substitute that into c->spec, and then just call v_fun. * tests/008/call-2.expected: New file. * tests/008/call-2.txr: New file. Test fails before this commit because both calls are matching against the same "A" element of the list.
-rw-r--r--match.c13
-rw-r--r--tests/008/call-2.expected0
-rw-r--r--tests/008/call-2.txr6
3 files changed, 9 insertions, 10 deletions
diff --git a/match.c b/match.c
index ef2daf9d..2b1a6f7c 100644
--- a/match.c
+++ b/match.c
@@ -4506,18 +4506,11 @@ static val v_call(match_files_ctx *c)
val funval = tleval_144(specline, funexpr, c->bindings);
val argexprs = cdr(exprs);
val call = cons(funval, argexprs);
- val spec = cons(cons(call, nil), nil);
- match_files_ctx ctx = mf_spec_bindings(*c, spec, c->bindings);
- val ret = v_fun(&ctx);
-
- if (ret == nil)
- return nil;
+ val spec = cons(cons(call, nil), cdr(c->spec));
- if (ret == decline_k)
- sem_error(nil, lit("call: function ~s not found"), funval, nao);
+ c->spec = spec;
- c->bindings = ctx.bindings;
- return ret;
+ return v_fun(c);
}
static val h_do(match_line_ctx *c)
diff --git a/tests/008/call-2.expected b/tests/008/call-2.expected
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/008/call-2.expected
diff --git a/tests/008/call-2.txr b/tests/008/call-2.txr
new file mode 100644
index 00000000..10257f62
--- /dev/null
+++ b/tests/008/call-2.txr
@@ -0,0 +1,6 @@
+@(define foo (var))
+@var
+@(end)
+@(next :list '("A" "B"))
+@(call (quote foo) "A")
+@(call (quote foo) "B")