// for clangd #include "../include/types.hpp" #include #include namespace info::type { std::optional AbstractType::InContext(const std::unordered_map& context) { auto type_iter = context.find(typeclass_graph_.GetVertex(graph_id_).name); if (type_iter != context.end()) { return type_iter->second; } return std::nullopt; } bool AbstractType::Same(const AbstractType& type) const { return graph_id_ == type.graph_id_; } bool AbstractType::Require(const AbstractType& type) const { // TODO: cache DependenciesSet return typeclass_graph_.GetDependenciesSet(graph_id_).count(type.graph_id_) != 0 || graph_id_ == type.graph_id_; } bool AbstractType::DeduceContext(const AbstractType& actual_type, std::unordered_map>& context, TypeManager& type_manager) const { return typeclass_graph_.GetDependenciesSet(graph_id_).count(actual_type.graph_id_) != 0 || graph_id_ == actual_type.graph_id_; } std::optional AbstractType::GetFieldType(const std::string&, const std::unordered_set&) const { return std::nullopt; } // std::optional DefinedType::InContext(const std::unordered_map& context) { std::optional maybe_type_replacement = type_manager_->GetAnyValue(type_)->InContext(context); if (maybe_type_replacement.has_value()) { type_ = maybe_type_replacement.value(); } return std::nullopt; } bool DefinedType::Same(const DefinedType& type) const { return type_id_ == type.type_id_ && type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_)); } bool DefinedType::Require(const DefinedType& type) const { return type_id_ == type.type_id_ && type_manager_->GetAnyValue(type_)->Require(*type_manager_->GetAnyValue(type.type_)); } bool DefinedType::DeduceContext(const DefinedType& actual_type, std::unordered_map>& context, TypeManager& type_manager) const { return type_id_ == actual_type.type_id_ && type_manager_->GetAnyValue(type_)->DeduceContext(*type_manager_->GetAnyValue(actual_type.type_), context, type_manager); } std::optional DefinedType::GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const { if (class_modifier_ == utils::ClassModifier::Struct || type_namespaces.count(type_id_) != 0) { return type_manager_->GetAnyValue(type_)->GetFieldType(name, type_namespaces); } return std::nullopt; } std::string DefinedType::ToString() const { return "Defined " + std::to_string(type_id_) + " ( " + type_manager_->GetAnyValue(type_)->ToString() + " )"; } // std::optional TupleType::InContext(const std::unordered_map& context) { for (size_t i = 0; i < fields_.size(); ++i) { std::optional maybe_field_replacement = type_manager_->GetAnyValue(fields_[i].second)->InContext(context); if (maybe_field_replacement.has_value()) { fields_[i].second = maybe_field_replacement.value(); } } return std::nullopt; } bool TupleType::Same(const TupleType& type) const { if (fields_.size() != type.fields_.size()) { return false; } for (size_t i = 0; i < fields_.size(); ++i) { if (!type_manager_->GetAnyValue(fields_[i].second)->Same(*type_manager_->GetAnyValue(type.fields_[i].second))) { return false; } } return true; } bool TupleType::Require(const TupleType& type) const { if (fields_.size() != type.fields_.size()) { return false; } for (size_t i = 0; i < fields_.size(); ++i) { if (!type_manager_->GetAnyValue(fields_[i].second)->Require(*type_manager_->GetAnyValue(type.fields_[i].second))) { return false; } } return true; } bool TupleType::DeduceContext(const TupleType& actual_type, std::unordered_map>& context, TypeManager& type_manager) const { if (fields_.size() != actual_type.fields_.size()) { return false; } for (size_t i = 0; i < fields_.size(); ++i) { if (!type_manager_->GetAnyValue(fields_[i].second)->DeduceContext(*type_manager_->GetAnyValue(actual_type.fields_[i].second), context, type_manager)) { return false; } } return true; } std::optional TupleType::GetFieldType(const std::string& name, const std::unordered_set&) const { for (size_t i = 0; i < fields_.size(); ++i) { // TODO: optimize?? if (fields_[i].first.has_value() && fields_[i].first.value() == name) { return fields_[i].second; } } return std::nullopt; } std::string TupleType::ToString() const { std::string result; result += "("; for (auto& field : fields_) { result += " & "; result += type_manager_->GetAnyValue(field.second)->ToString(); } result += ")"; return result; } // std::optional VariantType::InContext(const std::unordered_map& context) { for (size_t i = 0; i < constructors_.size(); ++i) { if (constructors_[i].second.has_value()) { constructors_[i].second.value().InContext(context); } } return std::nullopt; } bool VariantType::Same(const VariantType& type) const { if (constructors_.size() != type.constructors_.size()) { return false; } for (size_t i = 0; i < constructors_.size(); ++i) { if (constructors_[i].first != type.constructors_[i].first) { // TODO: decide return false; } if (constructors_[i].second.has_value() != type.constructors_[i].second.has_value()) { return false; } if (constructors_[i].second.has_value()) { if (!constructors_[i].second.value().Same(type.constructors_[i].second.value())) { return false; } } } return true; } bool VariantType::Require(const VariantType& type) const { if (constructors_.size() != type.constructors_.size()) { return false; } for (size_t i = 0; i < constructors_.size(); ++i) { if (constructors_[i].first != type.constructors_[i].first) { // TODO: decide return false; } if (constructors_[i].second.has_value() != type.constructors_[i].second.has_value()) { return false; } if (constructors_[i].second.has_value()) { if (!constructors_[i].second.value().Require(type.constructors_[i].second.value())) { return false; } } } return true; } bool VariantType::DeduceContext(const VariantType& actual_type, std::unordered_map>& context, TypeManager& type_manager) const { if (constructors_.size() != actual_type.constructors_.size()) { return false; } for (size_t i = 0; i < constructors_.size(); ++i) { if (constructors_[i].first != actual_type.constructors_[i].first) { // TODO: decide return false; } if (constructors_[i].second.has_value() != actual_type.constructors_[i].second.has_value()) { return false; } if (constructors_[i].second.has_value()) { if (!constructors_[i].second.value().DeduceContext(actual_type.constructors_[i].second.value(), context, type_manager)) { return false; } } } return true; } std::optional VariantType::GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const { if (current_constructor_.has_value() && constructors_.at(current_constructor_.value()).second.has_value()) { return constructors_[current_constructor_.value()].second.value().GetFieldType(name, type_namespaces); } return std::nullopt; } std::string VariantType::ToString() const { std::string result; result += "("; for (auto& constructor : constructors_) { result += "& "; result += constructor.first; if (constructor.second.has_value()) { result += " " + constructor.second.value().ToString(); } } result += ")"; return result; } // std::optional OptionalType::InContext(const std::unordered_map& context) { std::optional maybe_type_replacement = type_manager_->GetAnyValue(type_)->InContext(context); if (maybe_type_replacement.has_value()) { type_ = maybe_type_replacement.value(); } return std::nullopt; } bool OptionalType::Same(const OptionalType& type) const { return type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_)); } bool OptionalType::Require(const OptionalType& type) const { return type_manager_->GetAnyValue(type_)->Require(*type_manager_->GetAnyValue(type.type_)); } bool OptionalType::DeduceContext(const OptionalType& actual_type, std::unordered_map>& context, TypeManager& type_manager) const { return type_manager_->GetAnyValue(type_)->DeduceContext(*type_manager_->GetAnyValue(actual_type.type_), context, type_manager); } std::optional OptionalType::GetFieldType(const std::string&, const std::unordered_set&) const { return std::nullopt; } std::string OptionalType::ToString() const { return "Optional " + type_manager_->GetAnyValue(type_)->ToString(); } // std::optional ReferenceToType::InContext(const std::unordered_map& context) { std::optional maybe_type_replacement = type_manager_->GetAnyValue(type_)->InContext(context); if (maybe_type_replacement.has_value()) { type_ = maybe_type_replacement.value(); } return std::nullopt; } bool ReferenceToType::Same(const ReferenceToType& type) const { return references_ == type.references_ && type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_)); } bool ReferenceToType::Require(const ReferenceToType& type) const { return references_ == type.references_ && type_manager_->GetAnyValue(type_)->Require(*type_manager_->GetAnyValue(type.type_)); } bool ReferenceToType::DeduceContext(const ReferenceToType& actual_type, std::unordered_map>& context, TypeManager& type_manager) const { return references_ == actual_type.references_ && type_manager_->GetAnyValue(type_)->DeduceContext(*type_manager_->GetAnyValue(actual_type.type_), context, type_manager); } std::optional ReferenceToType::GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const { return type_manager_->GetAnyValue(type_)->GetFieldType(name, type_namespaces); } std::string ReferenceToType::ToString() const { std::string result; for (auto& reference : references_) { switch (reference) { case utils::ReferenceModifier::Dereference: result += '~'; break; case utils::ReferenceModifier::Reference: result += '^'; break; case utils::ReferenceModifier::UniqueReference: result += '@'; break; } } result += type_manager_->GetAnyValue(type_)->ToString(); return result; } // std::optional FunctionType::InContext(const std::unordered_map& context) { for (size_t i = 0; i < argument_types_.size(); ++i) { std::optional maybe_argument_type_replacement = type_manager_->GetAnyValue(argument_types_[i])->InContext(context); if (maybe_argument_type_replacement.has_value()) { argument_types_[i] = maybe_argument_type_replacement.value(); } } return std::nullopt; } bool FunctionType::Same(const FunctionType& type) const { if (argument_types_.size() != type.argument_types_.size()) { return false; } for (size_t i = 0; i < argument_types_.size(); ++i) { if (!type_manager_->GetAnyValue(argument_types_[i])->Same(*type_manager_->GetAnyValue(type.argument_types_[i]))) { return false; } } return true; } bool FunctionType::Require(const FunctionType& type) const { if (argument_types_.size() != type.argument_types_.size()) { return false; } for (size_t i = 0; i < argument_types_.size(); ++i) { if (!type_manager_->GetAnyValue(argument_types_[i])->Require(*type_manager_->GetAnyValue(type.argument_types_[i]))) { return false; } } return true; } bool FunctionType::DeduceContext(const FunctionType& actual_type, std::unordered_map>& context, TypeManager& type_manager) const { if (argument_types_.size() != actual_type.argument_types_.size()) { return false; } for (size_t i = 0; i < argument_types_.size(); ++i) { if (!type_manager_->GetAnyValue(argument_types_[i])->DeduceContext(*type_manager_->GetAnyValue(actual_type.argument_types_[i]), context, type_manager)) { return false; } } return true; } std::optional FunctionType::GetFieldType(const std::string&, const std::unordered_set&) const { return std::nullopt; } std::string FunctionType::ToString() const { std::string result; result += "("; bool is_first_argument = true; for (auto& argument_type : argument_types_) { if (is_first_argument) { is_first_argument = false; } else { result += " -> "; } result += type_manager_->GetAnyValue(argument_type)->ToString(); } result += " -> " + type_manager_->GetAnyValue(return_type_)->ToString() + ")"; return result; } // std::optional ArrayType::InContext(const std::unordered_map& context) { std::optional maybe_elements_type_replacement = type_manager_->GetAnyValue(elements_type_)->InContext(context); if (maybe_elements_type_replacement.has_value()) { elements_type_ = maybe_elements_type_replacement.value(); } return std::nullopt; } bool ArrayType::Same(const ArrayType& type) const { return size_ == type.size_ && type_manager_->GetAnyValue(elements_type_)->Same(*type_manager_->GetAnyValue(type.elements_type_)); } bool ArrayType::Require(const ArrayType& type) const { return size_ == type.size_ && type_manager_->GetAnyValue(elements_type_)->Require(*type_manager_->GetAnyValue(type.elements_type_)); } bool ArrayType::DeduceContext(const ArrayType& actual_type, std::unordered_map>& context, TypeManager& type_manager) const { return size_ == actual_type.size_ && type_manager_->GetAnyValue(elements_type_)->DeduceContext(*type_manager_->GetAnyValue(actual_type.elements_type_), context, type_manager); } std::optional ArrayType::GetFieldType(const std::string&, const std::unordered_set&) const { return std::nullopt; } std::string ArrayType::ToString() const { return "Array (" + std::to_string(size_) + ") " + type_manager_->GetAnyValue(elements_type_)->ToString(); } // std::optional Type::InContext(const std::unordered_map& context) { size_t this_index = type_.index(); switch (this_index) { case 0: return std::get(type_).InContext(context); case 1: return std::get(type_).InContext(context); case 2: return std::nullopt; case 3: return std::get(type_).InContext(context); case 4: return std::get(type_).InContext(context); case 5: return std::get(type_).InContext(context); case 6: return std::get(type_).InContext(context); case 7: return std::get(type_).InContext(context); case 8: return std::get(type_).InContext(context); default: // error break; } return std::nullopt; } bool Type::Same(const Type& type) const { size_t this_index = type_.index(); size_t type_index = type.type_.index(); if (this_index == type_index) { switch (this_index) { case 0: return std::get(type_).Same(std::get(type.type_)); case 1: return std::get(type_).Same(std::get(type.type_)); case 2: return std::get(type_) == std::get(type.type_); case 3: return std::get(type_).Same(std::get(type.type_)); case 4: return std::get(type_).Same(std::get(type.type_)); case 5: return std::get(type_).Same(std::get(type.type_)); case 6: return std::get(type_).Same(std::get(type.type_)); case 7: return std::get(type_).Same(std::get(type.type_)); case 8: return std::get(type_).Same(std::get(type.type_)); default: // error break; } } return false; } bool Type::Require(const Type& type) const { // TODO: check abstract type requirements for not abstract types size_t this_index = type_.index(); size_t type_index = type.type_.index(); if (this_index == type_index) { switch (this_index) { case 0: return std::get(type_).Require(std::get(type.type_)); case 1: return std::get(type_).Require(std::get(type.type_)); case 2: return std::get(type_) == std::get(type.type_); case 3: return std::get(type_).Require(std::get(type.type_)); case 4: return std::get(type_).Require(std::get(type.type_)); case 5: return std::get(type_).Require(std::get(type.type_)); case 6: return std::get(type_).Require(std::get(type.type_)); case 7: return std::get(type_).Require(std::get(type.type_)); case 8: return std::get(type_).Require(std::get(type.type_)); default: // error break; } } return false; } // TODO: check abstract type requirements for not abstract types bool Type::DeduceContext(const Type& actual_type, std::unordered_map>& context, TypeManager& type_manager) const { size_t this_index = type_.index(); size_t type_index = actual_type.type_.index(); if (this_index == 0) { std::string type_name = std::get(type_).GetName(); if (context.count(type_name) != 0) { // is abstract type context[type_name] = type_manager.AddAnyValue(Type(actual_type), utils::ValueType::Tmp); // TODO: choose value type ?? (or should be set later ??) } } error_handling::HandleGeneralError("Type::DeduceContext: not implemented"); if (this_index == type_index) { switch (this_index) { case 0: return std::get(type_).DeduceContext(std::get(actual_type.type_), context, type_manager); case 1: return std::get(type_).DeduceContext(std::get(actual_type.type_), context, type_manager); case 2: return std::get(type_) == std::get(actual_type.type_); case 3: return std::get(type_).DeduceContext(std::get(actual_type.type_), context, type_manager); case 4: return std::get(type_).DeduceContext(std::get(actual_type.type_), context, type_manager); case 5: return std::get(type_).DeduceContext(std::get(actual_type.type_), context, type_manager); case 6: return std::get(type_).DeduceContext(std::get(actual_type.type_), context, type_manager); case 7: return std::get(type_).DeduceContext(std::get(actual_type.type_), context, type_manager); case 8: return std::get(type_).DeduceContext(std::get(actual_type.type_), context, type_manager); default: // error break; } } return false; } std::optional Type::GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const { size_t index = type_.index(); switch (index) { case 0: return std::get(type_).GetFieldType(name, type_namespaces); case 1: return std::get(type_).GetFieldType(name, type_namespaces); case 2: return std::nullopt; case 3: return std::get(type_).GetFieldType(name, type_namespaces); case 4: return std::get(type_).GetFieldType(name, type_namespaces); case 5: return std::get(type_).GetFieldType(name, type_namespaces); case 6: return std::get(type_).GetFieldType(name, type_namespaces); case 7: return std::get(type_).GetFieldType(name, type_namespaces); case 8: return std::get(type_).GetFieldType(name, type_namespaces); default: // error break; } return std::nullopt; } std::string Type::GetTypeName() const { size_t index = type_.index(); switch (index) { case 0: return "AbstractType"; case 1: return "DefinedType"; case 2: return "Builtin"; case 3: return "TupleType"; case 4: return "VariantType"; case 5: return "ReferenceToType"; case 6: return "FunctionType"; case 7: return "ArrayType"; case 8: return "OptionalType"; default: // error break; } return ""; // ?? } std::string Type::ToString() const { size_t index = type_.index(); switch (index) { case 0: return std::get(type_).ToString(); case 1: return std::get(type_).ToString(); case 2: // ?? return ::info::type::ToString(std::get(type_)); case 3: return std::get(type_).ToString(); case 4: return std::get(type_).ToString(); case 5: return std::get(type_).ToString(); case 6: return std::get(type_).ToString(); case 7: return std::get(type_).ToString(); case 8: return std::get(type_).ToString(); default: // error break; } return ""; } } // namespace info::type