From 1ec8da8116d311199acd071d9fce8684d172ad9c Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 22 Feb 2021 09:03:49 -0800 Subject: 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. --- match.c | 13 +++---------- tests/008/call-2.expected | 0 tests/008/call-2.txr | 6 ++++++ 3 files changed, 9 insertions(+), 10 deletions(-) create mode 100644 tests/008/call-2.expected create mode 100644 tests/008/call-2.txr 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 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") -- cgit v1.2.3