diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-04-05 19:27:34 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-04-05 19:27:34 -0700 |
commit | 444853031ea9e9a2a79c259c2696cc0b6dda18ff (patch) | |
tree | 6c7c2b8ac44d727ac9bf55256fcd3cfbba187e3f | |
parent | 6ca6be767f8ac84a8c601c08d6e06822ced556f9 (diff) | |
download | txr-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.c | 63 |
1 files changed, 35 insertions, 28 deletions
@@ -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); } |