summaryrefslogtreecommitdiffstats
path: root/hash.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-02-12 20:25:27 -0800
committerKaz Kylheku <kaz@kylheku.com>2014-02-14 15:53:43 -0800
commit260968beacb1a2e1c6bdd652f75fe087f907ce0f (patch)
tree6f9da93f5136fc15dc0ad4c8fd1998edb8888081 /hash.c
parented290d6d0df5f4c694459f853983ab79929ea786 (diff)
downloadtxr-260968beacb1a2e1c6bdd652f75fe087f907ce0f.tar.gz
txr-260968beacb1a2e1c6bdd652f75fe087f907ce0f.tar.bz2
txr-260968beacb1a2e1c6bdd652f75fe087f907ce0f.zip
* eval.c (eval_init): Register hash_guni and hash_gisec as intrinsics.
* hash.c (hash_guni, hash_gisec): New functions. (hash_isec): Bugfix: since gethash was naively used, keys in hash2 associated with the value nil were erroneously omitted from the intersection. * hash.h (hash_guni, hash_gisec): Declared. * txr.1: Documented new functions.
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c61
1 files changed, 60 insertions, 1 deletions
diff --git a/hash.c b/hash.c
index f9548c3c..0941effb 100644
--- a/hash.c
+++ b/hash.c
@@ -952,6 +952,37 @@ val hash_uni(val hash1, val hash2)
}
}
+val hash_guni(val hash1, val hash2)
+{
+ struct hash *h1 = (struct hash *) cobj_handle(hash1, hash_s);
+ struct hash *h2 = (struct hash *) cobj_handle(hash2, hash_s);
+
+ if (h1->hash_fun != h2->hash_fun)
+ uw_throwf(error_s, lit("hash-guni: ~a and ~a are incompatible hashes"), hash1, hash2, nao);
+
+ {
+ val hout = make_similar_hash(hash1);
+ val hiter, entry;
+
+ for (hiter = hash_begin(hash1), entry = hash_next(hiter);
+ entry;
+ entry = hash_next(hiter))
+ {
+ sethash(hout, car(entry), cdr(entry));
+ }
+
+ for (hiter = hash_begin(hash2), entry = hash_next(hiter);
+ entry;
+ entry = hash_next(hiter))
+ {
+ val *loc = gethash_l(hout, car(entry), 0);
+ set(*loc, append2(*loc, cdr(entry)));
+ }
+
+ return hout;
+ }
+}
+
val hash_diff(val hash1, val hash2)
{
struct hash *h1 = (struct hash *) cobj_handle(hash1, hash_s);
@@ -991,7 +1022,9 @@ val hash_isec(val hash1, val hash2)
entry;
entry = hash_next(hiter))
{
- if (gethash(hash2, car(entry)))
+ val found;
+ gethash_f(hash2, car(entry), &found);
+ if (found)
sethash(hout, car(entry), cdr(entry));
}
@@ -999,6 +1032,32 @@ val hash_isec(val hash1, val hash2)
}
}
+val hash_gisec(val hash1, val hash2)
+{
+ struct hash *h1 = (struct hash *) cobj_handle(hash1, hash_s);
+ struct hash *h2 = (struct hash *) cobj_handle(hash2, hash_s);
+
+ if (h1->hash_fun != h2->hash_fun)
+ uw_throwf(error_s, lit("hash-uni: ~a and ~a are incompatible hashes"), hash1, hash2, nao);
+
+ {
+ val hout = make_similar_hash(hash1);
+ val hiter, entry;
+
+ for (hiter = hash_begin(hash1), entry = hash_next(hiter);
+ entry;
+ entry = hash_next(hiter))
+ {
+ val found;
+ val data2 = gethash_f(hash2, car(entry), &found);
+ if (found)
+ sethash(hout, car(entry), append2(cdr(entry), data2));
+ }
+
+ return hout;
+ }
+}
+
val hash_update(val hash, val fun)
{
val iter = hash_begin(hash);