summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-04-05 19:27:34 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-04-05 19:27:34 -0700
commit444853031ea9e9a2a79c259c2696cc0b6dda18ff (patch)
tree6c7c2b8ac44d727ac9bf55256fcd3cfbba187e3f
parent6ca6be767f8ac84a8c601c08d6e06822ced556f9 (diff)
downloadtxr-444853031ea9e9a2a79c259c2696cc0b6dda18ff.tar.gz
txr-444853031ea9e9a2a79c259c2696cc0b6dda18ff.tar.bz2
txr-444853031ea9e9a2a79c259c2696cc0b6dda18ff.zip
quasiliterals: issue in printing embedded syms.
The op macro replaces syntax like @3 with gensyms. The problem is these genyms are not wrapped with (sys:var ...). For instance: `foo@{1}bar` ;; (sys:quasi "foo" (sys:var 1 () ()) "bar") might, inside an op expression turn into: (sys:quasi "foo" #:arg001 "bar") If this object is printed, it renders as `foo#:arg001bar` which is garbage syntax. After this fix, that will come out as: `foo@{#:arg001}bar` It is not read/print consistent, but it has the same meaning under evaluation. * lib.c (out_quasi_str_sym): New static function. Formed out of a block of code taken from out_quasi_str. (out_quasi_str): Print (sys:var ...) symbols via a call to out_quasi_str_sym, eliminating a block of code. If an element itself is a symbol, then print that using out_quasi_str_sym also.
-rw-r--r--lib.c63
1 files changed, 35 insertions, 28 deletions
diff --git a/lib.c b/lib.c
index 172a39d8..7241796c 100644
--- a/lib.c
+++ b/lib.c
@@ -9816,6 +9816,37 @@ static void out_lazy_str(val lstr, val out)
put_char(chr('"'), out);
}
+static void out_quasi_str_sym(val name, val mods, val rem_args,
+ val out, struct strm_ctx *ctx)
+{
+ val next_elem = car(rem_args);
+ val next_elem_char = and3(next_elem && !mods, stringp(next_elem),
+ chr_str(next_elem, zero));
+ val osstrm = make_string_output_stream();
+ val namestr = (obj_print_impl(name, osstrm, nil, ctx),
+ get_string_from_stream(osstrm));
+ int need_brace = mods ||
+ (next_elem_char &&
+ (chr_isalpha(next_elem_char) ||
+ chr_isdigit(next_elem_char) ||
+ next_elem_char == chr('_'))) ||
+ (span_str(namestr, lit("0123456789_"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"))
+ != length(namestr));
+ put_char(chr('@'), out);
+ if (need_brace)
+ put_char(chr('{'), out);
+ obj_print_impl(namestr, out, t, ctx);
+ while (mods) {
+ put_char(chr(' '), out);
+ obj_print_impl(car(mods), out, nil, ctx);
+ mods = cdr(mods);
+ }
+ if (need_brace)
+ put_char(chr('}'), out);
+}
+
static void out_quasi_str(val args, val out, struct strm_ctx *ctx)
{
val iter, next;
@@ -9831,38 +9862,14 @@ static void out_quasi_str(val args, val out, struct strm_ctx *ctx)
val sym = car(elem);
if (sym == var_s)
{
- val next_elem = car(next);
- val name = second(elem);
- val mods = third(elem);
- val next_elem_char = and3(next_elem && !mods, stringp(next_elem),
- chr_str(next_elem, zero));
- val osstrm = make_string_output_stream();
- val namestr = (obj_print_impl(name, osstrm, nil, ctx),
- get_string_from_stream(osstrm));
- int need_brace = mods ||
- (next_elem_char &&
- (chr_isalpha(next_elem_char) ||
- chr_isdigit(next_elem_char) ||
- next_elem_char == chr('_'))) ||
- (span_str(namestr, lit("0123456789_"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"))
- != length(namestr));
- put_char(chr('@'), out);
- if (need_brace)
- put_char(chr('{'), out);
- obj_print_impl(namestr, out, t, ctx);
- while (mods) {
- put_char(chr(' '), out);
- obj_print_impl(car(mods), out, nil, ctx);
- mods = cdr(mods);
- }
- if (need_brace)
- put_char(chr('}'), out);
+ out_quasi_str_sym(second(elem), third(elem), next,
+ out, ctx);
} else {
put_char(chr('@'), out);
obj_print_impl(elem, out, nil, ctx);
}
+ } else if (symbolp(elem)) {
+ out_quasi_str_sym(elem, nil, next, out, ctx);
} else {
obj_print_impl(elem, out, nil, ctx);
}