diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-02-23 06:19:50 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-02-23 06:19:50 -0800 |
commit | 9a53386f3b8b6b41982decf162e4cd271d01ec97 (patch) | |
tree | 74085af7b6feefc200e1509f831b234f8bcbd53d /lib.c | |
parent | 6af39064ca9d9a78d0e12e64cb817f9080cf3793 (diff) | |
download | txr-9a53386f3b8b6b41982decf162e4cd271d01ec97.tar.gz txr-9a53386f3b8b6b41982decf162e4cd271d01ec97.tar.bz2 txr-9a53386f3b8b6b41982decf162e4cd271d01ec97.zip |
printer: revise package prefix decision.
* lib.c (symbol_needs_prefix): revisiting the wrongheaded
requirements codified in 7bc150f, because the ergonomics
is bad. In a package that has a local symbol that has the
same name as one in a fallback list, that symbol is always
printed with a prefix, which is annoying. The new rules
are simple: if the symbol being printed is the one which is
visible, then it gets no package prefix. Also, this
function now handles the full responsibility for the prefix
calculation, including for keyword symbols and uninterned
symbools. It returns nil to indicate no prefix is needed, or
else a character string. Moreover, logic is added to detect
symbols which have a home package, but are uninterned from it,
which should be printed with the "#" prefix. Lastly, this
function is optimized to avoid unnecessary gethash operations.
If a symbol S's home package is P, and P contains no hidden
symbols (overwhelmingly common situation), then S is interned
in P; no need to do the hash lookup to check this.
(obj_print_impl): Symbol printing simplified: if
symbol_needs_refix returns non-nil, that string value is
the prefix.
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 74 |
1 files changed, 50 insertions, 24 deletions
@@ -5557,40 +5557,68 @@ val symbol_visible(val package, val sym) val symbol_needs_prefix(val self, val package, val sym) { val name = symbol_name(sym); + val sym_pkg = sym->s.package; type_check (self, package, PKG); + if (!sym_pkg) + return lit("#"); + + if (sym_pkg == keyword_package) + return null_string; + + if (sym_pkg == package) { + if (us_hash_count(package->pk.hidhash) != zero) { + val here_cell = gethash_e(self, package->pk.symhash, name); + + if (here_cell) { + int found_here = (eq(cdr(here_cell), sym) != nil); + if (found_here) + return nil; + } + + return lit("#"); + } + + return nil; + } + { - int homed_here = (sym->s.package == package); - val home_cell = gethash_e(self, package->pk.symhash, name); - int present_here = (eq(cdr(home_cell), sym) != nil); val fallback = get_hash_userdata(package->pk.symhash); - val fb_cell = nil; - int in_fallback = 0; for (; fallback; fallback = cdr(fallback)) { val fb_pkg = car(fallback); - val cell = gethash_e(self, fb_pkg->pk.symhash, name); - if (cell) { - fb_cell = cell; - if (eq(cdr(cell), sym) != nil) { - in_fallback = 1; - break; + if (sym_pkg == fb_pkg) { + if (us_hash_count(fb_pkg->pk.hidhash) != zero) { + val cell = gethash_e(self, fb_pkg->pk.symhash, name); + if (cell) { + int found_in_fallback = (eq(cdr(cell), sym) != nil); + if (found_in_fallback) + return nil; + break; + } } + return nil; + } else { + if (gethash_e(self, fb_pkg->pk.symhash, name)) + break; } } + } - if (!homed_here && !present_here && !in_fallback) - return t; + if (us_hash_count(sym_pkg->pk.hidhash) != zero) { + val home_cell = gethash_e(self, sym_pkg->pk.symhash, name); - if ((homed_here || present_here) && fb_cell) - return t; + if (home_cell) { + int found_in_home = (eq(cdr(home_cell), sym) != nil); + if (found_in_home) + return sym_pkg->pk.name; + } - if (in_fallback && home_cell) - return t; + return lit("#"); } - return nil; + return sym_pkg->pk.name; } val find_symbol(val str, val package_in) @@ -11504,12 +11532,10 @@ dot: if (obj->s.package == keyword_package) put_char(chr(':'), out); } else { - if (!obj->s.package) { - put_string(lit("#:"), out); - } else if (obj->s.package == keyword_package) { - put_char(chr(':'), out); - } else if (symbol_needs_prefix(lit("print"), cur_package, obj)) { - put_string(obj->s.package->pk.name, out); + val prefix = symbol_needs_prefix(lit("print"), cur_package, obj); + + if (prefix) { + put_string(prefix, out); put_char(chr(':'), out); } } |