diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-08-17 21:38:13 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-08-17 21:38:13 -0700 |
commit | 8f03981dfcd66aed76a98716e1a41a8bf1f0dbe6 (patch) | |
tree | d10f3588a0b1de6c6d1addcf0987904141cd5d78 | |
parent | 42ba138efa6159e1d0387b8f3c7b3fb1a34721ad (diff) | |
download | txr-8f03981dfcd66aed76a98716e1a41a8bf1f0dbe6.tar.gz txr-8f03981dfcd66aed76a98716e1a41a8bf1f0dbe6.tar.bz2 txr-8f03981dfcd66aed76a98716e1a41a8bf1f0dbe6.zip |
txr: identify output repeat vars at parse time
Up to now the @(repeat) and @(rep) directives have scanned
their interior to find output variables. We now hoist that
into the parser; the variables are found up-front and
integrated into the abstract syntax.
This work anticipates doing a more proper job of identifying
free variables in Lisp expressions.
* match.c (extract_vars): Delete static this function here.
It moves into parser.y.
(extract_bindings): Don't call extract_vars to obtain the
variables occurring in the repeat body. Get it as a new
argument, occur_vars.
(do_output_line, do_repeat): Extract the new occur_vars
element of the abstract syntax node and pass it to
extract_bindings.
* parser.y (extract_vars): New static function, moved here
from match.c.
(repeat_rep_helper): Scan over each of the repeat subclauses
with extract vars. Catenate the resulting lists together and
pass through uniq to squash repeated symbols. Then add the
resulting vars as a new element of the returned syntax node.
-rw-r--r-- | match.c | 58 | ||||
-rw-r--r-- | parser.y | 58 |
2 files changed, 64 insertions, 52 deletions
@@ -1886,59 +1886,13 @@ static val bind_cdr(val bind_cons) bind_cons); } -static val extract_vars(val output_spec) -{ - list_collect_decl (vars, tai); - - if (consp(output_spec)) { - val sym = first(output_spec); - if (sym == var_s) { - val name = second(output_spec); - val modifiers = third(output_spec); - - if (bindable(name)) - tai = list_collect(tai, name); - else - tai = list_collect_nconc(tai, extract_vars(name)); - - for (; modifiers; modifiers = cdr(modifiers)) { - val mod = car(modifiers); - if (bindable(mod)) { - tai = list_collect(tai, mod); - } else if (consp(mod)) { - val msym = car(mod); - - if (msym == dwim_s) { - val arg = second(mod); - - if (bindable(arg)) { - tai = list_collect(tai, arg); - } else if (consp(arg) && car(arg) == rcons_s) { - val f = second(arg); - val t = third(arg); - if (bindable(f)) - tai = list_collect(tai, f); - if (bindable(t)) - tai = list_collect(tai, t); - } - } - } - } - } else if (sym != expr_s) { - for (; output_spec; output_spec = cdr(output_spec)) - tai = list_collect_nconc(tai, extract_vars(car(output_spec))); - } - } - - return vars; -} - -static val extract_bindings(val bindings, val output_spec, val vars) +static val extract_bindings(val bindings, val output_spec, + val vars, val occur_vars) { list_collect_decl (bindings_out, ptail); list_collect_decl (var_list, vtail); - vtail = list_collect_nconc(vtail, extract_vars(output_spec)); + vtail = list_collect_nconc(vtail, occur_vars); for (; vars; vars = cdr(vars)) { val var = car(vars); @@ -2007,6 +1961,7 @@ static void do_output_line(val bindings, val specline, val filter, val out) val empty_clauses = pop(&clauses); val mod_clauses = pop(&clauses); val modlast_clauses = pop(&clauses); + val occur_vars = pop(&clauses); val counter_spec = getplist(args, counter_k); val consp_counter = consp(counter_spec); val counter = if3(consp_counter, first(counter_spec), counter_spec); @@ -2015,7 +1970,7 @@ static void do_output_line(val bindings, val specline, val filter, val out) second(counter_spec), bindings), zero); val vars = getplist(args, vars_k); - val bind_cp = extract_bindings(bindings, elem, vars); + val bind_cp = extract_bindings(bindings, elem, vars, occur_vars); val max_depth = reduce_left(func_n2(max2), bind_cp, zero, chain(func_n1(cdr), @@ -2142,6 +2097,7 @@ static void do_repeat(val bindings, val repeat_syntax, val filter, val out) val empty_clauses = pop(&clauses); val mod_clauses = pop(&clauses); val modlast_clauses = pop(&clauses); + val occur_vars = pop(&clauses); val counter_spec = getplist(args, counter_k); val consp_counter = consp(counter_spec); val counter = if3(consp_counter, first(counter_spec), counter_spec); @@ -2150,7 +2106,7 @@ static void do_repeat(val bindings, val repeat_syntax, val filter, val out) second(counter_spec), bindings), zero); val vars = getplist(args, vars_k); - val bind_cp = extract_bindings(bindings, repeat_syntax, vars); + val bind_cp = extract_bindings(bindings, repeat_syntax, vars, occur_vars); val max_depth = reduce_left(func_n2(max2), bind_cp, zero, chain(func_n1(cdr), @@ -1481,6 +1481,53 @@ static val expand_repeat_rep_args(val args) return out; } +static val extract_vars(val output_spec) +{ + list_collect_decl (vars, tai); + + if (consp(output_spec)) { + val sym = first(output_spec); + if (sym == var_s) { + val name = second(output_spec); + val modifiers = third(output_spec); + + if (bindable(name)) + tai = list_collect(tai, name); + else + tai = list_collect_nconc(tai, extract_vars(name)); + + for (; modifiers; modifiers = cdr(modifiers)) { + val mod = car(modifiers); + if (bindable(mod)) { + tai = list_collect(tai, mod); + } else if (consp(mod)) { + val msym = car(mod); + + if (msym == dwim_s) { + val arg = second(mod); + + if (bindable(arg)) { + tai = list_collect(tai, arg); + } else if (consp(arg) && car(arg) == rcons_s) { + val f = second(arg); + val t = third(arg); + if (bindable(f)) + tai = list_collect(tai, f); + if (bindable(t)) + tai = list_collect(tai, t); + } + } + } + } + } else if (sym != expr_s) { + for (; output_spec; output_spec = cdr(output_spec)) + tai = list_collect_nconc(tai, extract_vars(car(output_spec))); + } + } + + return vars; +} + static val repeat_rep_helper(val sym, val args, val main, val parts) { uses_or2; @@ -1491,6 +1538,7 @@ static val repeat_rep_helper(val sym, val args, val main, val parts) val empty_parts = nil, empty_parts_p = nil; val mod_parts = nil, mod_parts_p = nil; val modlast_parts = nil, modlast_parts_p = nil; + val occur_vars = nil; val iter; for (iter = parts; iter != nil; iter = cdr(iter)) { @@ -1528,9 +1576,17 @@ static val repeat_rep_helper(val sym, val args, val main, val parts) mod_parts = or2(nreverse(mod_parts), mod_parts_p); modlast_parts = or2(nreverse(modlast_parts), modlast_parts_p); + occur_vars = extract_vars(main); + occur_vars = nappend2(occur_vars, extract_vars(single_parts)); + occur_vars = nappend2(occur_vars, extract_vars(first_parts)); + occur_vars = nappend2(occur_vars, extract_vars(last_parts)); + occur_vars = nappend2(occur_vars, extract_vars(empty_parts)); + occur_vars = nappend2(occur_vars, extract_vars(mod_parts)); + occur_vars = uniq(occur_vars); + return list(sym, exp_args, main, single_parts, first_parts, last_parts, empty_parts, nreverse(mod_parts), - nreverse(modlast_parts), nao); + nreverse(modlast_parts), occur_vars, nao); } static void process_catch_exprs(val exprs) |