diff --git a/include/type_check_utils.hpp b/include/type_check_utils.hpp index e77734b..ae0abb1 100644 --- a/include/type_check_utils.hpp +++ b/include/type_check_utils.hpp @@ -144,11 +144,46 @@ class Arguments { public: static Arguments expect_builtin(builtin::types::Type type, SourcesManager &sources_manager) { - return {{sources_manager.get_type_storage()->primitive_type(type)}}; + return Arguments(sources_manager.get_type_storage()->primitive_type(type), + {}); } -public: - nodes::MaybeTypeProxy expected_type = {}; + static Arguments nothing() { return Arguments({}, {}); } + + static Arguments expect(nodes::TypeProxy type) { return Arguments(type, {}); } + + static Arguments pass(nodes::TypeProxy type) { return Arguments({}, type); } + + static Arguments maybe_expect(nodes::MaybeTypeProxy type) { + return Arguments(type, {}); + } + + static Arguments maybe_pass(nodes::MaybeTypeProxy type) { + return Arguments({}, type); + } + + static Arguments expect_and_pass(nodes::TypeProxy expected_type, + nodes::TypeProxy passed_type) { + return Arguments(expected_type, passed_type); + } + + static Arguments maybe_expect_and_pass(nodes::MaybeTypeProxy expected_type, + nodes::MaybeTypeProxy passed_type) { + return Arguments(expected_type, passed_type); + } + + nodes::MaybeTypeProxy get_expected() const { return expected_type_; }; + + nodes::MaybeTypeProxy get_passed() const { return passed_type_; }; + +private: + explicit Arguments(nodes::MaybeTypeProxy expected_type = {}, + nodes::MaybeTypeProxy passed_type = {}) + : expected_type_(expected_type), passed_type_(passed_type) {} + +private: + nodes::MaybeTypeProxy expected_type_ = {}; + nodes::MaybeTypeProxy passed_type_ = {}; }; class ContextHolder { diff --git a/src/expression_type_check.cpp b/src/expression_type_check.cpp index d310ed8..2bb01c7 100644 --- a/src/expression_type_check.cpp +++ b/src/expression_type_check.cpp @@ -65,7 +65,7 @@ type_check_expression(const nodes::Expression &expression, case 12: // Literal // TODO return type_check_literal(*expression.get().value(), - sources_manager, arguments.expected_type); + sources_manager, arguments.get_expected()); // --- empty lines case 13: // Extra return nodes::TypeCheckResult( @@ -86,14 +86,13 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression, State &state, const Arguments &arguments) { nodes::TypeCheckResult value_result = type_check_expression( - *expression.get_value(), sources_manager, state, {}); + *expression.get_value(), sources_manager, state, Arguments::nothing()); if (value_result.is_invalid()) { sources_manager.get_error_log()->add_error( error_handling::ErrorLog::ErrorMessage( expression, "Match value is invalid", error_handling::ErrorType::TYPE_CHECK)); - } std::optional expression_result; @@ -103,24 +102,25 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression, type_check_expression( *current_case->get_value(), sources_manager, state, - Arguments{value_result.is_invalid() ? nodes::MaybeTypeProxy{} - : expression_result.value().get() - }); + Arguments::maybe_expect(value_result.is_invalid() + ? nodes::MaybeTypeProxy{} + : expression_result.value().get())); // TODO: work with case // TODO: use type modifiers if (current_case->get_condition().has_value()) { - type_check_expression( - *current_case->get_condition().value(), sources_manager, state, - Arguments::expect_builtin(builtin::types::Type::BOOL, sources_manager)); + type_check_expression(*current_case->get_condition().value(), + sources_manager, state, + Arguments::expect_builtin( + builtin::types::Type::BOOL, sources_manager)); } if (current_case->get_expression().has_value()) { nodes::TypeCheckResult case_result = type_check_expression( *current_case->get_condition().value(), sources_manager, state, - Arguments{expression_result.has_value() - ? expression_result.value().get() - : nodes::MaybeTypeProxy{}}); + Arguments::maybe_expect(expression_result.has_value() + ? expression_result.value().get() + : nodes::MaybeTypeProxy{})); if (!expression_result.has_value() && !case_result.is_invalid()) { expression_result = std::move(case_result); @@ -138,7 +138,7 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression, return type_same_to_expected(sources_manager.get_type_storage()->add_array_of( expression_result.value().get()), - arguments.expected_type, expression, + arguments.get_expected(), expression, *sources_manager.get_error_log()); } // IN PROGRESS @@ -156,9 +156,9 @@ nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression, nodes::TypeCheckResult case_result = type_check_expression( *expression.get_case(i).first, sources_manager, state, - Arguments{expression_result.has_value() - ? expression_result.value().get() - : nodes::MaybeTypeProxy{}}); + Arguments::maybe_expect(expression_result.has_value() + ? expression_result.value().get() + : nodes::MaybeTypeProxy{})); if (!expression_result.has_value() && !case_result.is_invalid()) { expression_result = std::move(case_result); @@ -166,11 +166,11 @@ nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression, } if (expression.get_else_case().has_value()) { - type_check_expression(*expression.get_else_case().value(), sources_manager, - state, - Arguments{expression_result.has_value() - ? expression_result.value().get() - : nodes::MaybeTypeProxy{}}); + type_check_expression( + *expression.get_else_case().value(), sources_manager, state, + Arguments::maybe_expect(expression_result.has_value() + ? expression_result.value().get() + : nodes::MaybeTypeProxy{})); } if (!expression_result.has_value()) { @@ -188,7 +188,7 @@ nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression, return type_same_to_expected(sources_manager.get_type_storage()->add_array_of( expression_result.value().get()), - arguments.expected_type, expression, + arguments.get_expected(), expression, *sources_manager.get_error_log()); } @@ -204,8 +204,9 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, std::optional variable_result; - nodes::TypeCheckResult expression_result = type_check_expression( - *expression.get_expression(), sources_manager, state, {}); + nodes::TypeCheckResult expression_result = + type_check_expression(*expression.get_expression(), sources_manager, + state, Arguments::nothing()); switch (expression.get_type()) { case nodes::Loop::LOOP: // infinity loop, no params @@ -247,7 +248,8 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, variable_result = type_check_expression( *expression.get_variable().value(), sources_manager, state, - Arguments{interval_result.value().get().get()->get_parameter_proxy(0)}); + Arguments::expect( + interval_result.value().get().get()->get_parameter_proxy(0))); // --- type check is independent from loop itself --- // if (variable_result.value().is_invalid()) { @@ -264,7 +266,7 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, return type_same_to_expected( sources_manager.get_type_storage()->add_array_of(expression_result.get()), - arguments.expected_type, expression, *sources_manager.get_error_log()); + arguments.get_expected(), expression, *sources_manager.get_error_log()); } // IN PROGRESS // --- containers @@ -277,8 +279,9 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression, for (size_t i = 0; i < expression.expressions_size(); ++i) { // elements should have same type, but type is not expected - auto expression_result = type_check_expression( - *expression.get_expression(i), sources_manager, state, Arguments{}); + auto expression_result = + type_check_expression(*expression.get_expression(i), sources_manager, + state, Arguments::nothing()); if (!last_expression_result.has_value()) { last_expression_result = expression_result; @@ -304,7 +307,7 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression, return type_same_to_expected(sources_manager.get_type_storage()->add_array_of( last_expression_result.value().get()), - arguments.expected_type, expression, + arguments.get_expected(), expression, *sources_manager.get_error_log()); } // IN PROGRESS @@ -338,8 +341,9 @@ nodes::TypeCheckResult type_check_return(const nodes::Return &expression, SourcesManager &sources_manager, State &state, const Arguments &arguments) { - auto returned_result = type_check_expression( - *expression.get_expression(), sources_manager, state, Arguments{}); + auto returned_result = + type_check_expression(*expression.get_expression(), sources_manager, + state, Arguments::nothing()); if (returned_result.is_invalid()) { return returned_result; @@ -369,7 +373,7 @@ nodes::TypeCheckResult type_check_return(const nodes::Return &expression, return type_same_to_expected( sources_manager.get_type_storage()->primitive_type( builtin::types::Type::UNIT), - arguments.expected_type, expression, *sources_manager.get_error_log()); + arguments.get_expected(), expression, *sources_manager.get_error_log()); } // TODO @@ -377,7 +381,7 @@ nodes::TypeCheckResult type_check_name_definition(const nodes::NameDefinition &expression, SourcesManager &sources_manager, State &state, const Arguments &arguments) { - if (!arguments.expected_type.has_value()) { + if (!arguments.get_expected().has_value()) { sources_manager.get_error_log()->add_error( error_handling::ErrorLog::ErrorMessage( expression, "Can't deduce type of new variable from context", @@ -386,7 +390,7 @@ type_check_name_definition(const nodes::NameDefinition &expression, // defined name modifier should be -> (or contain -> ??) // TODO: deal with ...|...|... modifiers - const auto &expected_type = arguments.expected_type.value(); + const auto expected_type = arguments.get_expected().value(); if (!expected_type.get()->is_modifier( nodes::Modifier::OUT)) { // TODO: utils::modifier_contains_OUT sources_manager.get_error_log()->add_error( @@ -431,7 +435,7 @@ nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression, // TODO: modifier checks ?? return type_same_to_expected(value_result.get().get()->get_parameter_proxy(0), - arguments.expected_type, expression, + arguments.get_expected(), expression, *sources_manager.get_error_log()); } @@ -457,7 +461,7 @@ nodes::TypeCheckResult type_check_tuple_access(const nodes::Access &expression, return type_same_to_expected( value_result.get().get()->get_parameter_proxy(index), - arguments.expected_type, expression, *sources_manager.get_error_log()); + arguments.get_expected(), expression, *sources_manager.get_error_log()); } nodes::TypeCheckResult type_check_access(const nodes::Access &expression, @@ -481,15 +485,16 @@ type_check_loop_control(const nodes::LoopControl &expression, return type_same_to_expected( sources_manager.get_type_storage()->primitive_type( builtin::types::Type::UNIT), - arguments.expected_type, expression, *sources_manager.get_error_log()); + arguments.get_expected(), expression, *sources_manager.get_error_log()); } nodes::TypeCheckResult type_check_modifier_expression(const nodes::ModifierExpression &expression, SourcesManager &sources_manager, State &state, const Arguments &arguments) { - auto modified_result = type_check_expression( - *expression.get_expression(), sources_manager, state, Arguments{}); + auto modified_result = + type_check_expression(*expression.get_expression(), sources_manager, + state, Arguments::nothing()); if (modified_result.is_invalid()) { return nodes::TypeCheckResult::construct_invalid_result(); @@ -521,7 +526,7 @@ type_check_modifier_expression(const nodes::ModifierExpression &expression, modified_result.get(), expression.get_modifier())); } - return type_same_to_expected(modified_result.get(), arguments.expected_type, + return type_same_to_expected(modified_result.get(), arguments.get_expected(), expression, *sources_manager.get_error_log()); } // IN PROGRESS @@ -589,7 +594,7 @@ type_check_constructor(const nodes::Constructor &expression, } // TODO: expect types of arguments by type definition return type_same_to_expected(expression.get_type_proxy(), - arguments.expected_type, expression, + arguments.get_expected(), expression, *sources_manager.get_error_log()); // TODO: add <- modifiier to type ?? @@ -600,14 +605,14 @@ nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression, SourcesManager &sources_manager, State &state, const Arguments &arguments) { - if (!arguments.expected_type.has_value()) { + if (!arguments.get_expected().has_value()) { sources_manager.get_error_log()->add_error( error_handling::ErrorLog::ErrorMessage( expression, "Can't deduce type of lambda function from context", error_handling::ErrorType::TYPE_CHECK)); } - const auto &expected_type = arguments.expected_type.value(); + const auto expected_type = arguments.get_expected().value(); if (!expected_type.get()->is_builtin(builtin::types::Type::FUNCTION)) { sources_manager.get_error_log()->add_error( error_handling::ErrorLog::ErrorMessage(