diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index 4dbc160..e9d656c 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -131,13 +131,15 @@ private: utils::IdType TypeInContext(utils::IdType type, const std::unordered_map& context); + void CheckPattern(Pattern& node, const BaseNode& base_node); + private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; info::TypeInfoContextManager& context_manager_; utils::IdType current_type_; std::optional returned_type_; - std::optional is_const_definition_; + std::optional is_const_definition_; bool is_in_statement_ = false; }; diff --git a/include/type_info_contexts.hpp b/include/type_info_contexts.hpp index 820a603..99faacb 100644 --- a/include/type_info_contexts.hpp +++ b/include/type_info_contexts.hpp @@ -11,12 +11,16 @@ namespace info { -// TODO: remember about typespointers +// TODO: remember about type pointers class TypeInfoContextManager { public: template - utils::IdType AddType(const T&& type) { - return type_manager_.AddType(std::forward(type)); + utils::IdType AddType(T&& type, utils::ValueType value_type) { + return type_manager_.AddType(std::forward(type), value_type); + } + + utils::IdType AddAnyType(type::Type&& type, utils::ValueType value_type) { + return type_manager_.AddType(std::move(type), value_type); } template @@ -28,6 +32,10 @@ public: return type_manager_.GetAnyType(type_id); } + utils::ValueType GetValueType(utils::IdType type_id) { + return type_manager_.GetValueType(type_id); + } + bool AddTypeRequirement(utils::IdType type, utils::IdType requrement) { return type_manager_.AddTypeRequirement(type, requrement); } @@ -36,6 +44,10 @@ public: return type_manager_.EqualTypes(first_type, second_type); } + utils::IdType ToModifiedType(utils::IdType type_id, utils::ValueType new_value_type) { + return AddAnyType(type::Type(*GetAnyType(type_id)), new_value_type); + } + type::TypeManager* GetTypeManager() { return &type_manager_; } @@ -56,10 +68,9 @@ public: contexts_.clear(); } - // TODO: variable modifiers - bool DefineVariable(const std::string& name, utils::IdType type_id, bool is_const) { + bool DefineVariable(const std::string& name, utils::IdType type_id) { // check in previous contexts ?? - return contexts_.back().DefineVariable(name, type_id, is_const); + return contexts_.back().DefineVariable(name, type_id); } bool DefineLocalAbstractType(const std::string& name, utils::IdType type_id) { @@ -80,14 +91,14 @@ public: return false; } - void EnterVariableContext(const std::string& name, - utils::IdType type_id, bool is_const) { // for variable namespaces, for loops - contexts_.push_back(false); + void EnterVariableContext(const std::string& name, utils::IdType type_id) { + // for variable namespaces, for loops + contexts_.emplace_back(); - DefineVariable(name, type_id, is_const); + DefineVariable(name, type_id); } - std::optional> GetVariableInfo(const std::string& name) { + std::optional GetVariableInfo(const std::string& name) { for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { auto maybe_type = contexts_[i].GetVariableInfo(name); if (maybe_type.has_value()) { @@ -110,13 +121,13 @@ public: private: class Context { public: - Context(bool hide_previous) : hide_previous_(hide_previous) {} + Context() = default; - bool DefineVariable(const std::string& name, utils::IdType type_id, bool is_const) { + bool DefineVariable(const std::string& name, utils::IdType type_id) { if (variables_.count(name) > 0) { return false; } - variables_[name] = {type_id, is_const}; + variables_[name] = type_id; return true; } @@ -132,7 +143,7 @@ private: return variables_.erase(name); } - std::optional> GetVariableInfo(const std::string& name) { + std::optional GetVariableInfo(const std::string& name) { auto variable_iter = variables_.find(name); if (variable_iter == variables_.end()) { @@ -151,11 +162,8 @@ private: return local_abstract_type_iter->second; } - - bool IsFirst() { return hide_previous_; } private: - bool hide_previous_; - std::unordered_map> variables_; + std::unordered_map variables_; std::unordered_map local_abstract_types_; }; diff --git a/include/types.hpp b/include/types.hpp index 20f3e37..08cfb83 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -31,6 +31,9 @@ public: bool Same(const AbstractType& type) const; bool operator<(const AbstractType& type) const; bool operator>(const AbstractType& type) const; + + std::optional GetFieldType(const std::string& name) const; + private: utils::AbstractTypeModifier modifier_; std::string name_; @@ -50,6 +53,8 @@ public: bool operator<(const DefinedType& type) const; bool operator>(const DefinedType& type) const; + std::optional GetFieldType(const std::string& name) const; + utils::IdType GetTypeId() const { return type_id_; } @@ -86,6 +91,8 @@ public: bool operator<(const TupleType& type) const; bool operator>(const TupleType& type) const; + std::optional GetFieldType(const std::string& name) const; + const std::vector, utils::IdType>>& GetFields() const { return fields_; } @@ -100,21 +107,29 @@ class VariantType { public: VariantType() = default; VariantType(const std::optional& name, - const std::vector& constructors) - : name_(name), constructors_(constructors){} + const std::vector& constructors, + std::optional current_constructor) + : name_(name), constructors_(constructors), current_constructor_(current_constructor) {} std::optional InContext(const std::unordered_map& context); bool Same(const VariantType& type) const; bool operator<(const VariantType& type) const; bool operator>(const VariantType& type) const; + std::optional GetFieldType(const std::string& name) const; + const std::vector& GetConstructors() const { return constructors_; } + const void SetCurrentConstructor(size_t constructor) { + current_constructor_ = constructor; + } + private: std::optional name_; std::vector constructors_; + std::optional current_constructor_; }; class OptionalType { @@ -129,6 +144,8 @@ public: bool operator<(const OptionalType& type) const; bool operator>(const OptionalType& type) const; + std::optional GetFieldType(const std::string& name) const; + private: utils::IdType type_; TypeManager* type_manager_ = nullptr; @@ -147,6 +164,8 @@ public: bool operator<(const ReferenceToType& type) const; bool operator>(const ReferenceToType& type) const; + std::optional GetFieldType(const std::string& name) const; + private: std::vector references_; utils::IdType type_; @@ -168,6 +187,8 @@ public: bool operator<(const FunctionType& type) const; bool operator>(const FunctionType& type) const; + std::optional GetFieldType(const std::string& name) const; + private: std::vector argument_types_; utils::IdType return_type_; @@ -187,6 +208,8 @@ public: bool operator<(const ArrayType& type) const; bool operator>(const ArrayType& type) const; + std::optional GetFieldType(const std::string& name) const; + utils::IdType GetElementsType() { return elements_type_; } @@ -199,6 +222,8 @@ private: class Type { public: + Type() = default; + template explicit Type(T&& type) : type_(std::forward(type)) {} @@ -207,6 +232,8 @@ public: bool operator<(const Type& type) const; // TODO: rule exceptions bool operator>(const Type& type) const; + std::optional GetFieldType(const std::string& name) const; + private: std::variant type_; + ArrayType, + OptionalType> type_; }; class TypeManager { public: template - utils::IdType AddType(const T&& type); + utils::IdType AddType(T&& type, utils::ValueType value_type); + + utils::IdType AddAnyType(Type&& type, utils::ValueType value_type); template std::optional GetType(utils::IdType type_id); Type* GetAnyType(utils::IdType type_id); + utils::ValueType GetValueType(utils::IdType type_id); + bool AddTypeRequirement(utils::IdType type, utils::IdType requrement); bool EqualTypes(utils::IdType first_type, utils::IdType second_type); private: - std::vector types_; + std::vector> types_; }; } // namespace info::type diff --git a/include/utils.hpp b/include/utils.hpp index 5c87112..d1bb206 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -17,6 +18,18 @@ enum class AliasModifier { Alias = 0, Type = 1, Let = 2 }; enum class AbstractTypeModifier { Basic = 0, Abstract = 1 }; enum class FunctionTypeModifier { Function = 0, Operator = 1 }; +enum class ValueType { Const = 0, Var = 1, Tmp = 2 }; + +inline ValueType IsConstModifierToValueType(IsConstModifier modifier) { + switch (modifier) { + case IsConstModifier::Const: + return ValueType::Const; + case IsConstModifier::Var: + return ValueType::Var; + } + // unreachable +} + template class Storage { public: diff --git a/src/main.cpp b/src/main.cpp index 7224127..885ace7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,7 +31,7 @@ int main(int argc, char** argv) { // TODO, only test version parser::ParseTree parse_tree(source); if (!parse_tree.IsProperlyParsed()) { - error_handling::HandleParsingError("There are some parsing errors in file.", {0, 0}); + error_handling::HandleParsingError("There are some parsing errors in file.", {0, 0}, {0, 0}); } std::unique_ptr source_file = diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index e7c1627..1e84edf 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -17,7 +18,7 @@ void TypeCheckVisitor::Visit(SourceFile* node) { for (auto& statement : node->statements) { Visitor::Visit(statement); } - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); } // Namespaces, partitions ----------------- @@ -26,33 +27,34 @@ void TypeCheckVisitor::Visit(PartitionSources* node) { for (auto& statement : node->statements) { Visitor::Visit(statement); } - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(Partition* node) { Visit(&node->scope); - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(NamespaceSources* node) { for (auto& statement : node->statements) { Visitor::Visit(statement); } - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(Namespace* node) { // TODO: two var namespces for class: const and var if (node->modifier.has_value()) { - bool is_const = node->modifier.value() == utils::IsConstModifier::Const; + bool is_const = (node->modifier.value() == utils::IsConstModifier::Const); if (node->link_typeclass_id_.has_value()) { // TODO: think about typeclass std::vector requirements {node->link_typeclass_id_.value()}; - utils::IdType abstract_type = context_manager_.AddType(info::type::AbstractType(utils::AbstractTypeModifier::Abstract, node->type, requirements)); + utils::IdType abstract_type = context_manager_.AddType( + info::type::AbstractType(utils::AbstractTypeModifier::Abstract, node->type, requirements), + IsConstModifierToValueType(node->modifier.value())); - context_manager_.EnterVariableContext("self", - abstract_type, - is_const); // TODO: different name ?? + context_manager_.EnterVariableContext("self", // TODO: different name ?? + abstract_type); context_manager_.DefineLocalAbstractType(node->type, abstract_type); } else if (node->link_type_id_.has_value()) { Visitor::Visit(*namespace_visitor_.GetGlobalInfo()->GetTypeInfo(node->link_type_id_.value()).value().value); // handle error? @@ -60,8 +62,8 @@ void TypeCheckVisitor::Visit(Namespace* node) { // TODO: two var namespces for c context_manager_.EnterVariableContext( "self", // TODO: different name ?? context_manager_.AddType( - info::type::DefinedType(node->link_type_id_.value(), current_type_, context_manager_.GetTypeManager())), - is_const); + info::type::DefinedType(node->link_type_id_.value(), current_type_, context_manager_.GetTypeManager()), + IsConstModifierToValueType(node->modifier.value()))); } } else { if (node->link_typeclass_id_.has_value()) { // ?? @@ -75,7 +77,7 @@ void TypeCheckVisitor::Visit(Namespace* node) { // TODO: two var namespces for c namespace_visitor_.ExitNamespace(); context_manager_.ExitContext(); - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); } // Definitions ----------------- @@ -85,36 +87,44 @@ void TypeCheckVisitor::Visit(ImportStatement* node) {} // TODO // + TODO: let bindings for abstract types void TypeCheckVisitor::Visit(AliasDefinitionStatement* node) { - if (!is_in_statement_) { // do nothing if alias is not applied - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); - return; - } - - context_manager_.EnterContext(); - - for (auto& parameter : node->parameters) { - current_type_ = context_manager_.AddType(info::type::AbstractType(utils::AbstractTypeModifier::Abstract, - parameter, - /*TODO*/{})); - context_manager_.DefineLocalAbstractType(parameter, current_type_); - } - - Visit(node->value.get()); - - context_manager_.ExitContext(); + error_handling::HandleInternalError("Unimplemented", + "TypeCheckVisitor.AliasDefinitionStatement"); + // if (!is_in_statement_) { // do nothing if alias is not applied + // current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); + // return; + // } + // + // context_manager_.EnterContext(); + // + // for (auto& parameter : node->parameters) { + // current_type_ = context_manager_.AddType(info::type::AbstractType(utils::AbstractTypeModifier::Abstract, + // parameter, + // /*TODO*/{}), + // utils::ValueType::Tmp); + // context_manager_.DefineLocalAbstractType(parameter, current_type_); + // } + // + // Visit(node->value.get()); + // + // context_manager_.ExitContext(); } -// TODO: remove variable on move void TypeCheckVisitor::Visit(VariableDefinitionStatement* node) { + // TODO: remove variable on move is_in_statement_ = true; Visitor::Visit(node->value); // current_type from value automatically passed to name definitions - is_const_definition_ = (node->modifier == utils::IsConstModifier::Const); + if (node->assignment_modifier == utils::AssignmentModifier::Assign) { + current_type_ = context_manager_.ToModifiedType(current_type_, utils::ValueType::Tmp); + // TODO: make type tmp recursively ?? + } + + is_const_definition_ = node->modifier; Visitor::Visit(node->name); is_const_definition_ = std::nullopt; - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); is_in_statement_ = false; } @@ -123,7 +133,7 @@ void TypeCheckVisitor::Visit(FunctionDeclaration* node) { bool was_in_statement = is_in_statement_; is_in_statement_ = true; - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); if (!was_in_statement) { is_in_statement_ = false; @@ -152,7 +162,8 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { // TODO: add recursive typeclasses from typeclass tree current_type_ = context_manager_.AddType(info::type::AbstractType(utils::AbstractTypeModifier::Abstract, parameter.type, - requirements)); + requirements), + utils::ValueType::Tmp); if (!context_manager_.DefineLocalAbstractType(parameter.type, current_type_)) { error_handling::HandleTypecheckError("Can't define function parameter type: abstract type redefinition", node->base); } @@ -160,7 +171,8 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { for (size_t i = 0; i < node->definition->arguments.size(); ++i) { Visitor::Visit(*declaration.argument_types[i]); - if (!context_manager_.DefineVariable(node->definition->arguments[i].name, current_type_, true)) { // TODO: watch to reference + current_type_ = context_manager_.ToModifiedType(current_type_, utils::ValueType::Const); // TODO: var function arguments?? + if (!context_manager_.DefineVariable(node->definition->arguments[i].name, current_type_)) { // TODO: watch to reference error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition", node->base); } } @@ -175,7 +187,7 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { context_manager_.ExitContext(); - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); is_in_statement_ = false; } @@ -183,7 +195,7 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) { is_in_statement_ = true; - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); is_in_statement_ = false; } @@ -198,12 +210,13 @@ void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) { } // TODO: add recursive typeclasses from typeclass tree - current_type_ = context_manager_.AddType(info::type::AbstractType(node->modifier, node->type->type, requirements)); + current_type_ = context_manager_.AddType(info::type::AbstractType(node->modifier, node->type->type, requirements), + utils::ValueType::Tmp); if (!context_manager_.DefineLocalAbstractType(node->type->type, current_type_)) { error_handling::HandleTypecheckError("Can't define basic/bastract type: abstract type redefinition", node->base); } - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); is_in_statement_ = false; } @@ -211,7 +224,7 @@ void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) { void TypeCheckVisitor::Visit(TypeclassDefinitionStatement* node) { is_in_statement_ = true; - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); is_in_statement_ = false; } @@ -219,40 +232,30 @@ void TypeCheckVisitor::Visit(TypeclassDefinitionStatement* node) { // Definition parts void TypeCheckVisitor::Visit(FunctionDefinition* node) { - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(TypeDefinition* node) { - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(AnyAnnotatedType* node) { - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); } // Flow control ----------------- -// TODO <----- | current position | +void TypeCheckVisitor::Visit(TypeConstructorPatternParameter* node) {} // Handled in TypeConstructorPattern // TODO -void Visitor::Visit(TypeConstructorPatternParameter* node) {} // Handled in TypeConstructorPattern - -// TODO -void Visitor::Visit(TypeConstructorPattern* node) { - Visit(node->constructor.get()); - for (auto& parameter : node->parameters) { - Visit(¶meter); - } -} - -/* -void TypeCheckVisitor::Visit(TypeConstructor* node) { +void TypeCheckVisitor::Visit(TypeConstructorPattern* node) { // TODO: match named constructor if (!node->constructor->constructor_id_.has_value()) { - error_handling::HandleTypecheckError("Type constructor name not found", node->base); + error_handling::HandleTypecheckError("Type constructor pattern name not found", node->base); } if (!node->constructor->type_id_.has_value()) { - error_handling::HandleInternalError("Type constructor without type", "TypeCheckVisitor.TypeConstructor"); + error_handling::HandleInternalError("Type constructor pattern without type", + "TypeCheckVisitor.TypeConstructorPattern"); } utils::IdType constructor_id = node->constructor->constructor_id_.value(); @@ -269,7 +272,8 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { namespace_visitor_.GetGlobalInfo()->GetTypeInfo(type_id); if (!maybe_type_info.has_value()) { // TODO - error_handling::HandleInternalError("Implemented only for AnyType", "TypeCheckVisitor.LambdaFunction"); + error_handling::HandleInternalError("Implemented only for AnyType", + "TypeCheckVisitor.TypeConstructorPattern"); } const info::definition::AnyType& type_info = maybe_type_info.value(); @@ -279,74 +283,55 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { TupleType* constructor_fields = constructor_info.constructor_tuple_node.value(); if (constructor_fields->entities.size() != node->parameters.size()) { - error_handling::HandleTypecheckError("Type constructor parameters count mismatch", node->base); + error_handling::HandleTypecheckError("Type constructor pattern parameters count mismatch", node->base); } for (size_t i = 0; i < node->parameters.size(); ++i) { - // TODO: remove variable on move - if (node->parameters[i].name.has_value()) { + if (node->parameters[i].name.has_value()) { // TODO: needed?? if (!constructor_fields->entities[i].first.has_value() || constructor_fields->entities[i].first.value().name != node->parameters[i].name.value().name) { - error_handling::HandleTypecheckError("Type constructor: name of parameter and name in constructor don't match each other", node->base); + error_handling::HandleTypecheckError("Type constructor pattern: name of parameter and name in constructor don't match each other", node->base); } } else { if (constructor_fields->entities[i].first.has_value()) { - error_handling::HandleTypecheckError("Type constructor: unnamed pprameter corresponds named field", node->base); + error_handling::HandleTypecheckError("Type constructor pattern: unnamed parameter corresponds named field", node->base); } } Visitor::Visit(constructor_fields->entities[i].second.get()); - utils::IdType parameter_type = TypeInContext(current_type_, context); + current_type_ = TypeInContext(current_type_, context); - Visitor::Visit(node->parameters[i].value); - - context_manager_.EqualTypes(TypeInContext(parameter_type, context), current_type_); + CheckPattern(node->parameters[i].value, node->base); // current_type_ passed to parameter } } else { if (node->parameters.size() > 0) { - error_handling::HandleTypecheckError("Parameters for untyped type constructor", node->base); + error_handling::HandleTypecheckError("Parameters for untyped type constructor pattern", node->base); } } Visitor::Visit(*type_info.value); current_type_ = TypeInContext(current_type_, context); + current_type_ = context_manager_.ToModifiedType(current_type_, utils::ValueType::Tmp); } -*/ void TypeCheckVisitor::Visit(MatchCase* node) { // value type passed as current_type_ - is_const_definition_ = true; // TODO: or var?? + is_const_definition_ = utils::IsConstModifier::Const; // TODO: or var?? Visitor::Visit(node->value); - utils::IdType value_type = current_type_; + current_type_ = context_manager_.ToModifiedType(current_type_, utils::ValueType::Tmp); - switch (node->value.index()) { - case 0: - context_manager_.DefineVariable(std::get>(node->value)->name, - current_type_, - is_const_definition_.value()); - break; - case 1: - Visitor::Visit(*std::get>(node->value)); - if (context_manager_.EqualTypes(current_type_, value_type)) { - error_handling::HandleTypecheckError("Literal and value have different types", node->base); - } - break; - case 2: - Visit(std::get>(node->value).get()); - break; - default: - // error - break; - } + CheckPattern(node->value, node->base); is_const_definition_ = std::nullopt; if (node->condition.has_value()) { Visitor::Visit(node->condition.value()); } - if (!context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool), current_type_)) { + if (!context_manager_.EqualTypes( + context_manager_.AddType(info::type::InternalType::Bool, utils::ValueType::Tmp), + current_type_)) { error_handling::HandleTypecheckError("Match case condition is not bool expression", node->base); } @@ -356,7 +341,7 @@ void TypeCheckVisitor::Visit(MatchCase* node) { // current_type_ from statement is current_type_ for MatchCase } -void TypeCheckVisitor::Visit(Match* node) { +void TypeCheckVisitor::Visit(Match* node) { // TODO: move value to match // TODO: types can be different in block statement utils::IdType type; @@ -367,7 +352,10 @@ void TypeCheckVisitor::Visit(Match* node) { for (size_t i = 0; i < node->matches.size(); ++i) { current_type_ = value_type; + + context_manager_.EnterContext(); Visit(&node->matches[i]); + context_manager_.ExitContext(); if (!node->matches[i].statement.has_value()) { continue; @@ -384,7 +372,7 @@ void TypeCheckVisitor::Visit(Match* node) { } if (!is_type_found) { - type = context_manager_.AddType(info::type::InternalType::Unit); + type = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); } current_type_ = type; @@ -396,11 +384,13 @@ void TypeCheckVisitor::Visit(Condition* node) { for (size_t i = 0; i < node->conditions.size(); ++i) { Visitor::Visit(node->conditions[i]); - if (!context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool), current_type_)) { + if (!context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool, utils::ValueType::Tmp), current_type_)) { error_handling::HandleTypecheckError("Condition statement condition is not bool expression", node->base); } + context_manager_.EnterContext(); Visitor::Visit(node->statements[i]); + context_manager_.ExitContext(); if (i == 0) { type = current_type_; } else { @@ -411,39 +401,48 @@ void TypeCheckVisitor::Visit(Condition* node) { } if (node->statements.size() > node->conditions.size()) { + context_manager_.EnterContext(); Visitor::Visit(node->statements[node->conditions.size()]); + context_manager_.ExitContext(); if (!context_manager_.EqualTypes(type, current_type_)) { error_handling::HandleTypecheckError("Condition statement else have different type from other cases", node->base); } current_type_ = type; } else { current_type_ = context_manager_.AddType( - info::type::OptionalType(type, context_manager_.GetTypeManager())); + info::type::OptionalType(type, context_manager_.GetTypeManager()), + utils::ValueType::Tmp); // ?? } } void TypeCheckVisitor::Visit(DoWhileLoop* node) { Visitor::Visit(node->condition); - if (!context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool), current_type_)) { + if (!context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool, utils::ValueType::Tmp), current_type_)) { error_handling::HandleTypecheckError("Do while loop statement condition is not bool expression", node->base); } + context_manager_.EnterContext(); Visitor::Visit(node->statement); + context_manager_.ExitContext(); current_type_ = context_manager_.AddType( - info::type::ArrayType(0, current_type_, context_manager_.GetTypeManager())); + info::type::ArrayType(0, current_type_, context_manager_.GetTypeManager()), + utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(WhileLoop* node) { Visitor::Visit(node->condition); - if (!context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool), current_type_)) { + if (!context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool, utils::ValueType::Tmp), current_type_)) { error_handling::HandleTypecheckError("While loop statement condition is not bool expression", node->base); } + context_manager_.EnterContext(); Visitor::Visit(node->statement); + context_manager_.ExitContext(); current_type_ = context_manager_.AddType( - info::type::ArrayType(0, current_type_, context_manager_.GetTypeManager())); + info::type::ArrayType(0, current_type_, context_manager_.GetTypeManager()), + utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(ForLoop* node) { @@ -454,22 +453,32 @@ void TypeCheckVisitor::Visit(ForLoop* node) { error_handling::HandleTypecheckError("For loop interval type mismatch", node->base); } - current_type_ = context_manager_.AddType(maybe_interval_type.value()->GetElementsType()); - is_const_definition_ = (node->modifier == utils::IsConstModifier::Const); + context_manager_.EnterContext(); + + current_type_ = context_manager_.AddType(maybe_interval_type.value()->GetElementsType(), + utils::IsConstModifierToValueType(node->variable_modifier)); + + is_const_definition_ = node->variable_modifier; Visitor::Visit(node->variable); // type passed to variable definition throught current_type_ is_const_definition_ = std::nullopt; Visitor::Visit(node->statement); + context_manager_.ExitContext(); + current_type_ = context_manager_.AddType( - info::type::ArrayType(0, current_type_, context_manager_.GetTypeManager())); + info::type::ArrayType(0, current_type_, context_manager_.GetTypeManager()), + utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(LoopLoop* node) { + context_manager_.EnterContext(); Visitor::Visit(node->statement); + context_manager_.ExitContext(); current_type_ = context_manager_.AddType( - info::type::ArrayType(0, current_type_, context_manager_.GetTypeManager())); + info::type::ArrayType(0, current_type_, context_manager_.GetTypeManager()), + utils::ValueType::Tmp); } // Statements, expressions, blocks, etc. ----------------- @@ -480,6 +489,7 @@ void TypeCheckVisitor::Visit(Block* node) { bool is_type_found = false; + context_manager_.EnterContext(); for (auto& statement : node->statements) { returned_type_ = std::nullopt; Visitor::Visit(statement); @@ -494,9 +504,10 @@ void TypeCheckVisitor::Visit(Block* node) { } } } + context_manager_.EnterContext(); if (!is_type_found) { - type = context_manager_.AddType(info::type::InternalType::Unit); + type = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); } current_type_ = type; @@ -508,7 +519,7 @@ void TypeCheckVisitor::Visit(ScopedStatement* node) { } void TypeCheckVisitor::Visit(LoopControlExpression& node) { // enum - current_type_ = context_manager_.AddType(info::type::InternalType::Unit); + current_type_ = context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp); } // Operators @@ -595,12 +606,13 @@ void TypeCheckVisitor::Visit(ReferenceExpression* node) { Visit(node->expression.get()); current_type_ = context_manager_.AddType( - info::type::ReferenceToType(node->references, current_type_, context_manager_.GetTypeManager())); + info::type::ReferenceToType(node->references, current_type_, context_manager_.GetTypeManager()), + context_manager_.GetValueType(current_type_)); // ?? } void TypeCheckVisitor::Visit(AccessExpression* node) { Visitor::Visit(node->id); - if (!context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Int), current_type_)) { + if (!context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Int, utils::ValueType::Tmp), current_type_)) { error_handling::HandleTypecheckError("Access index has wrong type (not Int)", node->base); } @@ -652,11 +664,18 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { "TypeCheckVisitor.FunctionCallExpresssion"); } - + // TODO: better decision ?? std::optional maybe_const_function_id = maybe_type_info.value().parent_namespace->const_namespaces.at(maybe_type_info->type.type).functions[node->name.name]; - // TODO: better decision ?? - if (/*is var expression*/) { + utils::ValueType expression_value_type = context_manager_.GetValueType(current_type_); + + if (expression_value_type == utils::ValueType::Tmp) { + error_handling::HandleInternalError("Expression value type is ValueType::Type", + "TypeCheckVisitor.FunctionCallExpression"); + } + + if (expression_value_type == utils::ValueType::Var || expression_value_type == utils::ValueType::Tmp) { + // TODO: choose expression value types maybe_function_id = maybe_type_info.value().parent_namespace->var_namespaces.at(maybe_type_info->type.type).functions[node->name.name]; } @@ -742,7 +761,8 @@ void TypeCheckVisitor::Visit(TupleExpression* node) { } current_type_ = context_manager_.AddType( - info::type::TupleType(std::nullopt, fields, context_manager_.GetTypeManager())); + info::type::TupleType(std::nullopt, fields, context_manager_.GetTypeManager()), + utils::ValueType::Tmp); } // ?? @@ -758,7 +778,8 @@ void TypeCheckVisitor::Visit(VariantExpression* node) { } - current_type_ = context_manager_.AddType(info::type::VariantType(std::nullopt, constructors)); + current_type_ = context_manager_.AddType(info::type::VariantType(std::nullopt, constructors, -1), + utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(ReturnExpression* node) { @@ -766,7 +787,7 @@ void TypeCheckVisitor::Visit(ReturnExpression* node) { returned_type_ = current_type_; } -void Visitor::Visit(TypeConstructorParameter* node) {} // Handeled in TypeConstructor visit +void TypeCheckVisitor::Visit(TypeConstructorParameter* node) {} // Handeled in TypeConstructor visit void TypeCheckVisitor::Visit(TypeConstructor* node) { if (!node->constructor->constructor_id_.has_value()) { @@ -791,7 +812,7 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { namespace_visitor_.GetGlobalInfo()->GetTypeInfo(type_id); if (!maybe_type_info.has_value()) { // TODO - error_handling::HandleInternalError("Implemented only for AnyType", "TypeCheckVisitor.LambdaFunction"); + error_handling::HandleInternalError("Implemented only for AnyType", "TypeCheckVisitor.TypeConstructor"); } const info::definition::AnyType& type_info = maybe_type_info.value(); @@ -813,7 +834,7 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { } } else { if (constructor_fields->entities[i].first.has_value()) { - error_handling::HandleTypecheckError("Type constructor: unnamed pprameter corresponds named field", node->base); + error_handling::HandleTypecheckError("Type constructor: unnamed parameter corresponds named field", node->base); } } @@ -822,7 +843,9 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { Visitor::Visit(node->parameters[i].value); - context_manager_.EqualTypes(TypeInContext(parameter_type, context), current_type_); + if (!context_manager_.EqualTypes(parameter_type, current_type_)) { + error_handling::HandleTypecheckError("Type constructor: wrong parameter type", node->base); + } } } else { @@ -832,6 +855,14 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { } Visitor::Visit(*type_info.value); + + std::optional maybe_variant_type = + context_manager_.GetType(current_type_); + + if (maybe_type_info.has_value()) { + maybe_variant_type.value()->SetCurrentConstructor(constructor_info.order); + } + current_type_ = TypeInContext(current_type_, context); } @@ -859,27 +890,42 @@ void TypeCheckVisitor::Visit(ArrayExpression* node) { } current_type_ = context_manager_.AddType( - info::type::ArrayType(node->elements.size(), elements_type, context_manager_.GetTypeManager())); + info::type::ArrayType(node->elements.size(), elements_type, context_manager_.GetTypeManager()), + utils::ValueType::Tmp); } // Name -// TODO void TypeCheckVisitor::Visit(NameExpression* node) { // TODO: move, etc. if (node->names.size() == 0) { error_handling::HandleInternalError("Name expression with zero names", "TypeCheckVisitor.NameExpression"); } - auto maybe_variable_info = context_manager_.GetVariableInfo(node->names[0].name); + auto maybe_variable_type = context_manager_.GetVariableInfo(node->names[0].name); - if (!maybe_variable_info.has_value()) { + if (!maybe_variable_type.has_value()) { error_handling::HandleTypecheckError("Variable not found", node->names[0].base); } - // TODO: get variable field + current_type_ = maybe_variable_type.value(); - return ; + if (node->names.size() == 1) { + return; + } + + utils::ValueType variable_value_type = context_manager_.GetValueType(current_type_); + + for (size_t i = 1; i < node->names.size(); ++i) { + std::optional maybe_type_value = context_manager_.GetAnyType(current_type_)->GetFieldType(node->names[i].name); + if (!maybe_type_value.has_value()) { + error_handling::HandleTypecheckError("Variable field not found", node->names[i].base); + } + + current_type_ = maybe_type_value.value(); + } + + current_type_ = context_manager_.ToModifiedType(current_type_, variable_value_type); } void TypeCheckVisitor::Visit(TupleName* node) { @@ -899,8 +945,24 @@ void TypeCheckVisitor::Visit(TupleName* node) { if (maybe_type_value.value()->GetFields().size() != node->names.size()) { error_handling::HandleTypecheckError("Mismatched field count in tuple variable definition", node->base); } + + if (!is_const_definition_.has_value()) { + error_handling::HandleInternalError("No value in is_const_definition_", "TypeCheckVisitor.TupleName"); + } + + utils::ValueType value_type = context_manager_.GetValueType(type); + if (value_type == utils::ValueType::Const + && is_const_definition_.value() == utils::IsConstModifier::Var) { + error_handling::HandleTypecheckError("TupleName: value type expression not match from variable definition modifier", node->base); + } + for (size_t i = 0; i < node->names.size(); ++i) { current_type_ = maybe_type_value.value()->GetFields()[i].second; + + if (value_type == utils::ValueType::Tmp) { // TODO: ?? + current_type_ = context_manager_.ToModifiedType(current_type_, utils::ValueType::Tmp); + } + Visitor::Visit(node->names[i]); } @@ -925,14 +987,30 @@ void TypeCheckVisitor::Visit(VariantName* node) { error_handling::HandleTypecheckError("Mismatched variant count in variant variable definition", node->base); } + if (!is_const_definition_.has_value()) { + error_handling::HandleInternalError("No value in is_const_definition_", "TypeCheckVisitor.VariantName"); + } + + utils::ValueType value_type = context_manager_.GetValueType(type); + if (value_type == utils::ValueType::Const + && is_const_definition_.value() == utils::IsConstModifier::Var) { + error_handling::HandleTypecheckError("VariantName: value type of type and value type are diifferent", node->base); + } + for (size_t i = 0; i < node->names.size(); ++i) { if (maybe_type_value.value()->GetConstructors()[i].GetFields().size() == 0) { current_type_ = context_manager_.AddType( - info::type::OptionalType(context_manager_.AddType(info::type::InternalType::Unit), context_manager_.GetTypeManager())); + info::type::OptionalType(context_manager_.AddType(info::type::InternalType::Unit, utils::ValueType::Tmp), context_manager_.GetTypeManager()), + utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? } else { - info::type::TupleType constructor_type = maybe_type_value.value()->GetConstructors()[i]; + info::type::TupleType constructor_type_value = maybe_type_value.value()->GetConstructors()[i]; + + utils::IdType constructor_type = + context_manager_.AddType(std::move(constructor_type_value), + utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? current_type_ = context_manager_.AddType( - info::type::OptionalType(context_manager_.AddType(std::move(constructor_type)), context_manager_.GetTypeManager())); + info::type::OptionalType(constructor_type, context_manager_.GetTypeManager()), + utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? } Visitor::Visit(node->names[i]); @@ -948,10 +1026,21 @@ void TypeCheckVisitor::Visit(AnnotatedName* node) { error_handling::HandleInternalError("No value in is_const_definition_", "TypeCheckVisitor.AnnotatedName"); } - context_manager_.DefineVariable(node->name, type, is_const_definition_.value()); + utils::ValueType value_type = context_manager_.GetValueType(type); + if (value_type == utils::ValueType::Const + && is_const_definition_.value() == utils::IsConstModifier::Var) { + error_handling::HandleTypecheckError("TupleName: value type expression not match from variable definition modifier", node->base); + } + + type = context_manager_.ToModifiedType(type, utils::IsConstModifierToValueType(is_const_definition_.value())); + if (!context_manager_.DefineVariable(node->name, type)) { + error_handling::HandleTypecheckError("Variable name already present in context", node->base); + } if (node->type.has_value()) { Visitor::Visit(node->type.value()); - context_manager_.EqualTypes(type, current_type_); + if (!context_manager_.EqualTypes(type, current_type_)) { // TODO ?? + error_handling::HandleTypecheckError("Wrong type annotation in annotated name", node->base); + } } } @@ -971,7 +1060,8 @@ void TypeCheckVisitor::Visit(FunctionType* node) { argument_types.pop_back(); current_type_ = context_manager_.AddType( - info::type::FunctionType(argument_types, return_type, context_manager_.GetTypeManager())); + info::type::FunctionType(argument_types, return_type, context_manager_.GetTypeManager()), + utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(TupleType* node) { @@ -984,7 +1074,8 @@ void TypeCheckVisitor::Visit(TupleType* node) { } current_type_ = context_manager_.AddType( - info::type::TupleType(node->type, fields, context_manager_.GetTypeManager())); + info::type::TupleType(node->type, fields, context_manager_.GetTypeManager()), + utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(VariantType* node) { @@ -1007,7 +1098,8 @@ void TypeCheckVisitor::Visit(VariantType* node) { } } - current_type_ = context_manager_.AddType(info::type::VariantType(node->type, constructors)); + current_type_ = context_manager_.AddType(info::type::VariantType(node->type, constructors, -1), + utils::ValueType::Tmp); } // TODO handle local abstract types, abstract types, aliases, etc. @@ -1032,7 +1124,8 @@ void TypeCheckVisitor::Visit(TypeExpression* node) { if (node->array_size.has_value()) { current_type_ = context_manager_.AddType( - info::type::ArrayType(node->array_size.value(), current_type_, context_manager_.GetTypeManager())); + info::type::ArrayType(node->array_size.value(), current_type_, context_manager_.GetTypeManager()), + utils::ValueType::Tmp); } } @@ -1040,13 +1133,13 @@ void TypeCheckVisitor::Visit(ExtendedScopedAnyType* node) { Visitor::Visit(node->type); current_type_ = context_manager_.AddType( - info::type::ReferenceToType(node->references, current_type_, context_manager_.GetTypeManager())); + info::type::ReferenceToType(node->references, current_type_, context_manager_.GetTypeManager()), + utils::ValueType::Tmp); } // Typeclass -void Visitor::Visit(ParametrizedTypeclass* node) { // TODO ?? - Visit(&node->typeclass); +void TypeCheckVisitor::Visit(ParametrizedTypeclass* node) { // TODO ?? for (auto& parameter : node->parameters) { Visit(parameter.get()); } @@ -1059,19 +1152,19 @@ void TypeCheckVisitor::Visit(ParametrizedType* node) {} // Handled in TypeExpres // Identifiers, constants, etc. ----------------- void TypeCheckVisitor::Visit(FloatNumberLiteral* node) { - current_type_ = context_manager_.AddType(info::type::InternalType::Float); + current_type_ = context_manager_.AddType(info::type::InternalType::Float, utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(NumberLiteral* node) { - current_type_ = context_manager_.AddType(info::type::InternalType::Int); + current_type_ = context_manager_.AddType(info::type::InternalType::Int, utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(StringLiteral* node) { - current_type_ = context_manager_.AddType(info::type::InternalType::String); + current_type_ = context_manager_.AddType(info::type::InternalType::String, utils::ValueType::Tmp); } void TypeCheckVisitor::Visit(CharLiteral* node) { - current_type_ = context_manager_.AddType(info::type::InternalType::Char); + current_type_ = context_manager_.AddType(info::type::InternalType::Char, utils::ValueType::Tmp); } // @@ -1118,7 +1211,30 @@ utils::IdType TypeCheckVisitor::TypeInContext(utils::IdType type, const std::unordered_map& context) { info::type::Type type_in_context = info::type::Type(context_manager_.GetAnyType(type)); type_in_context.InContext(context); - return context_manager_.AddType(std::move(type_in_context)); + return context_manager_.AddType(std::move(type_in_context), utils::ValueType::Tmp); +} + +void TypeCheckVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { // <-> ScopedPattern + utils::IdType value_type = current_type_; + + switch (node.index()) { + case 0: + context_manager_.DefineVariable(std::get>(node)->name, + value_type); + break; + case 1: + Visitor::Visit(*std::get>(node)); + if (context_manager_.EqualTypes(current_type_, value_type)) { // TODO: better solution ?? + error_handling::HandleTypecheckError("Literal and value have different types", base_node); + } + break; + case 2: + Visit(std::get>(node).get()); + break; + default: + // error + break; + } } } // namespace interpreter diff --git a/src/types.cpp b/src/types.cpp index 6536a04..ddd1b67 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -30,6 +30,10 @@ bool AbstractType::operator>(const AbstractType& type) const { return type < *this; } +std::optional AbstractType::GetFieldType(const std::string& name) const { + return std::nullopt; +} + // std::optional DefinedType::InContext(const std::unordered_map& context) { @@ -56,6 +60,10 @@ bool DefinedType::operator>(const DefinedType& type) const { return type < *this; } +std::optional DefinedType::GetFieldType(const std::string& name) const { + return type_manager_->GetAnyType(type_)->GetFieldType(name); +} + // std::optional TupleType::InContext(const std::unordered_map& context) { @@ -102,6 +110,15 @@ bool TupleType::operator>(const TupleType& type) const { return type < *this; } +std::optional TupleType::GetFieldType(const std::string& name) 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::optional VariantType::InContext(const std::unordered_map& context) { @@ -144,6 +161,13 @@ bool VariantType::operator>(const VariantType& type) const { return type < *this; } +std::optional VariantType::GetFieldType(const std::string& name) const { + if (current_constructor_.has_value()) { + return constructors_.at(current_constructor_.value()).GetFieldType(name); + } + return std::nullopt; +} + // std::optional OptionalType::InContext(const std::unordered_map& context) { @@ -168,6 +192,10 @@ bool OptionalType::operator>(const OptionalType& type) const { return type < *this; } +std::optional OptionalType::GetFieldType(const std::string& name) const { + return std::nullopt; +} + // std::optional ReferenceToType::InContext(const std::unordered_map& context) { @@ -192,6 +220,10 @@ bool ReferenceToType::operator>(const ReferenceToType& type) const { return type < *this; } +std::optional ReferenceToType::GetFieldType(const std::string& name) const { + return type_manager_->GetAnyType(type_)->GetFieldType(name); +} + // std::optional FunctionType::InContext(const std::unordered_map& context) { @@ -239,6 +271,10 @@ bool FunctionType::operator>(const FunctionType& type) const { return type < *this; } +std::optional FunctionType::GetFieldType(const std::string& name) const { + return std::nullopt; +} + // std::optional ArrayType::InContext(const std::unordered_map& context) { @@ -264,6 +300,10 @@ bool ArrayType::operator>(const ArrayType& type) const { return type < *this; } +std::optional ArrayType::GetFieldType(const std::string& name) const { + return std::nullopt; +} + // std::optional Type::InContext(const std::unordered_map& context) { @@ -286,6 +326,8 @@ std::optional Type::InContext(const std::unordered_map(type_).InContext(context); case 7: return std::get(type_).InContext(context); + case 8: + return std::get(type_).InContext(context); default: // error break; @@ -316,6 +358,8 @@ bool Type::Same(const Type& type) const { 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; @@ -347,6 +391,8 @@ bool Type::operator<(const Type& type) const { return std::get(type_) < std::get(type.type_); case 7: return std::get(type_) < std::get(type.type_); + case 8: + return std::get(type_) < std::get(type.type_); default: // error break; @@ -360,24 +406,63 @@ bool Type::operator>(const Type& type) const { return type < *this; } +std::optional Type::GetFieldType(const std::string& name) const { + size_t index = type_.index(); + + switch (index) { + case 0: + return std::get(type_).GetFieldType(name); + case 1: + return std::get(type_).GetFieldType(name); + case 2: + return std::nullopt; + case 3: + return std::get(type_).GetFieldType(name); + case 4: + return std::get(type_).GetFieldType(name); + case 5: + return std::get(type_).GetFieldType(name); + case 6: + return std::get(type_).GetFieldType(name); + case 7: + return std::get(type_).GetFieldType(name); + case 8: + return std::get(type_).GetFieldType(name); + default: + // error + break; + } + + return std::nullopt; +} + // template -utils::IdType TypeManager::AddType(const T&& type) { - types_.emplace_back(std::forward(type)); +utils::IdType TypeManager::AddType(T&& type, utils::ValueType value_type) { + types_.emplace_back({std::forward(type), value_type}); + return types_.size() - 1; +} + +utils::IdType TypeManager::AddAnyType(Type&& type, utils::ValueType value_type) { + types_.push_back({std::move(type), value_type}); return types_.size() - 1; } template std::optional TypeManager::GetType(utils::IdType type_id) { - if (!std::holds_alternative(types_.at(type_id))) { + if (!std::holds_alternative(types_.at(type_id).second)) { return std::nullopt; } - return &std::get(types_.at(type_id)); + return &std::get(types_.at(type_id).second); } Type* TypeManager::GetAnyType(utils::IdType type_id) { - return &types_.at(type_id); + return &types_.at(type_id).first; +} + +utils::ValueType TypeManager::GetValueType(utils::IdType type_id) { + return types_.at(type_id).second; } bool TypeManager::EqualTypes(utils::IdType first_type, utils::IdType second_type) {