about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-02-17 10:29:40 -0800
committerKartik K. Agaram <vc@akkartik.com>2016-02-17 10:29:40 -0800
commit37e717859c47a86754e1d2d33865513a7c16dcb0 (patch)
tree8261b16d12cdc920c3f86cefe8532756253a9c2f
parent3adc9e08715fb695b8a7f53d5cfb3db1bd434b05 (diff)
downloadmu-37e717859c47a86754e1d2d33865513a7c16dcb0.tar.gz
2668 - add an escape hatch for 'hash'
If you don't want a field of a container to be included in its hash, use
the /ignore-for-hash property.

This property only works for containers, not exclusive-containers or
arrays. Mu will warn if you misuse it.
-rw-r--r--077hash.cc21
1 files changed, 21 insertions, 0 deletions
diff --git a/077hash.cc b/077hash.cc
index f2cc403d..d5e45095 100644
--- a/077hash.cc
+++ b/077hash.cc
@@ -101,6 +101,7 @@ size_t hash_mu_container(size_t h, const reagent& r) {
   long long int offset = 0;
   for (long long int i = 0; i < SIZE(info.elements); ++i) {
     reagent element = element_type(r, i);
+    if (has_property(element, "ignore-for-hash")) continue;
     element.set_value(address+offset);
     h = hash(h, element);
 //?     cerr << i << ": " << h << '\n';
@@ -119,6 +120,9 @@ size_t hash_mu_exclusive_container(size_t h, const reagent& r) {
   assert(r.type->value);
   long long int tag = get(Memory, r.value);
   reagent variant = variant_type(r, tag);
+  // todo: move this warning to container definition time
+  if (has_property(variant, "ignore-for-hash"))
+    raise << get(Type, r.type->value).name << ": /ignore-for-hash won't work in exclusive containers\n";
   variant.set_value(r.value + /*skip tag*/1);
   h = hash(h, variant);
   return h;
@@ -173,6 +177,23 @@ recipe main [
 # hash on containers includes all elements
 +mem: storing 0 in location 9
 
+:(scenario hash_can_ignore_container_elements)
+container foo [
+  x:number
+  y:character/ignore-for-hash
+]
+recipe main [
+  1:foo <- merge 34, 97/a
+  3:number <- hash 1:foo
+  reply-unless 3:number
+  4:foo <- merge 34, 98/a
+  6:number <- hash 4:foo
+  reply-unless 6:number
+  7:boolean <- equal 3:number, 6:number
+]
+# hashes match even though y is different
++mem: storing 1 in location 7
+
 //: These properties aren't necessary for hash, they just test that the
 //: current implementation works like we think it does.