diff --git a/include/global_info.hpp b/include/global_info.hpp index 2d1e40b..fe95619 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -205,15 +205,21 @@ public: return current_path_; } + const std::vector& GetCurrentPathNamespaces() { + return namespace_stack_; + } + // use only after LinkSymbolsVisitor - std::vector GetCurrentPathTypes() { - std::vector types; + 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()); + } else { + types.push_back(std::nullopt); } } diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp index 8427259..0c68668 100644 --- a/include/interpreter_tree.hpp +++ b/include/interpreter_tree.hpp @@ -522,7 +522,7 @@ struct FunctionCallExpression { // only one from two is present std::optional function_id_; - std::optional typeclass_graph_id_; + std::optional graph_id_; // for type or typeclass bool is_method_of_first_argument_ = false; }; diff --git a/include/link_symbols_visitor.hpp b/include/link_symbols_visitor.hpp index ec3326d..f02e9cd 100644 --- a/include/link_symbols_visitor.hpp +++ b/include/link_symbols_visitor.hpp @@ -130,7 +130,8 @@ private: void AddTypeFunctionsToTypeclassGraph(utils::IdType type_id, utils::IdType graph_id, - utils::ClassInternalsModifier namespace_modifier); + utils::ClassInternalsModifier namespace_modifier, + const BaseNode& base_node); private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index d7bf32b..213f105 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -158,7 +158,7 @@ private: bool is_method); std::optional - FindDefinedTypeTypeclassFunctionAndUpdate( + FindDefinedTypeFunctionAndUpdate( FunctionCallExpression* node, info::definition::AnyType* defined_type, bool is_method); diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index 7a3e5fb..720a797 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -55,15 +55,18 @@ void LinkSymbolsVisitor::Visit(TypeDefinitionStatement* node) { AddTypeFunctionsToTypeclassGraph(node->type_id_, graph_id, - utils::ClassInternalsModifier::Static); + utils::ClassInternalsModifier::Static, + node->base); AddTypeFunctionsToTypeclassGraph(node->type_id_, graph_id, - utils::ClassInternalsModifier::Const); + utils::ClassInternalsModifier::Const, + node->base); AddTypeFunctionsToTypeclassGraph(node->type_id_, graph_id, - utils::ClassInternalsModifier::Var); + utils::ClassInternalsModifier::Var, + node->base); } void LinkSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { @@ -164,7 +167,8 @@ void LinkSymbolsVisitor::Visit(ParametrizedTypeclass* node) { void LinkSymbolsVisitor::AddTypeFunctionsToTypeclassGraph(utils::IdType type_id, utils::IdType graph_id, - utils::ClassInternalsModifier namespace_modifier) { + utils::ClassInternalsModifier namespace_modifier, + const BaseNode& base_node) { auto maybe_type_graph_info = typeclass_graph_.GetTypeVertex(graph_id); if (!maybe_type_graph_info.has_value()) { error_handling::HandleInternalError("Type in typeclass graph is not marked as type", @@ -198,10 +202,12 @@ void LinkSymbolsVisitor::AddTypeFunctionsToTypeclassGraph(utils::IdType type_id, type_graph_info->functions[function.first] = function_graph_info; } else { - if (function_info.definition.has_value()) { - function_graph_iter->second.is_defined_in_owner = true; - function_graph_iter->second.definition = function_info.definition.value().node; + if (namespace_modifier != function_graph_iter->second.modifier) { + error_handling::HandleTypecheckError("Type function \"" + function.first + "\" has definitions / declarations with different modifiers (static / const /var)", base_node); } + + error_handling::HandleInternalError("This code should be unreachable", + "LinkSymbolsVisitor.AddTypeFunctionsToTypeclassGraph"); } } } diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 6506d34..74cbd82 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -713,6 +713,7 @@ void TypeCheckVisitor::Visit(AccessExpression* node) { // Other Expressions // TODO: builtin functions / methods +// TODO: find & check definitions void TypeCheckVisitor::Visit(FunctionCallExpression* node) { std::optional maybe_function_declaration; @@ -776,7 +777,27 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { context_manager_.AddValueRequirement(current_type_, argument_type); } - // node->function_id_ = maybe_function_id.value(); // IMPORTANT // TODO: do in functions + if (node->function_id_.has_value()) { + if (!global_info_.GetFunctionInfo(node->function_id_.value()).definition.has_value()) { + error_handling::HandleTypecheckError("No function definition found (non-type function)", node->base); + } + } else if (node->graph_id_.has_value()) { + if (typeclass_graph_.GetVertex(node->graph_id_.value()).modifier != info::TypeclassGraph::Modifier::Typeclass) { + auto maybe_graph_function_info = typeclass_graph_.GetFunctionInfo(node->name, node->graph_id_.value()); + + if (!maybe_graph_function_info.has_value()) { + error_handling::HandleInternalError("FunctionInfo by graph_id_ not found", + "TypeCheckVisitor.FunctionCallExpression"); + } + + if (!maybe_graph_function_info.value()->definition.has_value()) { + error_handling::HandleTypecheckError("No function definition found (type function)", node->base); + } + } + } else { + error_handling::HandleInternalError("No function_id_ and graph_id_ found", + "TypeCheckVisitor.FunctionCallExpression"); + } Visitor::Visit(function_declaration->type->types.back()); current_type_ = TypeInContext(current_type_, context); @@ -1372,7 +1393,6 @@ void TypeCheckVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { } // TODO: internal types ?? -// TODO: find & check definitions std::optional TypeCheckVisitor::FindExpressionMethodAndUpdate(FunctionCallExpression* node, utils::IdType expression_type) { @@ -1399,35 +1419,9 @@ std::optional } info::definition::AnyType* type_info = maybe_type_info.value(); - std::optional maybe_const_function_id = global_info_.GetNamespaceInfo(global_info_.GetNamespaceInfo(type_info->parent_namespace).const_namespaces.at(type_info->type.type)).functions[node->name]; - - 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", node->base); - } - - if (!maybe_function_id.has_value()) { - maybe_function_id = maybe_const_function_id; - } - - 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()) { - maybe_function_declaration = FindDefinedTypeTypeclassFunctionAndUpdate(node, - type_info, - true); - } + maybe_function_declaration = FindDefinedTypeFunctionAndUpdate(node, + type_info, + true); } return maybe_function_declaration; } @@ -1467,26 +1461,26 @@ std::optional } path.push_back(type_node->type.type); - 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()) { + if (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); + maybe_function_declaration = FindDefinedTypeFunctionAndUpdate(node, + maybe_type_info.value(), + false); + } else { + std::optional maybe_function_id = namespace_visitor_.FindFunctionId(path, node->name); + + 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; + } } } return maybe_function_declaration; @@ -1494,36 +1488,63 @@ std::optional std::optional TypeCheckVisitor::FindFunctionAndUpdate(FunctionCallExpression* node) { std::optional maybe_function_declaration; - std::optional maybe_function_id; - if (namespace_visitor_.GetCurrentNamespace()->modifier != utils::ClassInternalsModifier::Static) { - std::string namespace_name = - namespace_visitor_.GetCurrentNamespace()->type_name; - utils::ClassInternalsModifier namespace_modifier = - namespace_visitor_.GetCurrentNamespace()->modifier; - namespace_visitor_.ExitNamespace(); + const std::vector& path_namespaces = namespace_visitor_.GetCurrentPathNamespaces(); + auto path_types = namespace_visitor_.GetCurrentPathTypes(); + for (ssize_t i = (ssize_t)path_types.size() - 1; i >= 0; --i) { // optimize ?? + if (path_types[i].has_value()) { + auto maybe_type_info = global_info_.GetTypeInfo(path_types[i].value()); + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("typeclass functions / methods implemented only for AnyType", + "TypeCheckVisitor.FindTypeFunctionAndUpdate"); + } - maybe_function_id = namespace_visitor_.FindFunctionId(std::nullopt, node->name); - if (!maybe_function_id.has_value()) { - // call functions from static namespace of current type - std::vector current_type_path { namespace_visitor_.GetCurrentNamespace()->type_name }; - maybe_function_id = namespace_visitor_.FindFunctionId(current_type_path, node->name); // TODO: check !!! + maybe_function_declaration = + FindDefinedTypeFunctionAndUpdate(node, + maybe_type_info.value(), + false); + } else { + auto function_iter = global_info_.GetNamespaceInfo(path_namespaces[i]).functions.find(node->name); + if (function_iter != global_info_.GetNamespaceInfo(path_namespaces[i]).functions.end()) { + auto& maybe_declaration_info = global_info_.GetFunctionInfo(function_iter->second).declaration; + + if (maybe_declaration_info.has_value()) { + maybe_function_declaration = maybe_declaration_info.value().node; + } + } } - namespace_visitor_.EnterNamespace(namespace_name, namespace_modifier); - } else { - maybe_function_id = namespace_visitor_.FindFunctionId(std::nullopt, node->name); + if (maybe_function_declaration.has_value()) { + break; + } } - 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; - } + // ------------------ replaced ------------------ + // if (namespace_visitor_.GetCurrentNamespace()->modifier != utils::ClassInternalsModifier::Static) { + // std::string namespace_name = + // namespace_visitor_.GetCurrentNamespace()->type_name; + // utils::ClassInternalsModifier namespace_modifier = + // namespace_visitor_.GetCurrentNamespace()->modifier; + // namespace_visitor_.ExitNamespace(); + // + // maybe_function_id = namespace_visitor_.FindFunctionId(std::nullopt, node->name); + // if (!maybe_function_id.has_value()) { + // // call functions from static namespace of current type + // std::vector current_type_path { namespace_visitor_.GetCurrentNamespace()->type_name }; + // maybe_function_id = namespace_visitor_.FindFunctionId(current_type_path, node->name); + // } + // + // namespace_visitor_.EnterNamespace(namespace_name, namespace_modifier); + // } else { + // maybe_function_id = namespace_visitor_.FindFunctionId(std::nullopt, node->name); + // } + // + // 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; + // } - // call as method of first argument // TODO: earlier?? if (!maybe_function_declaration.has_value() && node->is_binary_operator_expression && node->arguments.size() > 0) { Visitor::Visit(node->arguments[0]); maybe_function_declaration = FindExpressionMethodAndUpdate(node, current_type_); @@ -1532,30 +1553,6 @@ std::optional TypeCheckVisitor::FindFunctionAndUpdate(Func } } - // 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; - } - } - } - } - return maybe_function_declaration; } @@ -1589,44 +1586,28 @@ std::optional error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base); } - node->typeclass_graph_id_ = maybe_typeclass_graph_id; + node->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) { + TypeCheckVisitor::FindDefinedTypeFunctionAndUpdate( + 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 maybe_type_function_info = typeclass_graph_.GetFunctionInfo(node->name, defined_type->type.node->graph_id_); + + if (!maybe_type_function_info.has_value()) { return std::nullopt; + // error_handling::HandleTypecheckError("Function is not declared in type", node->base); } - auto typeclasses = typeclass_graph_.GetDependenciesSet(defined_type->type.node->graph_id_); - auto function_typeclass_iter = typeclasses.find(maybe_typeclass_graph_id.value()); - - if (function_typeclass_iter == typeclasses.end()) { - error_handling::HandleTypecheckError("Function typeclass not pesent in type typeclasses list (defined type)", node->base); - } - - 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; + node->graph_id_ = defined_type->type.node->graph_id_; + maybe_function_declaration = maybe_type_function_info.value()->declaration; return maybe_function_declaration; }