7#include <llvm/Support/raw_ostream.h>
44 [[nodiscard]]
auto as_type() const& -> const ty::Type& {
48 [[nodiscard]]
auto as_expr() const& -> const ast::Expr* {
return expr; }
54 [[nodiscard]]
auto name() const ->
string {
59 return expr->describe();
63 return this->
type == other.type &&
static_cast<bool>(this->
expr) ==
static_cast<bool>(other.expr) &&
64 ((this->
expr ==
nullptr) || this->
expr->equals_by_hash(*other.expr));
70 vector<GenericKey> m_keys;
71 vector<GenericValue> m_values;
72 vector<ty::Generic*> m_generic_type_fallbacks;
76 Substitutions(vector<GenericKey> keys,
const vector<unique_ptr<ty::Generic>>& generic_type_fallbacks,
78 : m_keys{move(keys)} {
79 for (
const auto& i : generic_type_fallbacks)
80 m_generic_type_fallbacks.emplace_back(i.get());
81 for ([[maybe_unused]]
const auto& i : m_keys)
82 m_values.emplace_back();
84 if (parent !=
nullptr) {
85 for (
auto [k, v] : llvm::zip(parent->m_keys, parent->m_values)) {
87 m_values.push_back(v);
89 for (
auto* f : parent->m_generic_type_fallbacks)
90 m_generic_type_fallbacks.push_back(f);
93 Substitutions(vector<GenericKey> keys, vector<ty::Generic*> generic_type_fallbacks,
95 : m_keys{move(keys)}, m_generic_type_fallbacks{move(generic_type_fallbacks)} {
96 for ([[maybe_unused]]
const auto& i : m_keys)
97 m_values.emplace_back();
99 if (parent !=
nullptr) {
100 for (
auto [k, v] : llvm::zip(parent->m_keys, parent->m_values)) {
102 m_values.push_back(v);
104 for (
auto* f : parent->m_generic_type_fallbacks)
105 m_generic_type_fallbacks.push_back(f);
109 [[nodiscard]]
auto empty() const ->
bool {
return m_values.empty(); }
110 [[nodiscard]]
auto size() const ->
size_t {
return m_values.size(); }
120 YUME_ASSERT(ptr !=
nullptr,
"Mapped value must not be null");
125 YUME_ASSERT(ptr !=
nullptr,
"Mapped value must not be null");
129 [[nodiscard]]
auto find_type(string_view generic_name)
const -> optional<ty::Type> {
138 YUME_ASSERT(
mapping->holds_type(),
"A generic type key must correspond to a generic type mapping");
143 [[nodiscard]]
auto type_mappings() const -> std::map<
string, ty::Type>;
148 m_keys.emplace_back(move(key));
149 return m_values.emplace_back();
152 void dump(llvm::raw_ostream& os)
const {
154 for (
const auto& [k, v] : llvm::zip(m_keys, m_values)) {
157 os << k.name <<
"=" << v.name();
162 vector<const GenericKey*> keys{};
163 keys.reserve(m_keys.size());
164 for (
const auto& k : m_keys)
170 vector<const GenericValue*> values{};
171 values.reserve(m_values.size());
172 for (
const auto& m : m_values)
173 values.push_back(&m);
178 vector<GenericValue*> values{};
179 values.reserve(m_values.size());
180 for (
auto& m : m_values)
181 values.push_back(&m);
193 auto other_keys = other.all_keys();
195 auto other_vals = other.all_values();
197 return std::ranges::equal(this_keys, other_keys, [](
auto* a,
auto* b) {
return *a == *b; }) &&
198 std::ranges::equal(this_vals, other_vals, [](
auto* a,
auto* b) {
return *a == *b; });
203template <>
struct std::hash<
yume::Substitutions> {
206 for (
const auto* k : s.all_keys()) {
210 for (
const auto* v : s.all_values()) {
212 if (v->type.has_value()) {
218 if (v->expr !=
nullptr)
An unsubstituted generic type variable, usually something like T.
A "qualified" type, with a non-stackable qualifier, i.e. mut.
static void hash_combine(uint64_t &seed, const T &v)
auto holds_expr() const -> bool
auto holds_type() const -> bool
auto operator<=>(const GenericKey &other) const noexcept=default
GenericKey(string_view name, nonnull< ast::Type * > type)
GenericKey(string_view name)
nullable< ast::Type * > expr_type
auto operator==(const GenericKey &other) const noexcept -> bool=default
GenericValue(nonnull< ast::Expr * > expr)
auto holds_expr() const -> bool
auto as_expr() const &-> const ast::Expr *
optional< ty::Type > type
auto as_type() const &-> const ty::Type &
auto unsubstituted_primary() const -> bool
GenericValue(ty::Type type)
auto operator==(const GenericValue &other) const noexcept -> bool
auto name() const -> string
auto unassigned() const -> bool
auto unassigned_or_unsubstituted() const -> bool
auto holds_type() const -> bool
nullable< ast::Expr * > expr
void associate(const GenericKey &key, GenericValue value)
auto all_values() const -> vector< const GenericValue * >
Substitutions(vector< GenericKey > keys, const vector< unique_ptr< ty::Generic > > &generic_type_fallbacks, nullable< Substitutions * > parent=nullptr)
Substitutions(vector< GenericKey > keys, vector< ty::Generic * > generic_type_fallbacks, nullable< Substitutions * > parent=nullptr)
auto mapping_ref(const GenericKey &generic) -> GenericValue &
auto get_generic_fallback(string_view generic_name) const -> ty::Generic *
void dump(llvm::raw_ostream &os) const
auto fully_substituted() const -> bool
auto find_type(string_view generic_name) const -> optional< ty::Type >
auto size() const -> size_t
auto all_values() -> vector< GenericValue * >
auto append_new_association(GenericKey key) -> GenericValue &
auto operator==(const Substitutions &other) const noexcept -> bool
auto mapping_ref_or_null(const GenericKey &generic) -> nullable< GenericValue * >
auto mapping_ref(const GenericKey &generic) const -> const GenericValue &
auto type_mappings() const -> std::map< string, ty::Type >
auto all_keys() const -> vector< const GenericKey * >
auto empty() const -> bool
#define YUME_ASSERT(assertion, message)