summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-07-21 07:34:12 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-07-21 07:34:12 -0700
commit17a0300e7d8858623feff27f5f43660ba90a0c32 (patch)
tree39f5ff69fa594681950fdcac4f4a1758d76d318a /eval.c
parent4c760c3b98fb4f0375b61b7b41e2c58bfca5fb59 (diff)
downloadtxr-17a0300e7d8858623feff27f5f43660ba90a0c32.tar.gz
txr-17a0300e7d8858623feff27f5f43660ba90a0c32.tar.bz2
txr-17a0300e7d8858623feff27f5f43660ba90a0c32.zip
hash: support both semantics of weak keys + values.
Hash tables with weak keys and values now support a choice of both possible semantics: under and-semantics, an entry lapses when both the key and value are unreachable. Under or-semantics, an entry lapses if either the key or value is unreachable. The and-semantics is new. Until TXR 266, only or-semantics was supported. This will be the default: when a hash table is specified as :weak-keys and :weak-vals, it will have or-semantics. The keywords :weak-or and :weak-and specify weak keys and values, with the specific semantics. They are utually exclusive, but tolerate the presence of :weak-keys and :weak-vals. The make-hash function is being extended such that if its leftmost argument, <weak-keys>, is specified as one of the keywords :weak-and or :weak-or, then the hash table will have weak keys and values with the specified semantics, and the <weak-vals> argument is ignored (values are weak even if that argument is false). * eval.c (eval_init): Initially register the top_vb, top_mb, top_smb, special and builtin hashes as ordinary hashes: no weak keys or values. Then use tweak_hash to switch to weak keys+vals with and-semantics. We do it this way because the keywords are not yet initialized; we cannot use them. * hash.h (enum hash_flags, hash_flags_t): Moved to header. Member hash_weak_both renamed to hash_weak_or. New member hash_weak_and. (weak_and_k, weak_or_k): New keyword variables. (hash_print_op): Handle hash_weak_and by printing :weak-and. (hash_mark): Handle hash_weak_and by marking nothing, like hash_weak_or. (do_make_hash): Check first argument against the two new keywords and set flags accordingly. This function is called from eval_init before the keywords have been initialized, in which case weak_keys == weak_and_k is true when both are nil; we watch for that. (tweak_hash): Now returns void and takes a hash_flags_t argument which is simply planted. (do_wak_tables): Implement hash_weak_and case. Remove the compat 266 stuff from hash_weak_or. Compatibility is no longer required since we are not changing the default semantics of hash tables. Phew; that's a load of worry off the plate. (hashv): Parse the two new keywords, validate and provide semantics. (hash_init): Initialize weak_and_k and weak_or_k kewyords. * hash.h (enum hash_flags, hash_flags_t): Moved here now. (weak_and_k, weak_or_k): Declared. * lib.c (compat_fixup): Remove call to parse_compat_fixup. * parser.c (parse_init): Create stream_parser_hash with and-semantics. (parse_compat_fixup): Function removed. * parser.h (parse_compat_fixup): Declaration removed. * txr.1: Hash documentation updated.
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c28
1 files changed, 13 insertions, 15 deletions
diff --git a/eval.c b/eval.c
index 77db6610..bb96d0cf 100644
--- a/eval.c
+++ b/eval.c
@@ -6488,15 +6488,22 @@ 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, 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);
+ top_fb = make_hash(nil, nil, nil);
+ top_vb = make_hash(nil, nil, nil);
+ top_mb = make_hash(nil, nil, nil);
+ top_smb = make_hash(nil, nil, nil);
+ special = make_hash(nil, nil, nil);
+ builtin = make_hash(nil, nil, nil);
op_table = make_hash(nil, nil, nil);
pm_table = make_hash(nil, nil, nil);
+ tweak_hash(top_fb, hash_weak_and);
+ tweak_hash(top_vb, hash_weak_and);
+ tweak_hash(top_mb, hash_weak_and);
+ tweak_hash(top_smb, hash_weak_and);
+ tweak_hash(special, hash_weak_and);
+ tweak_hash(builtin, hash_weak_and);
+
call_f = func_n1v(generic_funcall);
iter_begin_f = func_n1(iter_begin);
iter_from_binding_f = chain(cdr_f, iter_begin_f, nao);
@@ -7325,15 +7332,6 @@ 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 <= 257)
reg_fun(intern(lit("lexical-var-p"), user_package),
func_n2(old_lexical_var_p));