1 // Copyright 2016-2021 Doug Moen
2 // Licensed under the Apache License, version 2.0
3 // See accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0
4
5 #include <libcurv/function.h>
6 #include <libcurv/meaning.h>
7 #include <boost/functional/hash.hpp>
8
9 namespace curv
10 {
11
hash() const12 size_t Operation::hash() const noexcept
13 {
14 return size_t(this);
15 }
hash_eq(const Operation & rhs) const16 bool Operation::hash_eq(const Operation& rhs) const noexcept
17 {
18 return this == &rhs;
19 }
20
hash() const21 size_t Prefix_Expr_Base::hash() const noexcept
22 {
23 size_t result = typeid(*this).hash_code();
24 boost::hash_combine(result, arg_->hash());
25 return result;
26 }
hash_eq(const Operation & rhs) const27 bool Prefix_Expr_Base::hash_eq(const Operation& rhs) const noexcept
28 {
29 if (typeid(rhs) == typeid(*this)) {
30 auto& r = dynamic_cast<const Prefix_Expr_Base&>(rhs);
31 return arg_->hash_eq(*r.arg_);
32 }
33 return false;
34 }
35
36 #define GEN_BINARY_HASH(Class) \
37 size_t Class::hash() const noexcept \
38 { \
39 size_t result = arg1_->hash(); \
40 boost::hash_combine(result, arg2_->hash()); \
41 boost::hash_combine(result, #Class); \
42 return result; \
43 } \
44 bool Class::hash_eq(const Operation& rhs) const noexcept \
45 { \
46 auto r = dynamic_cast<const Class*>(&rhs); \
47 if (r) \
48 return arg1_->hash_eq(*r->arg1_) \
49 && arg2_->hash_eq(*r->arg2_); \
50 return false; \
51 }
52
53 #define arg1_ func_
54 #define arg2_ arg_
55 GEN_BINARY_HASH(Call_Expr)
56 #undef arg1_
57 #undef arg2_
58
59 #define GEN_TERNARY_HASH(Class) \
60 size_t Class::hash() const noexcept \
61 { \
62 size_t result = arg1_->hash(); \
63 boost::hash_combine(result, arg2_->hash()); \
64 boost::hash_combine(result, arg3_->hash()); \
65 boost::hash_combine(result, #Class); \
66 return result; \
67 } \
68 bool Class::hash_eq(const Operation& rhs) const noexcept \
69 { \
70 auto r = dynamic_cast<const Class*>(&rhs); \
71 if (r) \
72 return arg1_->hash_eq(*r->arg1_) \
73 && arg2_->hash_eq(*r->arg2_) \
74 && arg3_->hash_eq(*r->arg3_); \
75 return false; \
76 }
77
GEN_TERNARY_HASH(If_Else_Op)78 GEN_TERNARY_HASH(If_Else_Op)
79
80 size_t Constant::hash() const noexcept
81 {
82 size_t result = value_.hash();
83 boost::hash_combine(result, "Constant");
84 return result;
85 }
hash_eq(const Operation & rhs) const86 bool Constant::hash_eq(const Operation& rhs) const noexcept
87 {
88 auto r = dynamic_cast<const Constant*>(&rhs);
89 if (r)
90 return value_.hash_eq(r->value_);
91 return false;
92 }
93
hash() const94 size_t Local_Data_Ref::hash() const noexcept
95 {
96 size_t result = slot_;
97 boost::hash_combine(result, "Local_Data_Ref");
98 return result;
99 }
hash_eq(const Operation & rhs) const100 bool Local_Data_Ref::hash_eq(const Operation& rhs) const noexcept
101 {
102 auto r = dynamic_cast<const Local_Data_Ref*>(&rhs);
103 if (r)
104 return slot_ == r->slot_;
105 return false;
106 }
107
hash() const108 size_t List_Expr_Base::hash() const noexcept
109 {
110 std::hash<const char*> hasher;
111 size_t result = hasher("List");
112 for (size_t i = 0; i < size_; ++i)
113 boost::hash_combine(result, array_[i]->hash());
114 return result;
115 }
hash_eq(const Operation & rhs) const116 bool List_Expr_Base::hash_eq(const Operation& rhs) const noexcept
117 {
118 auto r = dynamic_cast<const List_Expr_Base*>(&rhs);
119 if (r) {
120 if (size_ != r->size_) return false;
121 for (size_t i = 0; i < size_; ++i) {
122 if (!array_[i]->hash_eq(*r->array_[i]))
123 return false;
124 }
125 return true;
126 }
127 return false;
128 }
129
130 } // namespace curv
131