diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-07-20 23:26:38 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-07-20 23:26:38 -0700 |
commit | 5613a3b0d42a89d061df18cd9ae4e1008696572c (patch) | |
tree | cf810df036b366a9f3fab00117db639e2b6c4378 | |
parent | a6f0c72306da0c628be9e180288f79fbf29bfa57 (diff) | |
download | txr-5613a3b0d42a89d061df18cd9ae4e1008696572c.tar.gz txr-5613a3b0d42a89d061df18cd9ae4e1008696572c.tar.bz2 txr-5613a3b0d42a89d061df18cd9ae4e1008696572c.zip |
parse/eval: use weak-both hash tables.
This addresses the problem that
a4c376979d15323ad729e92e41ba43768e8dc163
tried to fix.
* eval.c (eval_init): Make all the top-level binding tables,
top_fb, top_vb, top_mb, top_smb, special and builtin,
weak-both tables: keys and values are weak.
This way, the entries disappear if both key and value
are unreachable, even if they refer to each other.
(eval_compat_fixup): In 266 or earlier compat mode, weak-both
tables don't have the right semantics, so we tweak
the tables to weak-key tables.
* parser.c (parse_init): Same treatment for
stream_parser_hash. We want an entry to disappear from the
hash if neither the parser nor the stream are reachable.
(parse_compat_fixup): New function.
* parser.h (parse_compat_function): Declared.
* hash.c, hash.h (tweak_hash): New function.
* lib.c (compat_fixup): Call parse_compat_fixup.
-rw-r--r-- | eval.c | 21 | ||||
-rw-r--r-- | hash.c | 9 | ||||
-rw-r--r-- | hash.h | 1 | ||||
-rw-r--r-- | lib.c | 1 | ||||
-rw-r--r-- | parser.c | 8 | ||||
-rw-r--r-- | parser.h | 1 |
6 files changed, 34 insertions, 7 deletions
@@ -6488,12 +6488,12 @@ void eval_init(void) &call_f, &iter_begin_f, &iter_from_binding_f, &iter_more_f, &iter_item_f, &iter_step_f, &unbound_s, &origin_hash, &const_foldable_hash, convert(val *, 0)); - top_fb = make_hash(t, nil, nil); - top_vb = make_hash(t, nil, nil); - top_mb = make_hash(t, nil, nil); - top_smb = make_hash(t, nil, nil); - special = make_hash(t, nil, nil); - builtin = make_hash(t, nil, nil); + top_fb = make_hash(t, t, nil); + top_vb = make_hash(t, t, nil); + top_mb = make_hash(t, t, nil); + top_smb = make_hash(t, t, nil); + special = make_hash(t, t, nil); + builtin = make_hash(t, t, nil); op_table = make_hash(nil, nil, nil); pm_table = make_hash(nil, nil, nil); @@ -7342,6 +7342,15 @@ void eval_init(void) void eval_compat_fixup(int compat_ver) { + if (compat_ver <= 266) { + tweak_hash(top_fb, t, nil); + tweak_hash(top_vb, t, nil); + tweak_hash(top_mb, t, nil); + tweak_hash(top_smb, t, nil); + tweak_hash(special, t, nil); + tweak_hash(builtin, t, nil); + } + if (compat_ver <= 107) reg_fun(intern(lit("flip"), user_package), func_n1(swap_12_21)); } @@ -826,6 +826,15 @@ static val do_make_hash(val weak_keys, val weak_vals, } } +val tweak_hash(val hash, val weak_keys, val weak_vals) +{ + val self = lit("tweak-hash"); + struct hash *h = coerce(struct hash *, cobj_handle(self, hash, hash_cls)); + int flags = ((weak_vals != nil) << 1) | (weak_keys != nil); + h->flags = convert(hash_flags_t, flags); + return hash; +} + val make_seeded_hash(val weak_keys, val weak_vals, val equal_based, val seed) { return do_make_hash(weak_keys, weak_vals, @@ -39,6 +39,7 @@ extern struct cobj_class *hash_cls; ucnum equal_hash(val obj, int *count, ucnum); val make_seeded_hash(val weak_keys, val weak_vals, val equal_based, val seed); +val tweak_hash(val hash, val weak_keys, val weak_vals); val make_hash(val weak_keys, val weak_vals, val equal_based); val make_eq_hash(val weak_keys, val weak_vals); val make_similar_hash(val existing); @@ -14052,6 +14052,7 @@ int compat_fixup(int compat_ver) eval_compat_fixup(compat_ver); rand_compat_fixup(compat_ver); + parse_compat_fixup(compat_ver); return 0; } @@ -1878,7 +1878,7 @@ void parse_init(void) parser_cls = cobj_register(parser_s); protect(&stream_parser_hash, &unique_s, &catch_all, convert(val *, 0)); - stream_parser_hash = make_hash(t, nil, nil); + stream_parser_hash = make_hash(t, t, nil); catch_all = cons(t, nil); parser_l_init(); @@ -1897,3 +1897,9 @@ void parse_init(void) reg_fun(intern(lit("repl"), system_package), func_n4(repl)); reg_mac(json_s, func_n2(me_json)); } + +void parse_compat_fixup(int compat_ver) +{ + if (compat_ver <= 266) + tweak_hash(stream_parser_hash, t, nil); +} @@ -148,3 +148,4 @@ val parser_set_lineno(val self, val stream, val lineno); val parser_errors(val parser); val parse_errors(val stream); void parse_init(void); +void parse_compat_fixup(int compat_ver); |