diff --git a/crates/compiler/builtins/roc/Dict.roc b/crates/compiler/builtins/roc/Dict.roc index d1ff58ae16..ff01cdf8ff 100644 --- a/crates/compiler/builtins/roc/Dict.roc +++ b/crates/compiler/builtins/roc/Dict.roc @@ -821,6 +821,13 @@ expect |> len |> Bool.isEq 0 +# Makes sure a Dict with Nat keys works +expect + empty + |> insert 7nat "Testing" + |> get 7 + |> Bool.isEq (Ok "Testing") + # We have decided not to expose the standard roc hashing algorithm. # This is to avoid external dependence and the need for versioning. # The current implementation is a form of [Wyhash final3](https://github.com/wangyi-fudan/wyhash/blob/a5995b98ebfa7bd38bfadc0919326d2e7aabb805/wyhash.h). diff --git a/crates/compiler/builtins/roc/Hash.roc b/crates/compiler/builtins/roc/Hash.roc index 5f8081e8f6..4e5845becb 100644 --- a/crates/compiler/builtins/roc/Hash.roc +++ b/crates/compiler/builtins/roc/Hash.roc @@ -14,14 +14,16 @@ interface Hash hashI32, hashI64, hashI128, + hashNat, complete, hashStrBytes, hashList, hashUnordered, ] imports [ + Bool.{ isEq }, List, Str, - Num.{ U8, U16, U32, U64, U128, I8, I16, I32, I64, I128 }, + Num.{ U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, Nat }, ] ## A value that can hashed. @@ -88,6 +90,21 @@ hashI64 = \hasher, n -> addU64 hasher (Num.toU64 n) hashI128 : a, I128 -> a | a has Hasher hashI128 = \hasher, n -> addU128 hasher (Num.toU128 n) +## Adds a single Nat to a hasher. +hashNat : a, Nat -> a | a has Hasher +hashNat = \hasher, n -> + isPlatform32bit = + x : Nat + x = 0xffff_ffff + y = Num.addWrap x 1 + + y == 0 + + if isPlatform32bit then + addU32 hasher (Num.toU32 n) + else + addU64 hasher (Num.toU64 n) + ## Adds a container of [Hash]able elements to a [Hasher] by hashing each element. ## The container is iterated using the walk method passed in. ## The order of the elements does not affect the final hash. diff --git a/crates/compiler/derive_key/src/hash.rs b/crates/compiler/derive_key/src/hash.rs index 7eec881038..18d5e468d2 100644 --- a/crates/compiler/derive_key/src/hash.rs +++ b/crates/compiler/derive_key/src/hash.rs @@ -174,6 +174,9 @@ const fn num_symbol_to_hash_lambda(symbol: Symbol) -> Option { Symbol::NUM_I128 | Symbol::NUM_SIGNED128 => { Some(SingleLambdaSetImmediate(Symbol::HASH_HASH_I128)) } + Symbol::NUM_NAT | Symbol::NUM_NATURAL => { + Some(SingleLambdaSetImmediate(Symbol::HASH_HASH_NAT)) + } _ => None, } } diff --git a/crates/compiler/module/src/symbol.rs b/crates/compiler/module/src/symbol.rs index 094d548a7d..3bb4ee17ee 100644 --- a/crates/compiler/module/src/symbol.rs +++ b/crates/compiler/module/src/symbol.rs @@ -1522,10 +1522,11 @@ define_builtins! { 11 HASH_HASH_I32: "hashI32" 12 HASH_HASH_I64: "hashI64" 13 HASH_HASH_I128: "hashI128" - 14 HASH_COMPLETE: "complete" - 15 HASH_HASH_STR_BYTES: "hashStrBytes" - 16 HASH_HASH_LIST: "hashList" - 17 HASH_HASH_UNORDERED: "hashUnordered" + 14 HASH_HASH_NAT: "hashNat" + 15 HASH_COMPLETE: "complete" + 16 HASH_HASH_STR_BYTES: "hashStrBytes" + 17 HASH_HASH_LIST: "hashList" + 18 HASH_HASH_UNORDERED: "hashUnordered" } 14 JSON: "Json" => { 0 JSON_JSON: "Json" diff --git a/crates/compiler/test_mono/generated/dict.txt b/crates/compiler/test_mono/generated/dict.txt index 516685e5a7..e55056b74a 100644 --- a/crates/compiler/test_mono/generated/dict.txt +++ b/crates/compiler/test_mono/generated/dict.txt @@ -1,22 +1,22 @@ procedure Dict.1 (): - let Dict.518 : List {[], []} = Array []; - let Dict.525 : U64 = 0i64; - let Dict.526 : U64 = 8i64; - let Dict.519 : List U64 = CallByName List.11 Dict.525 Dict.526; - let Dict.522 : I8 = CallByName Dict.34; - let Dict.523 : U64 = 8i64; - let Dict.520 : List I8 = CallByName List.11 Dict.522 Dict.523; - let Dict.521 : U64 = 0i64; - let Dict.517 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.518, Dict.519, Dict.520, Dict.521}; - ret Dict.517; + let Dict.520 : List {[], []} = Array []; + let Dict.527 : U64 = 0i64; + let Dict.528 : U64 = 8i64; + let Dict.521 : List U64 = CallByName List.11 Dict.527 Dict.528; + let Dict.524 : I8 = CallByName Dict.34; + let Dict.525 : U64 = 8i64; + let Dict.522 : List I8 = CallByName List.11 Dict.524 Dict.525; + let Dict.523 : U64 = 0i64; + let Dict.519 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.520, Dict.521, Dict.522, Dict.523}; + ret Dict.519; procedure Dict.34 (): - let Dict.524 : I8 = -128i64; - ret Dict.524; + let Dict.526 : I8 = -128i64; + ret Dict.526; -procedure Dict.4 (Dict.505): - let Dict.85 : U64 = StructAtIndex 3 Dict.505; - dec Dict.505; +procedure Dict.4 (Dict.507): + let Dict.85 : U64 = StructAtIndex 3 Dict.507; + dec Dict.507; ret Dict.85; procedure List.11 (List.113, List.114):