From 57b1172a4fa288f95c21980e44345b1ef9ce9c09 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Thu, 11 Apr 2024 22:34:45 +0300 Subject: [PATCH] type check utils: optional error handling, name expression type check part --- include/type_check_utils.hpp | 41 +++++++------- src/expression_type_check.cpp | 84 ++++++++++++++------------- src/type_check_utils.cpp | 104 ++++++++++++++++------------------ 3 files changed, 117 insertions(+), 112 deletions(-) diff --git a/include/type_check_utils.hpp b/include/type_check_utils.hpp index f069fae..66e25d3 100644 --- a/include/type_check_utils.hpp +++ b/include/type_check_utils.hpp @@ -239,7 +239,8 @@ private: nodes::TypeProxy check_same_to_pass_type_in_arguments( nodes::TypeProxy type, const Arguments &arguments, const nodes::Node &node, SourcesManager &sources_manager, - const std::string &message = "Different type with passed one"); + const std::string &message = "Different type with passed one", + bool handle_errors = true); // bool check_no_pass_type_in_arguments( // const Arguments &arguments, const nodes::Node &node, @@ -249,33 +250,35 @@ nodes::TypeProxy check_same_to_pass_type_in_arguments( nodes::TypeCheckResult type_same_to_expected( nodes::TypeProxy type, const Arguments &argumensr, const nodes::Node &node, SourcesManager &sources_manager, - const std::string &message = "Different type with expected one"); + const std::string &message = "Different type with expected one", + bool handle_errors = true); -nodes::TypeCheckResult -type_check_from_arguments(nodes::TypeProxy type, const Arguments &arguments, - const nodes::Node &node, - SourcesManager &sources_manager); +nodes::TypeCheckResult type_check_from_arguments( + nodes::TypeProxy type, const Arguments &arguments, const nodes::Node &node, + SourcesManager &sources_manager, bool handle_errors = true); std::optional -find_type_definition_handle_errors(const std::string &name, - const nodes::Node &node, - SourcesManager &sources_manager); +find_type_definition(const std::string &name, const nodes::Node &node, + SourcesManager &sources_manager, + bool handle_errors = true); std::optional -find_name_definition_handle_errors(const std::string &name, - const nodes::Node &node, - SourcesManager &sources_manager); +find_name_definition(const std::string &name, const nodes::Node &node, + SourcesManager &sources_manager, + bool handle_errors = true); std::optional -unfold_user_defined_type_handle_errors(nodes::TypeProxy type, - const nodes::Node &node, - SourcesManager &sources_manager); +unfold_user_defined_type(nodes::TypeProxy type, const nodes::Node &node, + SourcesManager &sources_manager, + bool handle_errors = true); -std::optional get_field_type_by_name_handle_errors( - nodes::TypeProxy type, const std::string &field, const nodes::Node &node, - SourcesManager &sources_manager); +std::optional +get_field_type_by_name(nodes::TypeProxy type, const std::string &field, + const nodes::Node &node, SourcesManager &sources_manager, + bool handle_errors = true); void type_check_error(const std::string &message, const nodes::Node &node, - SourcesManager &sources_manager); + SourcesManager &sources_manager, + bool handle_error = true); } // namespace type_check diff --git a/src/expression_type_check.cpp b/src/expression_type_check.cpp index 1acb36b..e6a8d97 100644 --- a/src/expression_type_check.cpp +++ b/src/expression_type_check.cpp @@ -549,38 +549,49 @@ type_check_name_expression(const nodes::NameExpression &expression, nodes::Identifier current_prefix = fragments.front(); std::optional maybe_variable; size_t i = 0; - for (; i < fragments.size(); ++i) { // go in prefixes and try to find matching var namei - if (i > 0) { - current_prefix.append_after(fragments[i]); - } + for (; i < fragments.size(); ++i) { + // go in prefixes and try to find matching var namei + if (i > 0) { + current_prefix.append_after(fragments[i]); + } - maybe_variable = state.find_variable(*current_prefix.get()); + maybe_variable = state.find_variable(*current_prefix.get()); - if (maybe_variable.has_value()) { - break; - } + if (maybe_variable.has_value()) { + break; + } } if (maybe_variable.has_value()) { - auto& type = maybe_variable.value().type; - for (size_t j = i + 1; j < fragments.size(); ++i) { + auto &type = maybe_variable.value().type; + for (size_t j = i + 1; j < fragments.size(); ++i) { + + if (j + 1 == fragments.size()) { // then this can be method call + // TODO: try to find method or local function + // if found, search to field (without error handling) + } + + // TODO: fields from several fragments ? (not acceptable fors methods / + // functions) + + // <- in typecheck utils method // TODO: switch by type types: Variant, Tuple, ... // Tuple -> try to find field // Others -> try to open / builtin fields ? - const auto maybe_field = type.get()->get_parameter_proxy_by_name(*fragments[j].get()); + const auto maybe_field_type = get_field_type_by_name( + type, *fragments[i].get(), expression, sources_manager); - if (maybe_field.has_value()) { - type = maybe_field.value(); - continue; - } - - if (j + 1 == fragments.size()) { // then this can be method call - // TODO: try to fond method or local function - } - - // fields for the names should be found - // last segment can be function name + if (maybe_field_type.has_value()) { + type = maybe_field_type.value(); + // TODO + continue; } + + // TODO + + // fields for the names should be found + // last segment can be function name + } } } @@ -601,19 +612,16 @@ type_check_name_expression(const nodes::NameExpression &expression, // TODO: manage situation with one out type at any position // TODO + 1 - returned type - somtimes (can be ==) const auto arguments_given = expression.arguments_size(); - const auto arguments_defined = function_definition->arguments_size(); + const auto arguments_defined = function_definition->arguments_size(); if (arguments_given + 1 < arguments_defined || - arguments_given > - arguments_defined) { // other, when there is passed type + arguments_given > arguments_defined) { // other, when there is passed type type_check_error( "Number of function arguments is different from expected (" + std::to_string(arguments_given) + " instead of " + std::to_string(arguments_defined) + - std::string{ - arguments_defined > 0 - ? (" or " + std::to_string( - arguments_defined - 1)) - : ""} + + std::string{arguments_defined > 0 + ? (" or " + std::to_string(arguments_defined - 1)) + : ""} + ")", expression, sources_manager); return nodes::TypeCheckResult::construct_invalid_result(); @@ -967,17 +975,15 @@ nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression, // TODO: deal with return type (+1 sometimes), etc const auto arguments_given = expression.arguments_size(); - const auto arguments_defined = expected_type.get()->parameters_size(); + const auto arguments_defined = expected_type.get()->parameters_size(); if (arguments_given != arguments_defined) { type_check_error( "Number of function arguments is different from expected (" + std::to_string(arguments_given) + " instead of " + std::to_string(arguments_defined) + - std::string{ - arguments_defined > 0 - ? (" or " + std::to_string( - arguments_defined - 1)) - : ""} + + std::string{arguments_defined > 0 + ? (" or " + std::to_string(arguments_defined - 1)) + : ""} + ")", expression, sources_manager); } @@ -996,8 +1002,10 @@ nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression, // TODO: out type is can be not last if (arguments_given + 1 == arguments_defined) { - type_check_expression(*expression.get_expression(), sources_manager, state, - Arguments{}.expect(expected_type.get()->get_parameter_proxy(arguments_defined - 1))); + type_check_expression( + *expression.get_expression(), sources_manager, state, + Arguments{}.expect( + expected_type.get()->get_parameter_proxy(arguments_defined - 1))); } // TODO: needed ?? (only passed type check required ??) diff --git a/src/type_check_utils.cpp b/src/type_check_utils.cpp index 5e552e4..7eb9ef7 100644 --- a/src/type_check_utils.cpp +++ b/src/type_check_utils.cpp @@ -8,13 +8,14 @@ namespace type_check { // no pass type -> return type nodes::TypeProxy check_same_to_pass_type_in_arguments( nodes::TypeProxy type, const Arguments &arguments, const nodes::Node &node, - SourcesManager &sources_manager, const std::string &message) { + SourcesManager &sources_manager, const std::string &message, + bool handle_errors) { if (!arguments.get_passed().has_value()) { return type; } if (type != arguments.get_passed().value()) { - type_check_error(message, node, sources_manager); + type_check_error(message, node, sources_manager, handle_errors); } return sources_manager.get_type_storage()->primitive_type( @@ -24,20 +25,20 @@ nodes::TypeProxy check_same_to_pass_type_in_arguments( bool check_no_pass_type_in_arguments(const Arguments &arguments, const nodes::Node &node, SourcesManager &sources_manager, - const std::string &message) { + const std::string &message, + bool handle_errors) { if (arguments.get_passed().has_value()) { - type_check_error(message, node, sources_manager); + type_check_error(message, node, sources_manager, handle_errors); return false; } return true; } -nodes::TypeCheckResult type_same_to_expected(nodes::TypeProxy type, - const Arguments &arguments, - const nodes::Node &node, - SourcesManager &sources_manager, - const std::string &message) { +nodes::TypeCheckResult +type_same_to_expected(nodes::TypeProxy type, const Arguments &arguments, + const nodes::Node &node, SourcesManager &sources_manager, + const std::string &message, bool handle_errors) { const auto &expected = arguments.get_expected(); if (expected.empty()) { @@ -49,74 +50,66 @@ nodes::TypeCheckResult type_same_to_expected(nodes::TypeProxy type, [type](nodes::TypeProxy expected_type) { return type != expected_type; })) { - type_check_error(message, node, sources_manager); + type_check_error(message, node, sources_manager, handle_errors); } return nodes::TypeCheckResult{expected.front()}; // any can be choosen } template -std::optional -find_statement_handle_errors(const std::string &name, const nodes::Node &node, - SourcesManager &sources_manager, - const std::string &message_not_found, - const std::string &message_different_statement) { +std::optional find_statement_handle_errors( + const std::string &name, const nodes::Node &node, + SourcesManager &sources_manager, const std::string &message_not_found, + const std::string &message_different_statement, bool handle_errors) { const auto maybe_any_statement = sources_manager.get_name_tree()->find(name); if (!maybe_any_statement.has_value()) { - sources_manager.get_error_log()->add_error( - error_handling::ErrorLog::ErrorMessage( - node, message_not_found, error_handling::ErrorType::TYPE_CHECK)); + type_check_error(message_not_found, node, sources_manager, handle_errors); return std::nullopt; } const auto maybe_statement = maybe_any_statement.value().get()->get(); if (!maybe_statement.has_value()) { - sources_manager.get_error_log()->add_error( - error_handling::ErrorLog::ErrorMessage( - node, message_different_statement, - error_handling::ErrorType::TYPE_CHECK)); + type_check_error(message_different_statement, node, sources_manager, + handle_errors); return std::nullopt; } return maybe_statement.value(); } -std::optional -find_type_definition_handle_errors(const std::string &name, - const nodes::Node &node, - SourcesManager &sources_manager) { +std::optional find_type_definition_handle_errors( + const std::string &name, const nodes::Node &node, + SourcesManager &sources_manager, bool handle_errors) { return find_statement_handle_errors( name, node, sources_manager, "No type definition found in name tree", - "Node in name tree is not type definition"); + "Node in name tree is not type definition", handle_errors); } std::optional find_name_definition_handle_errors(const std::string &name, const nodes::Node &node, - SourcesManager &sources_manager) { + SourcesManager &sources_manager, + bool handle_errors) { return find_statement_handle_errors( name, node, sources_manager, "No name definition found in name tree", - "Node in name tree is not name definition"); + "Node in name tree is not name definition", handle_errors); } -std::optional -unfold_user_defined_type_handle_errors(nodes::TypeProxy type, - const nodes::Node &node, - SourcesManager &sources_manager) { +std::optional unfold_user_defined_type_handle_errors( + nodes::TypeProxy type, const nodes::Node &node, + SourcesManager &sources_manager, bool handle_errors) { const auto maybe_type_definition = find_type_definition_handle_errors( - *type.get()->get_name()->get(), node, sources_manager); + *type.get()->get_name()->get(), node, sources_manager, handle_errors); if (!maybe_type_definition.has_value()) { return std::nullopt; } if (maybe_type_definition.value()->get_type().has_value()) { - sources_manager.get_error_log()->add_error( - error_handling::ErrorLog::ErrorMessage( - node, - "Only type declaration found for type " + - *type.get()->get_name()->get() + " (type is not defined)", - error_handling::ErrorType::TYPE_CHECK)); + type_check_error("Only type declaration found for type " + + *type.get()->get_name()->get() + + " (type is not defined)", + node, sources_manager, handle_errors); return std::nullopt; } @@ -129,7 +122,7 @@ unfold_user_defined_type_handle_errors(nodes::TypeProxy type, std::optional get_field_type_by_name_handle_errors( nodes::TypeProxy type, const std::string &field, const nodes::Node &node, - SourcesManager &sources_manager) { + SourcesManager &sources_manager, bool handle_errors) { switch (type.get()->to_builtin()) { case builtin::types::Type::TUPLE: { // access field @@ -138,10 +131,8 @@ std::optional get_field_type_by_name_handle_errors( if (!maybe_field.has_value()) { // TODO: pass unfolded type name to log it ?? - sources_manager.get_error_log()->add_error( - error_handling::ErrorLog::ErrorMessage( - node, "Type has no defined field " + field, - error_handling::ErrorType::TYPE_CHECK)); + type_check_error("Type has no defined field " + field, node, + sources_manager, handle_errors); } return maybe_field.value(); } @@ -149,30 +140,33 @@ std::optional get_field_type_by_name_handle_errors( // then repeat access // remove recursion ?? - const auto maybe_internal_type = - unfold_user_defined_type_handle_errors(type, node, sources_manager); + const auto maybe_internal_type = unfold_user_defined_type_handle_errors( + type, node, sources_manager, handle_errors); if (!maybe_internal_type.has_value()) { return std::nullopt; } return get_field_type_by_name_handle_errors(maybe_internal_type.value(), - field, node, sources_manager); + field, node, sources_manager, + handle_errors); } default: // variant, function, optional, result, error (TODO: add message // field?), array (TODO: add length field ?), basic types - sources_manager.get_error_log()->add_error( - error_handling::ErrorLog::ErrorMessage( - node, - "Type " + builtin::types::to_string(type.get()->to_builtin()) + - " has no accessible fields by definition", - error_handling::ErrorType::TYPE_CHECK)); + type_check_error("Type " + + builtin::types::to_string(type.get()->to_builtin()) + + " has no accessible fields by definition", + node, sources_manager, handle_errors); return std::nullopt; } } void type_check_error(const std::string &message, const nodes::Node &node, - SourcesManager &sources_manager) { + SourcesManager &sources_manager, bool handle_error) { + if (!handle_error) { + return; + } + sources_manager.get_error_log()->add_error( error_handling::ErrorLog::ErrorMessage( node, message, error_handling::ErrorType::TYPE_CHECK));