diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-12-26 20:14:13 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-12-26 20:14:13 -0800 |
commit | 837b0f15d86b21665fdf7c5d55cbe4ecd6d42ea4 (patch) | |
tree | 51014445b28a04de955cbdc8bd251538e464f8c0 /match.c | |
parent | 5335d788dc601a50fc26319d39b21bdcaf1457b6 (diff) | |
download | txr-837b0f15d86b21665fdf7c5d55cbe4ecd6d42ea4.tar.gz txr-837b0f15d86b21665fdf7c5d55cbe4ecd6d42ea4.tar.bz2 txr-837b0f15d86b21665fdf7c5d55cbe4ecd6d42ea4.zip |
TXR quasiliterals and output vars treated as Lisp.
* eval.c (format_field): Function moved here from match.c,
along with the introduction of a new behavior: if a meta-expr
occurs among the modifiers, its constituent expression
is evaluated in its place. This allows for @{a @[expr]}
which was previously not allowed in Lisp quasiliterals,
but worked in TXR quasiliterals due to the treatment
of @ by txeval.
(subst_vars): Static function turns external, so code in
match.c can call it instead of the subst_vars in that module.
For that purpose, it needs to take a filter argument and
process filters, like the match.c subst_vars.
(op_quasi_lit): Pass nil as filter argument to subst_vars.
* eval.h (format_field, subst_vars): Declared.
* match.c (format_field): Function removed, moved to
eval.c and slightly changed.
(subst_vars): Renamed to tx_subst_vars. By default, now just a
wrapper for subst_vars. In compatibility mode, invokes the
old logic.
(do_txeval, do_output_line): Call tx_subst_vars rather than
subst_vars.
* match.h (format_field): Declaration removed.
* parser.y (expr): Grammar production removed: no longer
referenced.
(o_var): Braced variable case now parsed as n_expr, and
expanded as expr by default, since this is Lisp now. In
compatibility mode, expanded using expand_meta.
Also SYMTOK case must be subject to expansion; an output
var can now be a symbol macro.
(expand_meta): Expand a quasi-literal as Lisp, except
in compatibility mode.
* txr.1: Bit of a documentation update. Existing doc isn't
totally clear.
Diffstat (limited to 'match.c')
-rw-r--r-- | match.c | 216 |
1 files changed, 69 insertions, 147 deletions
@@ -1384,164 +1384,86 @@ static val match_line_completely(match_line_ctx c) return result; } - -val format_field(val obj, val modifier, val filter, val eval_fun) -{ - val n = zero, sep = lit(" "); - val plist = nil; - val str; - - for (; modifier; pop(&modifier)) { - val item = first(modifier); - if (regexp(item)) { - uw_throw(query_error_s, lit("bad field format: regex modifier in output")); - } else if (keywordp(item)) { - plist = modifier; - break; - } else if (consp(item) && car(item) == dwim_s) { - val arg_expr = second(item); - - if (consp(arg_expr) && car(arg_expr) == range_s) { - val from = funcall1(eval_fun, second(arg_expr)); - val to = funcall1(eval_fun, third(arg_expr)); - - obj = sub(obj, from, to); - } else { - val arg = funcall1(eval_fun, arg_expr); - if (bignump(arg) || fixnump(arg)) { - obj = ref(obj, arg); - } else if (rangep(arg)) { - obj = sub(obj, from(arg), to(arg)); - } else { - uw_throwf(query_error_s, lit("format_field: bad index: ~s"), - arg, nao); - } - } - } else { - val v = funcall1(eval_fun, item); - if (fixnump(v)) - n = v; - else if (stringp(v)) - sep = v; - else - uw_throwf(query_error_s, - lit("bad field format: bad modifier object: ~s"), - item, nao); - } - } - - if (listp(obj)) - str = cat_str(mapcar(func_n1(tostringp), obj), sep); - else - str = if3(stringp(obj), obj, tostringp(obj)); - - { - val filter_sym = getplist(plist, filter_k); - - if (filter_sym) { - filter = get_filter(filter_sym); - - if (!filter) { - uw_throwf(query_error_s, - lit("bad field format: ~s specifies unknown filter"), - filter_sym, nao); - } - } - - if (filter) - str = filter_string_tree(filter, str); - } - - { - val right = lt(n, zero); - val width = if3(lt(n, zero), neg(n), n); - val diff = minus(width, length_str(str)); - - if (le(diff, zero)) - return str; - - if (ge(length_str(str), width)) - return str; - - { - val padding = mkstring(diff, chr(' ')); - - return if3(right, - cat_str(list(padding, str, nao), nil), - cat_str(list(str, padding, nao), nil)); - } - } -} - -static val subst_vars(val spec, val bindings, val filter) +static val tx_subst_vars(val spec, val bindings, val filter) { - list_collect_decl(out, iter); - uw_env_begin; + if (opt_compat && opt_compat <= 128) { + list_collect_decl(out, iter); + uw_env_begin; - uw_set_match_context(cons(spec, bindings)); + uw_set_match_context(cons(spec, bindings)); - while (spec) { - val elem = first(spec); + while (spec) { + val elem = first(spec); - if (consp(elem)) { - val sym = first(elem); + if (consp(elem)) { + val sym = first(elem); - if (sym == var_s) { - val expr = second(elem); - val modifiers = third(elem); - val str = txeval(spec, expr, bindings); + if (sym == var_s) { + val expr = second(elem); + val modifiers = third(elem); + val str = txeval(spec, expr, bindings); - /* If the object is a list, we let format_field deal with the - conversion to text, because the modifiers influence how - it is done. */ - if (!stringp(str) && !listp(str)) - str = tostringp(str); + /* If the object is a list, we let format_field deal with the + conversion to text, because the modifiers influence how + it is done. */ + if (!stringp(str) && !listp(str)) + str = tostringp(str); - if (modifiers) { - spec = cons(format_field(str, modifiers, filter, - curry_123_2(func_n3(txeval), spec, bindings)), - rest(spec)); - } else { - if (listp(str)) - str = cat_str(mapcar(func_n1(tostringp), str), lit(" ")); + if (modifiers) { + spec = cons(format_field(str, modifiers, filter, + curry_123_2(func_n3(txeval), spec, bindings)), + rest(spec)); + } else { + if (listp(str)) + str = cat_str(mapcar(func_n1(tostringp), str), lit(" ")); - spec = cons(filter_string_tree(filter, str), rest(spec)); - } + spec = cons(filter_string_tree(filter, str), rest(spec)); + } - continue; - } else if (sym == quasi_s) { - val nested = subst_vars(rest(elem), bindings, filter); - iter = list_collect_append(iter, nested); - spec = cdr(spec); - continue; - } else if (sym == expr_s) { - if (opt_compat && opt_compat < 100) { - val result = eval_with_bindings(rest(elem), spec, bindings, elem); - spec = cons(filter_string_tree(filter, tostringp(result)), rest(spec)); continue; + } else if (sym == quasi_s) { + val nested = tx_subst_vars(rest(elem), bindings, filter); + iter = list_collect_append(iter, nested); + spec = cdr(spec); + continue; + } else if (sym == expr_s) { + if (opt_compat && opt_compat < 100) { + val result = eval_with_bindings(rest(elem), spec, bindings, elem); + spec = cons(filter_string_tree(filter, tostringp(result)), rest(spec)); + continue; + } else { + val str = eval_with_bindings(rest(elem), spec, bindings, elem); + if (listp(str)) + str = cat_str(mapcar(func_n1(tostringp), str), lit(" ")); + else if (!stringp(str)) + str = tostringp(str); + spec = cons(filter_string_tree(filter, tostringp(str)), rest(spec)); + continue; + } } else { - val str = eval_with_bindings(rest(elem), spec, bindings, elem); - if (listp(str)) - str = cat_str(mapcar(func_n1(tostringp), str), lit(" ")); - else if (!stringp(str)) - str = tostringp(str); - spec = cons(filter_string_tree(filter, tostringp(str)), rest(spec)); + val nested = tx_subst_vars(elem, bindings, filter); + iter = list_collect_append(iter, nested); + spec = cdr(spec); continue; } - } else { - val nested = subst_vars(elem, bindings, filter); - iter = list_collect_append(iter, nested); - spec = cdr(spec); - continue; } + + iter = list_collect(iter, elem); + spec = cdr(spec); } - iter = list_collect(iter, elem); - spec = cdr(spec); - } + uw_env_end; + return out; + } else { + val saved_de = set_dyn_env(make_env(bindings, nil, nil)); + val out; - uw_env_end; - return out; + uw_set_match_context(cons(spec, bindings)); + out = subst_vars(spec, nil, filter); + set_dyn_env(saved_de); + + return out; + } } static val do_txeval(val spec, val form, val bindings, val allow_unbound) @@ -1570,12 +1492,12 @@ static val do_txeval(val spec, val form, val bindings, val allow_unbound) } else if (consp(form)) { val sym = first(form); if (sym == quasi_s) { - ret = cat_str(subst_vars(rest(form), bindings, nil), nil); + ret = cat_str(tx_subst_vars(rest(form), bindings, nil), nil); } else if (sym == quasilist_s) { val iter; list_collect_decl (out, tail); for (iter = rest(form); iter != nil; iter = cdr(iter)) - tail = list_collect(tail, subst_vars(cdr(car(iter)), bindings, nil)); + tail = list_collect(tail, tx_subst_vars(cdr(car(iter)), bindings, nil)); ret = out; } else if (sym == var_s) { ret = eval_with_bindings(second(form), spec, bindings, form); @@ -1770,8 +1692,8 @@ static void do_output_line(val bindings, val specline, val filter, val out) val directive = first(elem); if (directive == var_s) { - val str = cat_str(subst_vars(cons(elem, nil), - bindings, filter), nil); + val str = cat_str(tx_subst_vars(cons(elem, nil), + bindings, filter), nil); if (str == nil) sem_error(specline, lit("bad substitution: ~a"), second(elem), nao); @@ -1884,8 +1806,8 @@ static void do_output_line(val bindings, val specline, val filter, val out) format(out, lit("~a"), eval_with_bindings(rest(elem), elem, bindings, elem), nao); } else { - val str = cat_str(subst_vars(cons(elem, nil), - bindings, filter), nil); + val str = cat_str(tx_subst_vars(cons(elem, nil), + bindings, filter), nil); if (str == nil) sem_error(specline, lit("bad substitution: ~a"), second(elem), nao); |