From 584bdfa54d7aaad8e4548b5d03f421077b002145 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Wed, 17 May 2023 15:08:18 +0300 Subject: [PATCH] type_check_visitor fixes, function_call_expression for typeclasses --- include/global_info.hpp | 19 ++- include/type_check_visitor.hpp | 16 ++- include/typeclass_graph.hpp | 6 +- src/global_info.cpp | 10 +- src/link_symbols_visitor.cpp | 6 + src/type_check_visitor.cpp | 208 +++++++++++++++++++++++---------- 6 files changed, 192 insertions(+), 73 deletions(-) diff --git a/include/global_info.hpp b/include/global_info.hpp index f2378be..6632566 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -205,6 +205,21 @@ public: return current_path_; } + // use only after LinkSymbolsVisitor + std::vector GetCurrentPathTypes() { + std::vector types; + + types.reserve(namespace_stack_.size()); + for (auto& namespace_id : namespace_stack_) { + definition::Namespace& namespace_info = global_info_.GetNamespaceInfo(namespace_id); + if (namespace_info.any_node.has_value() && namespace_info.any_node.value()->link_type_id_.has_value()) { + types.push_back(namespace_info.any_node.value()->link_type_id_.value()); + } + } + + return types; + } + utils::IdType GetCurrentNamespaceId() { return namespace_stack_.back(); } @@ -341,10 +356,10 @@ public: std::vector GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node); - std::unordered_map + std::unordered_map GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node); - std::vector> + std::vector> GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node); std::unordered_map* ChooseNamespaces( diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index b2f4b04..54a26cb 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -133,7 +133,7 @@ private: std::unordered_map& context); void CollectTypeExpressionContext(const TypeExpression& type_expression, - std::unordered_map& context); + std::unordered_map& context); utils::IdType TypeInContext(utils::IdType type, const std::unordered_map& context); @@ -143,14 +143,24 @@ private: std::optional FindSubExpressionMethodAndUpdate(FunctionCallExpression* node, - SubExpressionToken* expression_node, - const BaseNode& base_node); + SubExpressionToken* expression_node); std::optional FindTypeFunctionAndUpdate(FunctionCallExpression* node, TypeExpression* type_node, std::unordered_map& context); + std::optional + FindAbstractTypeTypeclassFunctionAndUpdate( + FunctionCallExpression* node, + info::type::AbstractType* abstract_type, + bool is_method); + + std::optional + FindDefinedTypeTypeclassFunctionAndUpdate( + FunctionCallExpression* node, + info::definition::AnyType* defined_type, + bool is_method); private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; info::GlobalInfo& global_info_; diff --git a/include/typeclass_graph.hpp b/include/typeclass_graph.hpp index 3533e75..e7614be 100644 --- a/include/typeclass_graph.hpp +++ b/include/typeclass_graph.hpp @@ -112,12 +112,12 @@ public: } // cache ?? - std::vector> GetTypeclassFunctions(utils::IdType id) { - std::vector> functions; + std::vector> GetTypeclassFunctions(utils::IdType id) { + std::vector> functions; functions.reserve(typeclasses_.at(id).functions.size()); for (auto& function : typeclasses_[id].functions) { - functions.push_back({function.first, function.second.modifier}); + functions.push_back({function.first, &function.second}); } return functions; diff --git a/src/global_info.cpp b/src/global_info.cpp index f6a4dbd..c90482b 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -476,10 +476,10 @@ std::vector return typeclasses_vector; } -std::unordered_map +std::unordered_map GlobalInfo::GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node) { - std::unordered_map functions; + std::unordered_map functions; for (auto& typeclass : node->typeclasses) { utils::IdType graph_id = typeclasses_[typeclass->typeclass_id_].graph_id_; @@ -492,12 +492,12 @@ std::unordered_map return functions; } -std::vector> +std::vector> GlobalInfo::GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node) { - std::unordered_map functions_set = GetAnnotatedTypeFunctionsMap(node); + std::unordered_map functions_set = GetAnnotatedTypeFunctionsMap(node); - std::vector> functions_vector; + std::vector> functions_vector; functions_vector.reserve(functions_vector.size()); for (auto& typeclass : functions_set) { functions_vector.push_back(typeclass); diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index 56c4ae1..0c0ab08 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -28,6 +28,12 @@ void LinkSymbolsVisitor::Visit(Namespace* node) { } if (maybe_typeclass.has_value()) { node->link_typeclass_id_ = maybe_typeclass.value(); + if (!namespace_visitor_.IsInGlobalNamespace()) { + // other type of error?? + error_handling::HandleParsingError("Can't use typeclass namespace in other namespace", + node->base.start_position, + node->base.end_position); + } } namespace_visitor_.EnterNamespace(node->type, node->modifier); diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 0589522..d1e9b3c 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -254,14 +254,19 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) { is_in_statement_ = true; - std::unordered_map required_functions = + // TODO: defined functions can be not redifined + std::unordered_map required_functions = global_info_.GetAnnotatedTypeFunctionsMap(node->definition->type.get()); std::string& type_name = node->definition->type->type; for (auto& function : required_functions) { // TODO: optimize + if (function.second->definition.has_value()) { // TODO: check + continue; + } + std::unordered_map* current_namespaces = - global_info_.ChooseNamespaces(function.second, namespace_visitor_.GetCurrentNamespace()); + global_info_.ChooseNamespaces(function.second->modifier, namespace_visitor_.GetCurrentNamespace()); auto& type_functions = global_info_.GetNamespaceInfo((*current_namespaces)[type_name]).functions; @@ -790,7 +795,6 @@ void TypeCheckVisitor::Visit(AccessExpression* node) { // Other Expressions // TODO: builtin functions / methods -// TODO: abstract types (check typeclass requirements) void TypeCheckVisitor::Visit(FunctionCallExpression* node) { std::optional maybe_function_declaration; @@ -807,8 +811,7 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { if (std::holds_alternative>(node->prefix.value())) { maybe_function_declaration = FindSubExpressionMethodAndUpdate( node, - std::get>(node->prefix.value()).get(), - node->base); + std::get>(node->prefix.value()).get()); } else if (std::holds_alternative>(node->prefix.value())) { maybe_function_declaration = FindTypeFunctionAndUpdate( node, @@ -819,8 +822,6 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { "TypeCheckVisitor.FunctionCallExpression"); } } else { - // TODO: static functions from parent namespaces' typeclasses - std::optional maybe_function_id; if (namespace_visitor_.GetCurrentNamespace()->modifier != utils::ClassInternalsModifier::Static) { @@ -844,17 +845,40 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { if (maybe_function_id.has_value() && global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.has_value()) { node->function_id_ = maybe_function_id.value(); - maybe_function_declaration = global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.value().node; } else { maybe_function_declaration = std::nullopt; } + + // try to find typeclass function in for parent namespaces (check definition ??) + if (!maybe_function_declaration.has_value()) { + // TODO: check + auto path_types = namespace_visitor_.GetCurrentPathTypes(); + if (!path_types.empty()) { + for (ssize_t i = (ssize_t)path_types.size() - 1; i >= 0; --i) { // optimize + auto maybe_type_info = global_info_.GetTypeInfo(path_types[i]); + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("typeclass functions / methods implemented only for AnyType", + "TypeCheckVisitor.FindTypeFunctionAndUpdate"); + } + + maybe_function_declaration = + FindDefinedTypeTypeclassFunctionAndUpdate(node, + maybe_type_info.value(), + false); + + if (maybe_function_declaration.has_value()) { + break; + } + } + } + } } // function declaration check if (!maybe_function_declaration.has_value()) { - error_handling::HandleTypecheckError("No function declaration found for function in function call expression", node->base); + error_handling::HandleTypecheckError("No function declaration found for function in call expression", node->base); } FunctionDeclaration* function_declaration = maybe_function_declaration.value(); @@ -1472,45 +1496,29 @@ void TypeCheckVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { // TODO: internal types ?? std::optional TypeCheckVisitor::FindSubExpressionMethodAndUpdate(FunctionCallExpression* node, - SubExpressionToken* expression_node, - const BaseNode& base_node) { - std::optional maybe_function_id; + SubExpressionToken* expression_node) { std::optional maybe_function_declaration; Visitor::Visit(*expression_node); utils::IdType expression_type = current_type_; - auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name); auto maybe_abstract_type_info = context_manager_.GetValue(expression_type); if (maybe_abstract_type_info.has_value()) { - if (!maybe_typeclass_graph_id.has_value()) { - error_handling::HandleTypecheckError("Typeclass function not found", base_node); - } - - info::type::AbstractType* abstract_type_info = maybe_abstract_type_info.value(); - - auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name, - maybe_typeclass_graph_id.value()); - if (!maybe_typeclass_function_info.has_value()) { - error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)", - "TypeCheckVisitor.FindSubExpressionMethodAndUpdate"); - } - if (abstract_type_info->HasTypeclass(maybe_typeclass_graph_id.value())) { - node->typeclass_graph_id_ = maybe_typeclass_graph_id; - maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; - } + maybe_function_declaration = FindAbstractTypeTypeclassFunctionAndUpdate(node, + maybe_abstract_type_info.value(), + true); } else { auto maybe_defined_type_info = context_manager_.GetValue(expression_type); if (!maybe_defined_type_info.has_value()) { - error_handling::HandleTypecheckError("There is no non-builtin methods for not defined type", base_node); + error_handling::HandleTypecheckError("There is no non-builtin methods for not defined type", node->base); } utils::IdType type_id = maybe_defined_type_info.value()->GetTypeId(); auto maybe_type_info = global_info_.GetTypeInfo(type_id); if (!maybe_type_info.has_value()) { - error_handling::HandleInternalError("Functions/Methods implemented only for AnyType", + error_handling::HandleInternalError("Functions / Methods implemented only for AnyType", "TypeCheckVisitor.FunctionCallExpresssion"); } info::definition::AnyType* type_info = maybe_type_info.value(); @@ -1519,13 +1527,14 @@ std::optional utils::ValueType expression_value_type = context_manager_.GetValueType(expression_type); + std::optional maybe_function_id; if (expression_value_type == utils::ValueType::Var || expression_value_type == utils::ValueType::Tmp) { // TODO: choose expression value types maybe_function_id = global_info_.GetNamespaceInfo(global_info_.GetNamespaceInfo(type_info->parent_namespace).var_namespaces.at(type_info->type.type)).functions[node->name]; } if (maybe_const_function_id.has_value() && maybe_function_id.has_value()) { // TODO: handle on link_types stage - error_handling::HandleTypecheckError("Redefinition of method: const & var", base_node); + error_handling::HandleTypecheckError("Redefinition of method: const & var", node->base); } if (!maybe_function_id.has_value()) { @@ -1538,19 +1547,10 @@ std::optional global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.value().node; } - if (!maybe_function_declaration.has_value() && maybe_typeclass_graph_id.has_value()) { - auto typeclasses = global_info_.GetAnnotatedTypeTypeclassesSet(type_info->type.node); - auto function_typeclass_iter = typeclasses.find(maybe_typeclass_graph_id.value()); - - if (function_typeclass_iter != typeclasses.end()) { - auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name, - maybe_typeclass_graph_id.value()); - if (!maybe_typeclass_function_info.has_value()) { - error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (definied type)", - "TypeCheckVisitor.FindSubExpressionMethodAndUpdate"); - } - maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; - } + if (!maybe_function_declaration.has_value()) { + maybe_function_declaration = FindDefinedTypeTypeclassFunctionAndUpdate(node, + type_info, + true); } } return maybe_function_declaration; @@ -1562,34 +1562,122 @@ std::optional TypeCheckVisitor::FindTypeFunctionAndUpdate(FunctionCallExpression* node, TypeExpression* type_node, std::unordered_map& context) { - std::optional maybe_function_id; std::optional maybe_function_declaration; if (type_node->array_size.has_value()) { error_handling::HandleTypecheckError("Can't call function from array type namespace", node->base); } - // std::optional maybe_local_abstract_type = - // context_manager_.GetLocalType(type_node->type.type); + std::optional maybe_local_abstract_type = context_manager_.GetLocalType(type_node->type.type); - std::vector path; - path.reserve(type_node->path.size() + 1); + if (maybe_local_abstract_type.has_value()) { + auto maybe_abstract_type_info = + context_manager_.GetValue(maybe_local_abstract_type.value()); - for (auto& path_type : type_node->path) { - path.push_back(path_type.type); - } - path.push_back(type_node->type.type); + if (!maybe_abstract_type_info.has_value()) { + error_handling::HandleInternalError("Local abstract type contains not abstract type", + "TypeCheckVisitor.FindTypeFunctionAndUpdate"); + } - maybe_function_id = namespace_visitor_.FindFunctionId(path, node->name); + maybe_function_declaration = FindAbstractTypeTypeclassFunctionAndUpdate(node, + maybe_abstract_type_info.value(), + false); + } else { + std::vector path; + path.reserve(type_node->path.size() + 1); - CollectTypeExpressionContext(*type_node, context); + for (auto& path_type : type_node->path) { + path.push_back(path_type.type); + } + path.push_back(type_node->type.type); - if (maybe_function_id.has_value()) { - node->function_id_ = maybe_function_id.value(); - maybe_function_declaration = - global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.value().node; + std::optional maybe_function_id = namespace_visitor_.FindFunctionId(path, node->name); + + CollectTypeExpressionContext(*type_node, context); + + if (maybe_function_id.has_value()) { + node->function_id_ = maybe_function_id.value(); + maybe_function_declaration = + global_info_.GetFunctionInfo(maybe_function_id.value()).declaration.value().node; + } + + if (!maybe_function_declaration.has_value() && type_node->type_id_.has_value()) { + auto maybe_type_info = global_info_.GetTypeInfo(type_node->type_id_.value()); + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("typeclass functions / methods implemented only for AnyType", + "TypeCheckVisitor.FindTypeFunctionAndUpdate"); + } + + maybe_function_declaration = FindDefinedTypeTypeclassFunctionAndUpdate(node, + maybe_type_info.value(), + false); + } } return maybe_function_declaration; } +std::optional + TypeCheckVisitor::FindAbstractTypeTypeclassFunctionAndUpdate( + FunctionCallExpression* node, + info::type::AbstractType* abstract_type_info, + bool is_method) { + std::optional maybe_function_declaration; + + auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name); + if (!maybe_typeclass_graph_id.has_value()) { + error_handling::HandleTypecheckError("Typeclass function not found", node->base); + } + + auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name, + maybe_typeclass_graph_id.value()); + + if (abstract_type_info->HasTypeclass(maybe_typeclass_graph_id.value())) { + if (!maybe_typeclass_function_info.has_value()) { + error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)", + "TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate"); + } + + if ((maybe_typeclass_function_info.value()->modifier == utils::ClassInternalsModifier::Static) != is_method) { + return std::nullopt; + } + + node->typeclass_graph_id_ = maybe_typeclass_graph_id; + maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; + } + + return maybe_function_declaration; +} + +std::optional + TypeCheckVisitor::FindDefinedTypeTypeclassFunctionAndUpdate( + FunctionCallExpression* node, + info::definition::AnyType* defined_type, + bool is_method) { + std::optional maybe_function_declaration; + + auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name); + if (maybe_typeclass_graph_id.has_value()) { + auto typeclasses = global_info_.GetAnnotatedTypeTypeclassesSet(defined_type->type.node); + auto function_typeclass_iter = typeclasses.find(maybe_typeclass_graph_id.value()); + + if (function_typeclass_iter != typeclasses.end()) { + auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name, + maybe_typeclass_graph_id.value()); + if (!maybe_typeclass_function_info.has_value()) { + error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (definied type)", + "TypeCheckVisitor.FindDefinedTypeTypeclassFunctionAndUpdate"); + } + + if ((maybe_typeclass_function_info.value()->modifier == utils::ClassInternalsModifier::Static) != is_method) { + return std::nullopt; + } + + node->typeclass_graph_id_ = maybe_typeclass_graph_id; + maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; + } + } + + return maybe_function_declaration; +} + } // namespace interpreter