diff --git a/include/builtin_methods.hpp b/include/builtin_methods.hpp new file mode 100644 index 0000000..0d0cfa7 --- /dev/null +++ b/include/builtin_methods.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include + +// for clangd +#include "types.hpp" +#include "utils.hpp" + +// TODO + +namespace info { + +struct BuiltinFunction { +public: + BuiltinFunction(const std::vector& argument_types, utils::IdType return_type) + : argument_types(argument_types), return_type(return_type) {} + + static std::optional FindMethod(const std::string& name, info::type::TypeManager& type_manager) { + return std::nullopt; + } + + static std::optional FindStaticMethod(const std::string& name, info::type::TypeManager& type_manager) { + return std::nullopt; + } + +public: + std::vector argument_types; + utils::IdType return_type; +}; + +} // namespace info diff --git a/include/definitions.hpp b/include/definitions.hpp index 8a28352..aa1ffd0 100644 --- a/include/definitions.hpp +++ b/include/definitions.hpp @@ -17,6 +17,8 @@ namespace interpreter { namespace info::definition { +struct Namespace; + struct TypeUsage { interpreter::tokens::TypeExpression* node; }; @@ -42,6 +44,8 @@ struct AnyType { Parameter type; std::vector parameters; interpreter::tokens::AnyType* value; + + Namespace* parent_namespace = nullptr; }; struct Type { @@ -52,6 +56,7 @@ struct Constructor { std::string name; size_t order; utils::IdType type_id; + std::optional constructor_tuple_node; }; struct FunctionDeclaration { @@ -90,7 +95,7 @@ struct Namespace { std::unordered_map namespaces; std::unordered_map variable_namespaces; - Namespace* parent_namespace = nullptr;; + Namespace* parent_namespace = nullptr; std::optional modifier; // modifier => variable namespace std::string type_name; diff --git a/include/global_info.hpp b/include/global_info.hpp index f57cd2b..1b669b5 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -6,6 +6,7 @@ // for clangd #include "definitions.hpp" +#include "interpreter_tree.hpp" #include "utils.hpp" namespace info { @@ -82,6 +83,10 @@ public: const std::vector& GetCurrentPath() { return current_path_; } + + definition::Namespace* GetCurrentNamespace() { + return namespace_stack_.back(); + } private: NamespaceVisitor(GlobalInfo& global_info) : global_info_(global_info), namespace_stack_({&global_info.global_namespace_}) {} @@ -104,23 +109,31 @@ public: } // remember about vector realloc - definition::Function* GetFunctionInfo(utils::IdType id) { - return &functions_[id]; + const definition::Function& GetFunctionInfo(utils::IdType id) { + return functions_.at(id); + } + + template + const std::optional& GetTypeInfo(utils::IdType id) { + if (!std::holds_alternative(types_.at(id).type)) { + return std::nullopt; + } + return std::get(types_[id].type); } // remember about vector realloc - definition::Type* GetTypeInfo(utils::IdType id) { - return &types_[id]; + const definition::Type& GetAnyTypeInfo(utils::IdType id) { + return types_.at(id); } // remember about vector realloc - definition::Typeclass* GetTypeclassInfo(utils::IdType id) { - return &typeclasses_[id]; + const definition::Typeclass& GetTypeclassInfo(utils::IdType id) { + return typeclasses_.at(id); } // remember about vector realloc - definition::Constructor* GetConstructorInfo(utils::IdType id) { - return &constructors_[id]; + const definition::Constructor& GetConstructorInfo(utils::IdType id) { + return constructors_.at(id); } private: diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp index 206e930..74041a2 100644 --- a/include/interpreter_tree.hpp +++ b/include/interpreter_tree.hpp @@ -231,7 +231,6 @@ struct ParametrizedTypeclass; // Typeclass & Type struct ParametrizedType; -// TypeSubExpression -> ParametrizedType // diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index beff08f..4dbc160 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -1,6 +1,7 @@ #pragma once // for clangd +#include "interpreter_tree.hpp" #include "type_info_contexts.hpp" #include "utils.hpp" #include "visitor.hpp" @@ -119,6 +120,17 @@ private: void Visit(CharLiteral* node) override; void Visit(UnitLiteral* node) override; + // + + void CollectTypeContext(const ParametrizedType& type, + std::unordered_map& context); + + void CollectTypeExpressionContext(const TypeExpression& type_expression, + std::unordered_map& context); + + utils::IdType TypeInContext(utils::IdType type, + const std::unordered_map& context); + private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; info::TypeInfoContextManager& context_manager_; diff --git a/include/types.hpp b/include/types.hpp index 14f85e4..445a508 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -48,9 +48,14 @@ public: bool operator<(const DefinedType& type) const; bool operator>(const DefinedType& type) const; - utils::IdType GetTypeId() { + utils::IdType GetTypeId() const { return type_id_; } + + utils::IdType GetType() const { + return type_; + } + private: utils::IdType type_id_; // in defined types utils::IdType type_; // in types manager, created using context types (if specific type) @@ -82,6 +87,7 @@ public: const std::vector, utils::IdType>>& GetFields() const { return fields_; } + private: std::optional name_; std::vector, utils::IdType>> fields_; @@ -103,6 +109,7 @@ public: const std::vector& GetConstructors() const { return constructors_; } + private: std::optional name_; std::vector constructors_; @@ -119,6 +126,7 @@ public: bool Same(const OptionalType& type) const; bool operator<(const OptionalType& type) const; bool operator>(const OptionalType& type) const; + private: utils::IdType type_; TypeManager* type_manager_ = nullptr; @@ -136,6 +144,7 @@ public: bool Same(const ReferenceToType& type) const; bool operator<(const ReferenceToType& type) const; bool operator>(const ReferenceToType& type) const; + private: std::vector references_; utils::IdType type_; @@ -156,6 +165,7 @@ public: bool Same(const FunctionType& type) const; bool operator<(const FunctionType& type) const; bool operator>(const FunctionType& type) const; + private: std::vector argument_types_; utils::IdType return_type_; @@ -178,6 +188,7 @@ public: utils::IdType GetElementsType() { return elements_type_; } + private: size_t size_; // = 0 for dynamic utils::IdType elements_type_; @@ -193,6 +204,7 @@ public: bool Same(const Type& type) const; bool operator<(const Type& type) const; // TODO: rule exceptions bool operator>(const Type& type) const; + private: std::variant types_; }; diff --git a/src/find_symbols_visitor.cpp b/src/find_symbols_visitor.cpp index dba268b..9e3da04 100644 --- a/src/find_symbols_visitor.cpp +++ b/src/find_symbols_visitor.cpp @@ -144,6 +144,7 @@ void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) { } any_type_info.value = &node->value; + any_type_info.parent_namespace = namespace_visitor_.GetCurrentNamespace(); std::string type = any_type_info.type.type; diff --git a/src/global_info.cpp b/src/global_info.cpp index 234735f..9fd0e6a 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -127,6 +127,8 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, definition::Type& moved_type_info = global_info_.types_.back(); + // TODO: constructors for tuple types, function types (??), array types (??), ... + if (std::holds_alternative(moved_type_info.type)) { definition::AnyType& any_type_info = std::get(moved_type_info.type); if (std::holds_alternative>(*any_type_info.value)) { @@ -142,7 +144,10 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, constructor_name = std::get(variant_type_info.constructors[i]); } else if (std::holds_alternative< std::unique_ptr>(variant_type_info.constructors[i])) { - auto maybe_constructor_name = std::get>(variant_type_info.constructors[i])->type; + constructor_info.constructor_tuple_node = + std::get>(variant_type_info.constructors[i]).get(); + + auto maybe_constructor_name = constructor_info.constructor_tuple_node.value()->type; if (maybe_constructor_name.has_value()) { constructor_name = maybe_constructor_name.value(); diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index 2774acf..775df69 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -53,6 +53,16 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check error_handling::HandleTypecheckError("Type or constructor not found"); } + if (node->constructor_id_.has_value()) { + utils::IdType constructor_type_id = namespace_visitor_.GetGlobalInfo()->GetConstructorInfo(node->constructor_id_.value()).type_id; + + if (node->type_id_.has_value() && node->type_id_.value() != constructor_type_id) { + error_handling::HandleTypecheckError("Contructor and type with same name have different types"); + } + + node->type_id_ = constructor_type_id; + } + if (node->type_id_.has_value()) { node->type.type_id_ = node->type_id_.value(); } diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index b1ee27a..43f173d 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -1,4 +1,6 @@ +#include #include +#include #include // for clangd @@ -114,13 +116,13 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { context_manager_.EnterContext(); - info::definition::Function* function_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_); + const info::definition::Function& function_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_); - if (!function_info->declaration.has_value()) { + if (!function_info.declaration.has_value()) { error_handling::HandleTypecheckError("Function defined, but not declared"); } - info::definition::FunctionDeclaration& declaration = function_info->declaration.value(); + const info::definition::FunctionDeclaration& declaration = function_info.declaration.value(); for (auto parameter : declaration.parameters) { std::vector requirements; @@ -137,14 +139,17 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { // Visit(node->definition.get()); // ?? for (size_t i = 0; i < node->definition->arguments.size(); ++i) { - current_type_ = ConstructAnyType(declaration.argument_types[i]); // TODO - if (!context_manager_.DefineVariable(node->definition->arguments[i].name, current_type_)) { + Visitor::Visit(*declaration.argument_types[i]); // TODO: ConstructAnyType + if (!context_manager_.DefineVariable(node->definition->arguments[i].name, current_type_, true)) { // TODO: watch to reference error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition"); } } + Visitor::Visit(*declaration.argument_types.back()); // TODO: ConstructAnyType + utils::IdType return_type = current_type_; + Visitor::Visit(node->value); - if (!context_manager_.EqualTypes(ConstructAnyType(declaration.argument_types.back()), current_type_)) { + if (!context_manager_.EqualTypes(return_type, current_type_)) { error_handling::HandleTypecheckError("Wrong function return type"); } @@ -370,31 +375,44 @@ void TypeCheckVisitor::Visit(LoopControlExpression& node) { // enum // Operators -// -------------------------- TODO -------------------------- +// TODO +// TODO: operator parameters (deduction?), etc. void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { - auto maybe_operator_id = namespace_visitor_.FindFunction({}, node->operator_name); + auto maybe_operator_id = namespace_visitor_.FindFunction(std::nullopt, node->operator_name); if (!maybe_operator_id.has_value()) { error_handling::HandleTypecheckError("Operator not found"); } - auto operator_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value()); + const info::definition::Function& operator_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value()); - if (operator_info->argument_count != 2) { + if (!operator_info.declaration.has_value()) { + error_handling::HandleTypecheckError("Operator declaration not found"); + } + + if (!operator_info.definition.has_value()) { // TODO: builtin + error_handling::HandleTypecheckError("Operator definition not found"); + } + + if (operator_info.argument_count != 2) { error_handling::HandleTypecheckError("Operator wrong argument count"); } - if (!operator_info->declaration.has_value() || !operator_info->definition.has_value()) { - error_handling::HandleTypecheckError("Operator declaration or definition not found"); + if (operator_info.declaration->parameters.size() > 0) { + error_handling::HandleTypecheckError("Operator with parameters"); } + Visitor::Visit(*operator_info.declaration.value().argument_types[0]); + utils::IdType left_expression_type = current_type_; + Visitor::Visit(node->left_expression); - context_manager_.AddTypeRequirement(current_type_, - ConstructAnyType(operator_info->declaration.value().argument_types[0])); // TODO + context_manager_.AddTypeRequirement(current_type_, left_expression_type); // TODO: ConstructAnyType + + Visitor::Visit(*operator_info.declaration.value().argument_types[1]); + utils::IdType right_expression_type = current_type_; Visitor::Visit(node->right_expression); - context_manager_.AddTypeRequirement(current_type_, - ConstructAnyType(operator_info->declaration.value().argument_types[1])); // TODO + context_manager_.AddTypeRequirement(current_type_, right_expression_type); // TODO: ConstructAnyType } @@ -406,19 +424,29 @@ void TypeCheckVisitor::Visit(UnaryOperatorExpression* node) { error_handling::HandleTypecheckError("Operator not found"); } - auto operator_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value()); + const info::definition::Function& operator_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value()); - if (operator_info->argument_count != 1) { + if (!operator_info.declaration.has_value()) { + error_handling::HandleTypecheckError("Operator declaration not found"); + } + + if (!operator_info.definition.has_value()) { // TODO: builtin + error_handling::HandleTypecheckError("Operator definition not found"); + } + + if (operator_info.argument_count != 1) { error_handling::HandleTypecheckError("Operator wrong argument count"); } - if (!operator_info->declaration.has_value() || !operator_info->definition.has_value()) { - error_handling::HandleTypecheckError("Operator declaration or definition not found"); + if (operator_info.declaration->parameters.size() > 0) { + error_handling::HandleTypecheckError("Operator with parameters"); } + Visitor::Visit(*operator_info.declaration.value().argument_types[0]); + utils::IdType expression_type = current_type_; + Visitor::Visit(node->expression); - context_manager_.AddTypeRequirement(current_type_, - ConstructAnyType(operator_info->declaration.value().argument_types[0])); // TODO + context_manager_.AddTypeRequirement(current_type_, expression_type); // TODO: ConstructAnyType } void TypeCheckVisitor::Visit(ReferenceExpression* node) { @@ -447,53 +475,128 @@ void TypeCheckVisitor::Visit(AccessExpression* node) { // Other Expressions // TODO +// TODO: builtin functions/methods +// TODO: alias types, abstract types, etc. void TypeCheckVisitor::Visit(FunctionCallExpression* node) { + std::optional maybe_function_id; + std::unordered_map context; + + // guaranteed, that name.size() > 0 + if (node->name.name[0] == '_') { // TODO: manage pointers to function + error_handling::HandleInternalError("Builtin functions/methods weren't implemented yet", "TypeCheckVisitor.FunctionCallExpresssion"); + } + if (node->prefix.has_value()) { if (std::holds_alternative>(node->prefix.value())) { Visitor::Visit(*std::get>(node->prefix.value())); - // TODO + + std::optional maybe_expression_type = context_manager_.GetType(current_type_); + + if (!maybe_expression_type.has_value()) { + error_handling::HandleTypecheckError("There is no non-builtin methods for not defined type"); + } + + utils::IdType type_id = maybe_expression_type.value()->GetTypeId(); + + const std::optional& maybe_type_info = namespace_visitor_.GetGlobalInfo()->GetTypeInfo(type_id); + + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("Functions/Methods implemented only for AnyType", "TypeCheckVisitor.FunctionCallExpresssion"); + } + + // TODO: better decision ?? + maybe_function_id = maybe_type_info.value().parent_namespace->variable_namespaces.at(maybe_type_info->type.type).functions[node->name.name]; } else if (std::holds_alternative>(node->prefix.value())) { - Visit(std::get>(node->prefix.value()).get()); - // TODO + TypeExpression* type_expression = std::get>(node->prefix.value()).get(); + + std::vector path; + path.reserve(type_expression->path.size() + 1); + + for (auto& path_type : type_expression->path) { + path.push_back(path_type.type); + } + path.push_back(type_expression->type.type); + + maybe_function_id = namespace_visitor_.FindFunction(path, node->name.name); + + CollectTypeExpressionContext(*std::get>(node->prefix.value()), context); } else { // error } - - current_type_ = /*...*/; // TODO + } else { + maybe_function_id = namespace_visitor_.FindFunction(std::nullopt, node->name.name); } - if (!std::holds_alternative(context_manager_.GetType(current_type_))) { - error_handling::HandleTypecheckError("Mismatched types in function call expression"); + if (!maybe_function_id.has_value()) { + error_handling::HandleTypecheckError("Can't find function"); // InterlnalError ?? } - info::type::FunctionType type_value = std::get(context_manager_.GetType(current_type_)); + std::optional maybe_function_declaration = + namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_function_id.value()).declaration; + if (!maybe_function_declaration.has_value()) { + error_handling::HandleTypecheckError("No function declaration found for function in function call expression"); + } + info::definition::FunctionDeclaration function_declaration = maybe_function_declaration.value(); + + // TODO: ?? + // // Visitor::Visit(function_declaration.node->type.get()); + // // + // // std::optional maybe_type_value = context_manager_.GetType(current_type_); + // // if (!maybe_type_value.has_value()) { + // // error_handling::HandleInternalError("Type of function is not FunctionType", "TypeCheckVisitor.FunctionCallExpresssion"); + // // } + // // + // // info::type::FunctionType* type_value = maybe_type_value.value(); + + // size_t argument_num = 0; size_t paramater_num = 0; + // TODO: parameters and arguments should be separated, parameters go first for (size_t i = 0; i < node->arguments.size(); ++i) { Visitor::Visit(node->arguments[i]); - if (std::holds_alternative(node->arguments[i])) { - // TODO + if (std::holds_alternative>(node->arguments[i])) { + if (function_declaration.parameters.size() <= paramater_num) { + error_handling::HandleTypecheckError("Mismatched parameter count in function call expression"); + } + + std::string parameter_name = function_declaration.parameters[paramater_num].type; + + if (context.count(parameter_name) != 0) { + error_handling::HandleInternalError("Local abstract types with same name in one context", "TypeCheckVisitor.FunctionCallExpresssion"); // TypecheckError ?? + } + + context[parameter_name] = current_type_; + ++paramater_num; } else if (std::holds_alternative(node->arguments[i])) { - if (type_value.argument_types.size() <= argument_num) { + if (function_declaration.argument_types.size() <= argument_num) { error_handling::HandleTypecheckError("Mismatched argument count in function call expression"); } - context_manager_.AddTypeRequirement(current_type_, type_value.argument_types[argument_num]); + // TODO: not full context, if arguments and parameters not sepoarated + + Visitor::Visit(*function_declaration.argument_types[argument_num]); + context_manager_.AddTypeRequirement(current_type_, TypeInContext(current_type_, context)); + ++argument_num; } else { // error } } - if (type_value.argument_types.size() != argument_num) { + if (function_declaration.parameters.size() != paramater_num) { + error_handling::HandleTypecheckError("Mismatched parameter count in function call expression"); + } + + if (function_declaration.argument_types.size() + 1 != argument_num) { error_handling::HandleTypecheckError("Mismatched argument count in function call expression"); } - current_type_ = type_value.return_type; + Visitor::Visit(*function_declaration.argument_types.back()); // add return type to info ?? + current_type_ = TypeInContext(current_type_, context); } void TypeCheckVisitor::Visit(TupleExpression* node) { @@ -530,41 +633,86 @@ void TypeCheckVisitor::Visit(ReturnExpression* node) { } // TODO -void Visitor::Visit(TypeConstructorParameter* node) { - if (node->name.has_value()) { - Visit(&node->name.value()); - } - Visit(node->value); -} +void Visitor::Visit(TypeConstructorParameter* node) {} // Handeled in TypeConstructor visit // TODO +// TODO: get argument types, etc. void TypeCheckVisitor::Visit(TypeConstructor* node) { // TODO: find constructor names, etc. // Visit(node->constructor.get()); if (!node->constructor->constructor_id_.has_value()) { error_handling::HandleTypecheckError("Type constructor name not found"); } - utils::IdType type = node->constructor->constructor_id_.value(); - - - // TODO: check if exist - info::definition::AnyType* type_info = &std::get( - namespace_visitor_.GetGlobalInfo()->GetTypeInfo(context_manager_.GetType(type).value()->GetTypeId())->type); - - for (size_t i = 0; i < node->parameters.size(); ++i) { - // TODO: remove variable on move - Visitor::Visit(node->parameters[i].value); - // TODO: type in context of parameters - // TODO: require ?? - context_manager_.EqualTypes(ConstructAnyType(type_info), current_type_); // TODO + if (!node->constructor->type_id_.has_value()) { + error_handling::HandleInternalError("Type constructor without type", "TypeCheckVisitor.TypeConstructor"); } - current_type_ = type; + utils::IdType constructor_id = node->constructor->constructor_id_.value(); + + info::definition::Constructor constructor_info = namespace_visitor_.GetGlobalInfo()->GetConstructorInfo(constructor_id); + + utils::IdType type_id = constructor_info.type_id; + + std::unordered_map context; + CollectTypeExpressionContext(*node->constructor, context); + + // TODO: handle alias types + const std::optional& maybe_type_info = + namespace_visitor_.GetGlobalInfo()->GetTypeInfo(type_id); + + if (!maybe_type_info.has_value()) { // TODO + error_handling::HandleInternalError("Implemented only for AnyType", "TypeCheckVisitor.LambdaFunction"); + } + + const info::definition::AnyType& type_info = maybe_type_info.value(); + + // TODO: check if exist + /*info::definition::AnyType* type_info = &std::get( + namespace_visitor_.GetGlobalInfo()->GetTypeInfo(context_manager_.GetType(type).value()->GetTypeId())->type);*/ + + if (constructor_info.constructor_tuple_node.has_value()) { + + 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"); + } + + for (size_t i = 0; i < node->parameters.size(); ++i) { + // TODO: remove variable on move + // TODO: check that has name <-> has name in constructor <- chck correctness + if (node->parameters[i].name.has_value()) { + 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"); + } + } else { + if (constructor_fields->entities[i].first.has_value()) { + error_handling::HandleTypecheckError("Type constructor: unnamed pprameter corresponds named field"); + } + } + + Visitor::Visit(constructor_fields->entities[i].second.get()); + utils::IdType parameter_type = TypeInContext(current_type_, context); + + Visitor::Visit(node->parameters[i].value); + + context_manager_.EqualTypes(TypeInContext(parameter_type, context), current_type_); + } + + } else { + if (node->parameters.size() > 0) { + error_handling::HandleTypecheckError("Parameters for untyped type constructor"); + } + } + + Visitor::Visit(*type_info.value); + current_type_ = TypeInContext(current_type_, context); } // TODO void TypeCheckVisitor::Visit(LambdaFunction* node) { - error_handling::HandleInternalError("Unimplemented", "TypeCheckVisitor.LambdaFunction"); + error_handling::HandleInternalError("Unimplemented (unsolved type deduction problems)", "TypeCheckVisitor.LambdaFunction"); } void TypeCheckVisitor::Visit(ArrayExpression* node) { @@ -615,6 +763,11 @@ void TypeCheckVisitor::Visit(NameExpression* node) { // TODO: ?? functions witho void TypeCheckVisitor::Visit(TupleName* node) { utils::IdType type = current_type_; + std::optional maybe_defined_type_value = context_manager_.GetType(type); + if (maybe_defined_type_value.has_value()) { + type = maybe_defined_type_value.value()->GetType(); + } + std::optional maybe_type_value = context_manager_.GetType(type); if (maybe_type_value.has_value()) { @@ -635,6 +788,11 @@ void TypeCheckVisitor::Visit(TupleName* node) { void TypeCheckVisitor::Visit(VariantName* node) { utils::IdType type = current_type_; + std::optional maybe_defined_type_value = context_manager_.GetType(type); + if (maybe_defined_type_value.has_value()) { + type = maybe_defined_type_value.value()->GetType(); + } + std::optional maybe_type_value = context_manager_.GetType(type); if (!maybe_type_value.has_value()) { @@ -731,13 +889,21 @@ void TypeCheckVisitor::Visit(VariantType* node) { current_type_ = context_manager_.AddType(info::type::VariantType(node->type, constructors)); } -// TODO, different for constructors +// TODO different for constructors +// TODO handle local abstract types, abstract types, aliases, etc. void TypeCheckVisitor::Visit(TypeExpression* node) { - // TODO: type in context of parameters - utils::IdType type = ConstructAnyType(/*...*/); // TODO + std::unordered_map context; + CollectTypeExpressionContext(*node, context); - current_type_ = context_manager_.AddType( - info::type::DefinedType(node->type_id_, type, context_manager_.GetTypeManager())); + const std::optional& maybe_type_info = + namespace_visitor_.GetGlobalInfo()->GetTypeInfo(node->type.type_id_.value()); + + if (!maybe_type_info.has_value()) { // TODO: add alias, abstract, ... types + error_handling::HandleInternalError("No any type found", "TypeCheckVisitor.TypeExpression"); + } + + Visitor::Visit(*maybe_type_info.value().value); + current_type_ = TypeInContext(current_type_, context); // TODO: check } void TypeCheckVisitor::Visit(ExtendedScopedAnyType* node) { @@ -759,20 +925,7 @@ void Visitor::Visit(ParametrizedTypeclass* node) { // Typeclass & Type ----------------- -void TypeCheckVisitor::Visit(ParametrizedType* node) { // TODO: always used in TypeExpression ?? - utils::IdType type; - - // type.paramaters.reserve(node->parameters.size()); - // for (auto& paramater : node->parameters) { - // Visitor::Visit(paramater); - // type.paramaters.push_back(current_type_); - // } - - // TODO: type in context of parameters - ConstructAnyType(/*any type from node*/); // TODO. ?? - - current_type_ = context_manager_.AddType(info::type::DefinedType(node->type_expression->type_id_, type, context_manager_.GetTypeManager())); -} +void TypeCheckVisitor::Visit(ParametrizedType* node) {} // Used in TypeExpression // Identifiers, constants, etc. ----------------- @@ -794,4 +947,51 @@ void TypeCheckVisitor::Visit(CharLiteral* node) { current_type_ = context_manager_.AddType(info::type::InternalType::Char); } +// + +void TypeCheckVisitor::CollectTypeContext(const ParametrizedType& type, + std::unordered_map& context) { + if (!type.type_id_.has_value()) { + return; + } + + const std::optional& maybe_type_info = + namespace_visitor_.GetGlobalInfo()->GetTypeInfo(type.type_id_.value()); + + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("Wrong type id", "TypeCheckVisitor.CollectTypeContext"); + } + + const info::definition::AnyType& type_info = maybe_type_info.value(); + + if (type_info.parameters.size() != type.parameters.size()) { + error_handling::HandleTypecheckError("Wrong type parameters count"); + } + + for (size_t i = 0; i < type.parameters.size(); ++i) { + Visit(type.parameters[i].get()); + + if (context.count(type_info.parameters[i].type) != 0) { + error_handling::HandleInternalError("Same parameter type names", "TypeCheckVisitor.CollectTypeContext"); + } + + context[type_info.parameters[i].type] = current_type_; + } +} + +void TypeCheckVisitor::CollectTypeExpressionContext(const TypeExpression& type_expression, + std::unordered_map& context) { + for (auto& path_type : type_expression.path) { + CollectTypeContext(path_type, context); + } + CollectTypeContext(type_expression.type, context); +} + +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)); +} + } // namespace interpreter