From 7fc56df2b7f1cb2bee519ab40daadb0092eb9cac Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Tue, 16 May 2023 20:45:41 +0300 Subject: [PATCH] fixes --- include/interpreter_tree.hpp | 4 +- include/type_check_visitor.hpp | 10 + src/link_symbols_visitor.cpp | 10 +- src/type_check_visitor.cpp | 331 +++++++++++++++++++++------------ 4 files changed, 225 insertions(+), 130 deletions(-) diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp index 15ca1ec..c4ac003 100644 --- a/include/interpreter_tree.hpp +++ b/include/interpreter_tree.hpp @@ -519,7 +519,9 @@ struct FunctionCallExpression { std::vector> parameters; std::vector arguments; - utils::IdType function_id_; + // only one from two is present + std::optional function_id_; + std::optional typeclass_graph_id_; }; struct TupleExpression { diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index e49fc5c..77f6daa 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -140,6 +140,16 @@ private: void CheckPattern(Pattern& node, const BaseNode& base_node); + + std::optional + FindSubExpressionMethod(utils::IdType expression_type, + const std::string& name, + const BaseNode& base_node); + + std::optional FindTypeFunction(TypeExpression* node, + const std::string& name, + std::unordered_map& context); + private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; info::GlobalInfo& global_info_; diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index 5c2bf26..56c4ae1 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -81,16 +81,8 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { return; } - // check made in typecheck visitor ?? - ////////////////////////////////////////////////////////// - // abstract / basic / TODO: local abstract type - // if (path.size() == 0 && (namespace_visitor_.FindAbstractType(node->type.type).has_value()) { - // return; - // } - ////////////////////////////////////////////////////////// - if (!node->type_id_.has_value() && !node->constructor_id_.has_value()) { - // check made in typecheck visitor ?? + // check made in typecheck visitor return; } diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index deba86f..4926275 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -792,132 +792,140 @@ void TypeCheckVisitor::Visit(AccessExpression* node) { // Other Expressions -// TODO: better structure, ... // TODO: builtin functions/methods -// TODO: alias types, abstract types, etc. -// TODO: deduce function parameter types -// TODO: find functions in typeclasses +// TODO: abstract types (check typeclass requirements) void TypeCheckVisitor::Visit(FunctionCallExpression* node) { std::optional maybe_function_id; std::unordered_map context; + std::optional expression_type; + // guaranteed, that name.size() > 0 - if (node->name[0] == '_') { // TODO: manage pointers to function + if (node->name[0] == '_') { error_handling::HandleInternalError("Builtin functions/methods weren't implemented yet", "TypeCheckVisitor.FunctionCallExpresssion"); } + // try to find function id if (node->prefix.has_value()) { if (std::holds_alternative>(node->prefix.value())) { Visitor::Visit(*std::get>(node->prefix.value())); - - std::optional maybe_expression_type = context_manager_.GetValue(current_type_); - - if (!maybe_expression_type.has_value()) { - error_handling::HandleTypecheckError("There is no non-builtin methods for not defined type", node->base); - } - - utils::IdType type_id = maybe_expression_type.value()->GetTypeId(); - - std::optional maybe_type_info = global_info_.GetTypeInfo(type_id); - - if (!maybe_type_info.has_value()) { - error_handling::HandleInternalError("Functions/Methods implemented only for AnyType", - "TypeCheckVisitor.FunctionCallExpresssion"); - } - - // TODO: better decision ?? - std::optional maybe_const_function_id = global_info_.GetNamespaceInfo(global_info_.GetNamespaceInfo(maybe_type_info.value()->parent_namespace).const_namespaces.at(maybe_type_info.value()->type.type)).functions[node->name]; - - 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 = global_info_.GetNamespaceInfo(global_info_.GetNamespaceInfo(maybe_type_info.value()->parent_namespace).var_namespaces.at(maybe_type_info.value()->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; - } + expression_type = current_type_; + maybe_function_id = FindSubExpressionMethod( + expression_type.value(), + node->name, + node->base); } else if (std::holds_alternative>(node->prefix.value())) { - TypeExpression& type_expression = *std::get>(node->prefix.value()); - - if (type_expression.array_size.has_value()) { - error_handling::HandleTypecheckError("Can't call function from array type namespace", node->base); - } - - 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_.FindFunctionId(path, node->name); - - CollectTypeExpressionContext(*std::get>(node->prefix.value()), context); + maybe_function_id = FindTypeFunction( + std::get>(node->prefix.value()).get(), + node->name, + context); } else { - // error + error_handling::HandleInternalError("Unexpected prefix type", + "TypeCheckVisitor.FunctionCallExpression"); } } else { - maybe_function_id = namespace_visitor_.FindFunctionId(std::nullopt, node->name); - } - - if (!maybe_function_id.has_value()) { - error_handling::HandleTypecheckError("Can't find function", node->base); // InternalError ?? - } - - std::optional maybe_function_declaration = - global_info_.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", node->base); - } - info::definition::FunctionDeclaration function_declaration = maybe_function_declaration.value(); - - // - - if (function_declaration.parameters.size() != node->parameters.size()) { - error_handling::HandleTypecheckError("Mismatched parameter count in function call expression", node->base); - } - for (size_t i = 0; i < node->parameters.size(); ++i) { - Visit(node->parameters[i].get()); - - std::string parameter_name = function_declaration.parameters[i].type; - - if (context.count(parameter_name) != 0) { - error_handling::HandleInternalError("Local abstract types with same name in one context", - "TypeCheckVisitor.FunctionCallExpresssion"); // TypecheckError ?? + if (namespace_visitor_.GetCurrentNamespace()->modifier != utils::ClassInternalsModifier::Static) { + // 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 !!! + } else { + maybe_function_id = namespace_visitor_.FindFunctionId(std::nullopt, node->name); } - context[parameter_name] = current_type_; } - // + if (maybe_function_id.has_value()) { + // found function id => function defined or declared in type // ?? - if (function_declaration.argument_types.size() != node->arguments.size() + 1) { - error_handling::HandleTypecheckError("Mismatched argument count in function call expression", node->base); - } - for (size_t i = 0; i < node->arguments.size(); ++i) { - Visitor::Visit(*function_declaration.argument_types[i]); - utils::IdType argument_type = TypeInContext(current_type_, context); + // find function declaration + std::optional& maybe_function_declaration = + global_info_.GetFunctionInfo(maybe_function_id.value()).declaration; + FunctionDeclaration* function_declaration = nullptr; + if (maybe_function_declaration.has_value()) { + function_declaration = maybe_function_declaration.value().node; + } else { + auto maybe_function_info = + typeclass_graph_.GetFunctionInfo(node->name, std::nullopt); - Visitor::Visit(node->arguments[i]); - context_manager_.AddValueRequirement(current_type_, argument_type); + if (!maybe_function_info.has_value()) { + error_handling::HandleTypecheckError("No function declaration found for function in function call expression", node->base); + } + + function_declaration = maybe_function_info.value()->declaration; + } + + // check & collect parmeters + if (function_declaration->parameters.size() != node->parameters.size()) { + error_handling::HandleTypecheckError("Mismatched parameter count in function call expression", node->base); + } + for (size_t i = 0; i < node->parameters.size(); ++i) { + Visit(node->parameters[i].get()); + + std::string parameter_name = function_declaration->parameters[i]->type; + + if (context.count(parameter_name) != 0) { + error_handling::HandleInternalError("Local abstract types with same name in one context", + "TypeCheckVisitor.FunctionCallExpresssion"); + } + context[parameter_name] = current_type_; + } + + // check arguments + if (function_declaration->type->types.size() != node->arguments.size() + 1) { + error_handling::HandleTypecheckError("Mismatched argument count in function call expression", node->base); + } + for (size_t i = 0; i < node->arguments.size(); ++i) { + Visitor::Visit(function_declaration->type->types[i]); + utils::IdType argument_type = TypeInContext(current_type_, context); + + Visitor::Visit(node->arguments[i]); + context_manager_.AddValueRequirement(current_type_, argument_type); + } + + node->function_id_ = maybe_function_id.value(); // IMPORTANT + + Visitor::Visit(function_declaration->type->types.back()); + current_type_ = TypeInContext(current_type_, context); + } else { + // TODO: handle typeclass functions + auto maybe_function_info = typeclass_graph_.GetFunctionInfo(node->name, std::nullopt); + + if (!maybe_function_info.has_value()) { + error_handling::HandleTypecheckError("Can't find function", node->base); + } + + if (node->prefix.has_value()) { + if (std::holds_alternative>(node->prefix.value())) { + // std::get>(node->prefix.value()).get() + // TODO + } else if (std::holds_alternative>(node->prefix.value())) { + // std::get>(node->prefix.value()).get() + // context_manager_.GetLocalType() + // TODO + } else { + error_handling::HandleInternalError("Unexpected prefix type (when checking typeclass function)", + "TypeCheckVisitor.FunctionCallExpression"); + } + } else { + // TODO + } } - node->function_id_ = maybe_function_id.value(); // IMPORTANT + /* + + if (node->path.empty() && maybe_local_abstract_type.has_value()) { + // TODO: find function in one of typeclasses + } + if (!maybe_function_id.has_value()) { + auto maybe_any_type_info = global_info_.GetTypeInfo(node->type_id_.value()); + + if (maybe_function_info.has_value() && node->type_id_.has_value() && global_info_.GetAnnotatedTypeFunctionsMap(.value()->type.node).count(name) != 0) { + + } + // TODO: try to find in one of typeclasses + } + */ - Visitor::Visit(*function_declaration.argument_types.back()); - current_type_ = TypeInContext(current_type_, context); } void TypeCheckVisitor::Visit(TupleExpression* node) { @@ -935,7 +943,6 @@ void TypeCheckVisitor::Visit(TupleExpression* node) { node->base.type_ = current_type_; } -// ?? void TypeCheckVisitor::Visit(VariantExpression* node) { std::vector constructors; @@ -987,7 +994,6 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { std::unordered_map context; CollectTypeExpressionContext(*node->constructor, context); - // TODO: handle alias types std::optional maybe_type_info = global_info_.GetTypeInfo(type_id); @@ -1048,7 +1054,8 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { node->base.type_ = current_type_; } -void TypeCheckVisitor::Visit(LambdaFunction* node) { // TODO +// TODO +void TypeCheckVisitor::Visit(LambdaFunction* node) { error_handling::HandleInternalError("Unimplemented (unsolved type deduction problems)", "TypeCheckVisitor.LambdaFunction"); @@ -1322,27 +1329,31 @@ void TypeCheckVisitor::Visit(TypeExpression* node) { if (maybe_internal_type.has_value()) { // checks made in link_symbols_visitor - current_type_ = context_manager_.AddValue(maybe_internal_type.value(), utils::ValueType::Tmp); + current_type_ = + context_manager_.AddValue( + maybe_internal_type.value(), + utils::ValueType::Tmp); } else { - std::optional maybe_local_abstract_type = context_manager_.GetLocalType(node->type.type); + std::optional maybe_local_abstract_type = + context_manager_.GetLocalType(node->type.type); if (node->path.empty() && maybe_local_abstract_type.has_value()) { current_type_ = maybe_local_abstract_type.value(); - } else if (node->type.type_id_.has_value()) { // TODO: chack that names are different (always true ??) - + } else if (node->type.type_id_.has_value()) { // TODO: check that names are different (always true ??) std::optional maybe_type_info = global_info_.GetTypeInfo(node->type.type_id_.value()); - if (!maybe_type_info.has_value()) { // TODO: add alias, abstract, ... types - error_handling::HandleInternalError("No AnyType found", "TypeCheckVisitor.TypeExpression"); + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("No AnyType found (alias types, ... not implemented)", "TypeCheckVisitor.TypeExpression"); } Visitor::Visit(*maybe_type_info.value()->value); current_type_ = TypeInContext(current_type_, context); - current_type_ = context_manager_.AddValue(info::type::DefinedType(node->type_id_.value(), - current_type_, - maybe_type_info.value()->modifier, - context_manager_.GetValueManager()), - utils::ValueType::Tmp); + current_type_ = + context_manager_.AddValue(info::type::DefinedType(node->type_id_.value(), + current_type_, + maybe_type_info.value()->modifier, + context_manager_.GetValueManager()), + utils::ValueType::Tmp); } else { error_handling::HandleTypecheckError("Type not found", node->base); } @@ -1369,12 +1380,14 @@ void TypeCheckVisitor::Visit(ExtendedScopedAnyType* node) { // Typeclass -void TypeCheckVisitor::Visit(ParametrizedTypeclass* node) { // TODO ?? - for (auto& parameter : node->parameters) { - Visit(parameter.get()); +void TypeCheckVisitor::Visit(ParametrizedTypeclass* node) { + if (node->parameters.size()) { + error_handling::HandleInternalError("Typeclasses with parameters are not implemented", + "TypeCheckVisitor.ParametrizedTypeclass"); } - node->base.type_ = current_type_; + error_handling::HandleInternalError("ParametizedTypeclass shouldn't be visited (?)", + "TypeCheckVisitor.ParametrizedTypeclass"); } // Typeclass & Type ----------------- @@ -1479,7 +1492,7 @@ void TypeCheckVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { break; case 1: Visitor::Visit(*std::get>(node)); - if (!context_manager_.EqualValues(current_type_, value_type)) { // TODO: better solution ?? + if (!context_manager_.EqualValues(current_type_, value_type)) { error_handling::HandleTypecheckError("Literal and value have different types", base_node); } break; @@ -1492,4 +1505,82 @@ void TypeCheckVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { } } +// TODO: internal types ?? +// TODO: abstract types, typeclasses +std::optional + TypeCheckVisitor::FindSubExpressionMethod(utils::IdType expression_type, + const std::string& name, + const BaseNode& base_node) { + std::optional maybe_function_id; + + std::optional maybe_expression_type_info = + context_manager_.GetValue(expression_type); + if (!maybe_expression_type_info.has_value()) { + error_handling::HandleTypecheckError("There is no non-builtin methods for not defined type", base_node); + } + + utils::IdType type_id = maybe_expression_type_info.value()->GetTypeId(); + std::optional maybe_type_info = + global_info_.GetTypeInfo(type_id); + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("Functions/Methods implemented only for AnyType", + "TypeCheckVisitor.FunctionCallExpresssion"); + } + + // TODO: better decision ?? + std::optional maybe_const_function_id = global_info_.GetNamespaceInfo(global_info_.GetNamespaceInfo(maybe_type_info.value()->parent_namespace).const_namespaces.at(maybe_type_info.value()->type.type)).functions[name]; + + utils::ValueType expression_value_type = context_manager_.GetValueType(expression_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 = global_info_.GetNamespaceInfo(global_info_.GetNamespaceInfo(maybe_type_info.value()->parent_namespace).var_namespaces.at(maybe_type_info.value()->type.type)).functions[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); + } + + if (!maybe_function_id.has_value()) { + maybe_function_id = maybe_const_function_id; + } + + return maybe_function_id; +} + +// TODO: internal types ?? +// TODO: abstract types, typeclasses +std::optional + TypeCheckVisitor::FindTypeFunction(TypeExpression* node, + const std::string& name, + std::unordered_map& context) { + std::optional maybe_function_id; + + if (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(node->type.type); + + std::vector path; + path.reserve(node->path.size() + 1); + + for (auto& path_type : node->path) { + path.push_back(path_type.type); + } + path.push_back(node->type.type); + + maybe_function_id = namespace_visitor_.FindFunctionId(path, name); + + CollectTypeExpressionContext(*node, context); + + return maybe_function_id; +} + } // namespace interpreter