diff --git a/EqSat/include/Luau/Language.h b/EqSat/include/Luau/Language.h index ba5434f5..14581919 100644 --- a/EqSat/include/Luau/Language.h +++ b/EqSat/include/Luau/Language.h @@ -29,6 +29,14 @@ struct Atom { return !(*this == rhs); } + + struct Hash + { + size_t operator()(const Atom& atom) const + { + return std::hash{}(atom.value); + } + }; }; // `Language` is very similar to `Luau::Variant` with enough differences warranting a different type altogether. @@ -55,6 +63,7 @@ class Language using FnMove = void (*)(void*, void*); using FnDtor = void (*)(void*); using FnPred = bool (*)(const void*, const void*); + using FnHash = size_t (*)(const void*); template static void fnCopy(void* dst, const void* src) @@ -81,10 +90,17 @@ class Language return *static_cast(lhs) == *static_cast(rhs); } + template + static size_t fnHash(const void* buffer) + { + return typename T::Hash{}(*static_cast(buffer)); + } + static constexpr FnCopy tableCopy[sizeof...(Ts)] = {&fnCopy...}; static constexpr FnMove tableMove[sizeof...(Ts)] = {&fnMove...}; static constexpr FnDtor tableDtor[sizeof...(Ts)] = {&fnDtor...}; static constexpr FnPred tablePred[sizeof...(Ts)] = {&fnPred...}; + static constexpr FnHash tableHash[sizeof...(Ts)] = {&fnHash...}; static constexpr int getIndexFromTag(const char* tag) { @@ -161,10 +177,11 @@ public: public: struct Hash { - size_t operator()(const Language& lang) + size_t operator()(const Language& language) const { - // TODO. Currently here so I can build and test this project. - return 0; + size_t hash = std::hash{}(language.tag); + hash ^= tableHash[getIndexFromTag(language.tag)](&language.buffer); + return hash; } }; }; diff --git a/tests/EqSat.language.test.cpp b/tests/EqSat.language.test.cpp index a539188f..e5f5d772 100644 --- a/tests/EqSat.language.test.cpp +++ b/tests/EqSat.language.test.cpp @@ -4,6 +4,7 @@ #include "Luau/Language.h" #include +#include LUAU_EQSAT_ATOM(I32, int); LUAU_EQSAT_ATOM(Bool, bool); @@ -76,4 +77,21 @@ TEST_CASE("language_equality") CHECK(v3 != v4); } +TEST_CASE("language_is_mappable") +{ + std::unordered_map map; + + Value v1{I32{5}}; + Value v2{I32{5}}; + Value v3{Bool{true}}; + + map[v1] = 1; + map[v2] = 2; + map[v3] = 42; + + CHECK(map[v1] == 2); + CHECK(map[v2] == 2); + CHECK(map[v3] == 42); +} + TEST_SUITE_END();