From 43b4d36e37ca650cdf70568240ccc041b20306bd Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 17 Oct 2014 21:17:11 -0700 Subject: * match.c (dest_bind): Remove the restriction of not allowing @(expr ...) and @var on the left side of a bind. This is useful, and necessary for @(line @(lisp expr)) to work: matching computed line numbers and character positions. * txr.1: Document use of Lisp on left hand side of bind, that there is a restriction on the left hand side of a set, and that Lisp can be used in a line or chr directive for computed matches. --- ChangeLog | 12 ++++++++++++ match.c | 16 ++++++++++++++-- txr.1 | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5d876612..6453947e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2014-10-17 Kaz Kylheku + + * match.c (dest_bind): Remove the restriction of not allowing + @(expr ...) and @var on the left side of a bind. This + is useful, and necessary for @(line @(lisp expr)) to work: + matching computed line numbers and character positions. + + * txr.1: Document use of Lisp on left hand side of bind, + that there is a restriction on the left hand side of a set, + and that Lisp can be used in a line or chr directive for + computed matches. + 2014-10-17 Kaz Kylheku * HACKING: New section Type Safety. diff --git a/match.c b/match.c index 95328b32..9e699646 100644 --- a/match.c +++ b/match.c @@ -296,15 +296,27 @@ static val dest_bind(val spec, val bindings, val pattern, } } else if (consp(pattern)) { val piter = pattern, viter = value; + val lisp_evaled = nil; + val ret; if (first(pattern) == var_s) { - sem_error(spec, lit("metavariable @~a syntax cannot be used here"), second(pattern), nao); + uw_env_begin; + uw_set_match_context(cons(spec, bindings)); + ret = eval(second(pattern), make_env(bindings, nil, nil), pattern); + lisp_evaled = t; + uw_env_end; } if (first(pattern) == expr_s) { - sem_error(spec, lit("the @~s syntax cannot be used here"), rest(pattern), nao); + uw_env_begin; + uw_set_match_context(cons(spec, bindings)); + ret = eval(rest(pattern), make_env(bindings, nil, nil), pattern); + lisp_evaled = t; + uw_env_end; } + if (lisp_evaled) + return if3(tree_find(value, ret, swap_12_21(testfun)), bindings, t); while (consp(piter) && consp(viter)) { diff --git a/txr.1 b/txr.1 index 4541c485..006d3b0a 100644 --- a/txr.1 +++ b/txr.1 @@ -3678,6 +3678,19 @@ takes the entire line of input: @(chr 0)@(chr 0)@x .cble +The argument of +.code line +or +.code chr +may be a +.codn @ -delimited +Lisp expression. This is useful for matching computed lines or +character positions: + +.cblk + @(line @(+ a (* b c))) +.cble + .dirs some all none maybe cases choose These directives, called the parallel directives, combine multiple subqueries, @@ -5351,6 +5364,33 @@ matches .str c if these are upcased. +.coNP Lisp forms in the @ bind directive + +\*(TL forms, introduced by +.code @ +may be used on either side of +.codn bind . + + +Example: + +.cblk + @(bind a @(+ 2 2)) + @(bind @(+ 2 2) @(* 2 2)) +.cble + +Here, +.code a +is bound to the integer +.codn 4 . +The second +.code bind +then succeeds because the forms +.code (+ 2 2) +and +.code (* 2 2) +produce equal values. + .dir set The @@ -5420,6 +5460,21 @@ binds to @(set (A B . C) D) .cble +Note that +.code set +does not support a \*(TL expression on the left side, so the following +are invalid syntax: + +.cblk + @(set @(+ 1 1) @(* 2 2)) + @(set @b @(list "a")) +.cble + +The second one is erroneous even though there is a variable on the left. +Because it is preceded by the +.code @ +escape, it is a Lisp variable, and not a pattern variable. + .dir rebind The -- cgit v1.2.3