From 63d0335188f6113a2b2a9c19bd9bc12e072ae162 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Wed, 7 Feb 2024 22:45:54 +0300 Subject: [PATCH] fixes, conditions typecheck --- include/nodes/type_nodes.hpp | 2 + src/expression_type_check.cpp | 89 ++++++++++++++++++++++++++--------- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/include/nodes/type_nodes.hpp b/include/nodes/type_nodes.hpp index c61cc0b..d4c0a33 100644 --- a/include/nodes/type_nodes.hpp +++ b/include/nodes/type_nodes.hpp @@ -28,6 +28,8 @@ public: bool operator==(const TypeProxy &other) const; + bool operator!=(const TypeProxy&) const = default; + private: TypeProxy(TypeStorage &type_storage, size_t id) : type_storage_(&type_storage), id_(id) {} diff --git a/src/expression_type_check.cpp b/src/expression_type_check.cpp index 225edbd..40641fa 100644 --- a/src/expression_type_check.cpp +++ b/src/expression_type_check.cpp @@ -87,13 +87,54 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression, const Arguments &arguments) { } // IN PROGRESS -// TODO nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression, SourcesManager &sources_manager, State &state, const Arguments &arguments) { - // TODO: extract functiona argument names + + std::optional expression_result; + + for (size_t i = 0; i < expression.cases_size(); ++i) { + type_check_expression( + *expression.get_case(i).first, sources_manager, state, + Arguments::expect_builtin(builtin::types::Type::BOOL, sources_manager)); + + 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{}}); + + if (!expression_result.has_value() && !case_result.is_invalid()) { + expression_result = std::move(case_result); + } + } + + 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{}}); + } + + if (!expression_result.has_value()) { + sources_manager.get_error_log()->add_error( + error_handling::ErrorLog::ErrorMessage( + expression, "There should be at least one case in if statement", + error_handling::ErrorType::TYPE_CHECK)); + expression_result = nodes::TypeCheckResult::construct_invalid_result(); + } + + // ?????????????????????????? + // TODO: extract function argument names // typecheck in statements ?? + // ?????????????????????????? + + return type_same_to_expected(sources_manager.get_type_storage()->add_array_of( + expression_result.value().get()), + arguments.expected_type, expression, + *sources_manager.get_error_log()); } // IN PROGRESS nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, @@ -102,7 +143,7 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, const Arguments &arguments) { // TODO: ranges ?? - std::optional condition_result; + // std::optional condition_result; std::optional interval_result; @@ -115,23 +156,26 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, case nodes::Loop::LOOP: // infinity loop, no params break; case nodes::Loop::WHILE: - condition_result = type_check_expression( + /*condition_result = */ type_check_expression( *expression.get_condition().value(), sources_manager, state, Arguments::expect_builtin(builtin::types::Type::BOOL, sources_manager)); - if (condition_result.value().is_invalid()) { - return condition_result.value(); - } + // --- type check is independent from loop itself --- + // if (condition_result.value().is_invalid()) { + // return condition_result.value(); + // } + + // --- done in expect --- + // if (!condition_result.value().get().get()->is_builtin( + // builtin::types::Type::BOOL)) { + // sources_manager.get_error_log()->add_error( + // error_handling::ErrorLog::ErrorMessage( + // *expression.get_condition().value(), + // "While loop condition should have type Bool", + // error_handling::ErrorType::TYPE_CHECK)); + // return nodes::TypeCheckResult::construct_invalid_result(); + // } - if (!condition_result.value().get().get()->is_builtin( - builtin::types::Type::BOOL)) { - sources_manager.get_error_log()->add_error( - error_handling::ErrorLog::ErrorMessage( - *expression.get_condition().value(), - "While loop condition should have type Bool", - error_handling::ErrorType::TYPE_CHECK)); - return nodes::TypeCheckResult::construct_invalid_result(); - } break; case nodes::Loop::FOR: // TODO: expect range ?? @@ -141,20 +185,23 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, sources_manager)); if (interval_result.value().is_invalid()) { - return interval_result.value(); + // --- type check is independent from loop itself --- + // return interval_result.value(); + break; } variable_result = type_check_expression( *expression.get_variable().value(), sources_manager, state, Arguments{interval_result.value().get().get()->get_parameter_proxy(0)}); - if (variable_result.value().is_invalid()) { - return variable_result.value(); - } + // --- type check is independent from loop itself --- + // if (variable_result.value().is_invalid()) { + // return variable_result.value(); + // } break; } - if (expression_result.is_invalid()) { + if (expression_result.is_invalid()) { // TODO: log invalid return expression_result; }