diff --git a/lang/type_check/include/basic_type_check.hpp b/lang/type_check/include/basic_type_check.hpp index e5ceb82..ab8eac1 100644 --- a/lang/type_check/include/basic_type_check.hpp +++ b/lang/type_check/include/basic_type_check.hpp @@ -1,13 +1,17 @@ #pragma once #include "basic_nodes.hpp" -#include "sources_manager.hpp" #include "type_check_utils.hpp" namespace type_check { // IN PROGRESS: modifiers ?? -Result check(const nodes::Literal &literal, SourcesManager &sources_manager, - State &state, const Arguments &arguments); + +template <> +struct CheckTask : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; + + Result operator()(const nodes::Literal &literal, Arguments &&arguments); +}; } // namespace type_check diff --git a/lang/type_check/include/expression_type_check.hpp b/lang/type_check/include/expression_type_check.hpp index c8f4153..256997d 100644 --- a/lang/type_check/include/expression_type_check.hpp +++ b/lang/type_check/include/expression_type_check.hpp @@ -2,84 +2,143 @@ #include "expression_nodes.hpp" #include "type_check_utils.hpp" -#include "type_nodes.hpp" -#include "utils.hpp" - -#include // IN PROGRESS namespace type_check { -// TODO: ??? -// TODO: add State to Executor and Task -class CheckTask : public Task { - using Task::Task; +template <> +struct CheckTask : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; Result operator()(const nodes::Expression &expr, - const Arguments &arguments); // check + const Arguments &args) override; }; -Result check(const nodes::Expression &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments); - // --- flow control -Result check(const nodes::Match &expression, SourcesManager &sources_manager, - State &state, const Arguments &arguments); +template <> +struct CheckTask : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; -Result check(const nodes::Condition &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments); + Result operator()(const nodes::Match &expr, const Arguments &args) override; +}; -Result check(const nodes::Loop &expression, SourcesManager &sources_manager, - State &state, const Arguments &arguments); +template <> +struct CheckTask : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; + + Result operator()(const nodes::Condition &expr, + const Arguments &args) override; +}; + +template <> struct CheckTask : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; + + Result operator()(const nodes::Loop &expr, const Arguments &args) override; +}; // --- containers -Result check(const nodes::Container &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments); +template <> +struct CheckTask : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; + + Result CheckArray(const nodes::Container &expr, const Arguments &args); + + Result CheckBlock(const nodes::Container &expr, const Arguments &args); + + Result operator()(const nodes::Container &expr, + const Arguments &args) override; +}; // --- modifiers -Result check(const nodes::Return &expression, SourcesManager &sources_manager, - State &state, const Arguments &arguments); +template <> +struct CheckTask : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; -Result check(const nodes::NameDefinition &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments); + Result operator()(const nodes::Return &expr, const Arguments &args) override; +}; -Result check(const nodes::Access &expression, SourcesManager &sources_manager, - State &state, const Arguments &arguments); +template <> +struct CheckTask + : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; -Result check(const nodes::LoopControl &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments); + Result operator()(const nodes::NameDefinition &expr, + const Arguments &args) override; +}; -Result check(const nodes::ModifierExpression &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments); +template <> +struct CheckTask : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; + + Result CheckArrayAccess(const nodes::Access &expr, const Arguments &args); + + Result CheckTupleAccess(const nodes::Access &expr, const Arguments &args); + + Result operator()(const nodes::Access &expr, const Arguments &args) override; +}; + +template <> +struct CheckTask + : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; + + Result operator()(const nodes::LoopControl &expr, + const Arguments &args) override; +}; + +template <> +struct CheckTask + : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; + + Result operator()(const nodes::ModifierExpression &expr, + const Arguments &args) override; +}; // --- other -Result check(const nodes::NameExpression &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments); +template <> +struct CheckTask + : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; -Result check(const nodes::Constructor &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments); + Result operator()(const nodes::NameExpression &expr, + const Arguments &args) override; +}; -Result check(const nodes::Lambda &expression, SourcesManager &sources_manager, - State &state, const Arguments &arguments); +template <> +struct CheckTask + : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; -Result check(const nodes::Extra &expression, SourcesManager &sources_manager, - State &state, const Arguments &arguments); + Result operator()(const nodes::Constructor &expr, + const Arguments &args) override; +}; -Result check(const nodes::EmptyLines &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments); +template <> +struct CheckTask : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; + + Result operator()(const nodes::Lambda &expr, const Arguments &args) override; +}; + +template <> +struct CheckTask : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; + + Result operator()(const nodes::Extra &expr, const Arguments &args) override; +}; + +template <> +struct CheckTask : public CheckTaskBase { + using CheckTaskBase::CheckTaskBase; + + Result operator()(const nodes::EmptyLines &expr, + const Arguments &args) override; +}; } // namespace type_check diff --git a/lang/type_check/include/type_check_utils.hpp b/lang/type_check/include/type_check_utils.hpp index b2f22dd..0048436 100644 --- a/lang/type_check/include/type_check_utils.hpp +++ b/lang/type_check/include/type_check_utils.hpp @@ -10,11 +10,6 @@ namespace type_check { -using Executor = utils::Executor; -using Task = - utils::Task; - class ContextHolder; class State { @@ -164,20 +159,27 @@ private: // +using Exprs = nodes::ExpressionStorage; +using Types = nodes::TypeStorage; +using Names = names::NameTree; + +using Executor = utils::Executor; + +// + class Arguments { public: Arguments() = default; Arguments expect_builtin(builtin::Type type, Executor &executor) const { Arguments copy(*this); - copy.expected_types_ = { - executor.state().primitive(type)}; + copy.expected_types_ = {executor.state().primitive(type)}; return copy; } Arguments pass_builtin(builtin::Type type, Executor &executor) const { Arguments copy(*this); - copy.passed_type_ = executor.state().primitive(type); + copy.passed_type_ = executor.state().primitive(type); return copy; } @@ -340,4 +342,21 @@ nodes::MaybeTypeProxy get_field_type_by_name(nodes::TypeProxy type, void type_check_error(const std::string &message, const nodes::Node &node, Executor &executor, bool handle_error = true); +// + +template using Task = utils::Task; + +template struct CheckTask { + static_assert(false); +}; + +template struct CheckTaskBase : public Task { + using Task::Task; + + template Result Run(const OtherN &node, const Arguments &args) { + CheckTask task(this->executor); + return task(node, args); + } +}; + } // namespace type_check diff --git a/lang/type_check/src/basic_type_check.cpp b/lang/type_check/src/basic_type_check.cpp index f199229..44d4584 100644 --- a/lang/type_check/src/basic_type_check.cpp +++ b/lang/type_check/src/basic_type_check.cpp @@ -3,44 +3,44 @@ namespace type_check { nodes::TypeProxy get_literal_type(const nodes::Literal &literal, - SourcesManager &sources_manager) { + Executor &executor) { switch (literal.get_any()->index()) { case 0: // float - return sources_manager.types()->primitive(builtin::Type::FLOAT); + return executor.state().primitive(builtin::Type::FLOAT); case 1: // double - return sources_manager.types()->primitive(builtin::Type::DOUBLE); + return executor.state().primitive(builtin::Type::DOUBLE); case 2: // int32_t - return sources_manager.types()->primitive(builtin::Type::INT); + return executor.state().primitive(builtin::Type::INT); case 3: // int64_t - return sources_manager.types()->primitive(builtin::Type::LONG); + return executor.state().primitive(builtin::Type::LONG); case 4: // size_t - return sources_manager.types()->primitive(builtin::Type::INDEX); + return executor.state().primitive(builtin::Type::INDEX); case 5: // std::string - return sources_manager.types()->add_array_of( - sources_manager.types()->primitive(builtin::Type::CHAR)); + return executor.state().add_array_of( + executor.state().primitive(builtin::Type::CHAR)); case 6: // unicode_string - return sources_manager.types()->add_array_of( - sources_manager.types()->primitive(builtin::Type::UNICODE)); + return executor.state().add_array_of( + executor.state().primitive(builtin::Type::UNICODE)); case 7: // char - return sources_manager.types()->primitive(builtin::Type::CHAR); + return executor.state().primitive(builtin::Type::CHAR); case 8: // unicode - return sources_manager.types()->primitive(builtin::Type::UNICODE); + return executor.state().primitive(builtin::Type::UNICODE); case 9: // bool - return sources_manager.types()->primitive(builtin::Type::BOOL); + return executor.state().primitive(builtin::Type::BOOL); case 10: // unit - return sources_manager.types()->primitive(builtin::Type::UNIT); + return executor.state().primitive(builtin::Type::UNIT); case 11: // null - return sources_manager.types()->primitive(builtin::Type::NULL_OPTION); + return executor.state().primitive(builtin::Type::NULL_OPTION); } - error_handling::handle_general_error("Unreachable"); + utils::Assert(true, "Unreachable"); exit(1); // unreachable } -Result check(const nodes::Literal &literal, SourcesManager &sources_manager, - State &, const Arguments &arguments) { - auto const type = get_literal_type(literal, sources_manager); - return type_same_to_expected(type, arguments, literal, sources_manager); +Result CheckTask::operator()(const nodes::Literal &literal, + Arguments &&arguments) { + auto const type = get_literal_type(literal, this->executor); + return type_same_to_expected(type, arguments, literal, this->executor); } } // namespace type_check diff --git a/lang/type_check/src/expression_type_check.cpp b/lang/type_check/src/expression_type_check.cpp index aab879f..56f9539 100644 --- a/lang/type_check/src/expression_type_check.cpp +++ b/lang/type_check/src/expression_type_check.cpp @@ -1,10 +1,7 @@ #include "expression_type_check.hpp" #include "basic_nodes.hpp" -#include "basic_type_check.hpp" #include "builtin_types.hpp" -#include "sources_manager.hpp" #include "type_nodes.hpp" -#include "utils.hpp" // IN PROGRESS @@ -13,26 +10,24 @@ namespace type_check { -Result check(const nodes::Expression &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments) { +Result CheckTask::operator()(const nodes::Expression &expr, + const Arguments &arguments) { return std::visit( - [&sources_manager, &state, &arguments](const auto &arg) -> Result { - return check(arg, sources_manager, state, arguments); + [this, &arguments](const auto &node) -> Result { + return Run(node, arguments); }, - *expression.get_any()); + *expr.get_any()); } // --- flow control -Result check(const nodes::Match &expression, SourcesManager &sources_manager, - State &state, const Arguments &arguments) { - Result value_result = - check(*expression.get_value(), sources_manager, state, Arguments{}); +Result CheckTask::operator()(const nodes::Match &expr, + const Arguments &args) { + Result value_result = Run(*expr.get_value(), {}); // x :=/=: ... if (value_result.is_invalid()) { - type_check_error("Match value is invalid", expression, sources_manager); + type_check_error("Match value is invalid", expr, executor); } MaybeResult expression_result; @@ -40,32 +35,31 @@ Result check(const nodes::Match &expression, SourcesManager &sources_manager, bool at_least_one_case_with_expression = false; bool at_least_one_case_without_expression = false; - for (size_t i = 0; i < expression.cases_size(); ++i) { - const nodes::Match::Case *current_case = expression.get_case(i); + for (size_t i = 0; i < expr.cases_size(); ++i) { + const nodes::Match::Case *current_case = expr.get_case(i); // :=/=: x ... - check(*current_case->get_value(), sources_manager, state, - Arguments{} - .expect_builtin(builtin::Type::BOOL, sources_manager) - .pass(value_result.is_invalid() - ? nodes::MaybeTypeProxy{} - : expression_result.value().get())); + Run(*current_case->get_value(), + Arguments{} + .expect_builtin(builtin::Type::BOOL, executor) + .pass(value_result.is_invalid() ? nodes::MaybeTypeProxy{} + : expression_result.value().get())); // TODO: use type modifiers ?? // ... ?? x ... if (current_case->get_condition().has_value()) { - check(*current_case->get_condition().value(), sources_manager, state, - Arguments{}.expect_builtin(builtin::Type::BOOL, sources_manager)); + Run(*current_case->get_condition().value(), + Arguments{}.expect_builtin(builtin::Type::BOOL, executor)); } // ... -> x if (current_case->get_expression().has_value()) { at_least_one_case_with_expression = true; Result case_result = - check(*current_case->get_condition().value(), sources_manager, state, - Arguments{}.expect(expression_result.has_value() - ? expression_result.value().get() - : nodes::MaybeTypeProxy{})); + Run(*current_case->get_condition().value(), + Arguments{}.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); @@ -78,76 +72,73 @@ Result check(const nodes::Match &expression, SourcesManager &sources_manager, if (at_least_one_case_with_expression && at_least_one_case_without_expression) { type_check_error( - "All cases should be with or without expression at the same time", - expression, sources_manager); + "All cases should be with or without expression at the same time", expr, + executor); expression_result = Result::invalid(); } if (!expression_result.has_value()) { - expression_result = - Result{sources_manager.types()->primitive(builtin::Type::UNIT)}; + expression_result = Result{state().primitive(builtin::Type::UNIT)}; } return type_check_from_arguments( - sources_manager.types()->add_array_of(expression_result.value().get()), - arguments, expression, sources_manager); + state().add_array_of(expression_result.value().get()), args, expr, + executor); } -Result check(const nodes::Condition &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments) { +Result CheckTask::operator()(const nodes::Condition &expr, + const Arguments &args) { MaybeResult expression_result; - for (size_t i = 0; i < expression.cases_size(); ++i) { - check(*expression.get_case(i).first, sources_manager, state, - Arguments{}.expect_builtin(builtin::Type::BOOL, sources_manager)); + for (size_t i = 0; i < expr.cases_size(); ++i) { + Run(*expr.get_case(i).first, + Arguments{}.expect_builtin(builtin::Type::BOOL, executor)); Result case_result = - check(*expression.get_case(i).first, sources_manager, state, - Arguments{}.expect(expression_result.has_value() - ? expression_result.value().get() - : nodes::MaybeTypeProxy{})); + Run(*expr.get_case(i).first, + Arguments{}.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); } } - if (expression.get_else_case().has_value()) { - check(*expression.get_else_case().value(), sources_manager, state, - Arguments{}.expect(expression_result.has_value() - ? expression_result.value().get() - : nodes::MaybeTypeProxy{})); + if (expr.get_else_case().has_value()) { + Run(*expr.get_else_case().value(), + Arguments{}.expect(expression_result.has_value() + ? expression_result.value().get() + : nodes::MaybeTypeProxy{})); } if (!expression_result.has_value()) { - type_check_error("There should be at least one case in if statement", - expression, sources_manager); + type_check_error("There should be at least one case in if statement", expr, + executor); expression_result = Result::invalid(); } return type_check_from_arguments( - sources_manager.types()->add_array_of(expression_result.value().get()), - arguments, expression, sources_manager); + state().add_array_of(expression_result.value().get()), args, expr, + executor); } -Result check(const nodes::Loop &expression, SourcesManager &sources_manager, - State &state, const Arguments &arguments) { +Result CheckTask::operator()(const nodes::Loop &expr, + const Arguments &args) { // TODO: ranges ?? MaybeResult interval_result; MaybeResult variable_result; - Result expression_result = - check(*expression.get_expression(), sources_manager, state, Arguments{}); + Result expression_result = Run(*expr.get_expression(), {}); - switch (expression.get_type()) { + switch (expr.get_type()) { case nodes::Loop::LOOP: // infinity loop, no params break; case nodes::Loop::WHILE: - check(*expression.get_condition().value(), sources_manager, state, - Arguments{}.expect_builtin(builtin::Type::BOOL, sources_manager)); + Run(*expr.get_condition().value(), + Arguments{}.expect_builtin(builtin::Type::BOOL, executor)); // --- type check is independent from loop itself --- // if (condition_result.value().is_invalid()) { @@ -157,9 +148,9 @@ Result check(const nodes::Loop &expression, SourcesManager &sources_manager, break; case nodes::Loop::FOR: // TODO: expect range ?? - interval_result = check( - *expression.get_interval().value(), sources_manager, state, - Arguments{}.expect_builtin(builtin::Type::ARRAY, sources_manager)); + interval_result = + Run(*expr.get_interval().value(), + Arguments{}.expect_builtin(builtin::Type::ARRAY, executor)); if (interval_result.value().is_invalid()) { // --- type check is independent from loop itself --- @@ -168,9 +159,9 @@ Result check(const nodes::Loop &expression, SourcesManager &sources_manager, } variable_result = - check(*expression.get_variable().value(), sources_manager, state, - Arguments{}.expect( - interval_result.value().get().get()->get_parameter_proxy(0))); + Run(*expr.get_variable().value(), + Arguments{}.expect( + interval_result.value().get().get()->get_parameter_proxy(0))); // --- type check is independent from loop itself --- // if (variable_result.value().is_invalid()) { @@ -186,28 +177,26 @@ Result check(const nodes::Loop &expression, SourcesManager &sources_manager, // TODO: modifier checks ??, modifiers ?? return type_check_from_arguments( - sources_manager.types()->add_array_of(expression_result.get()), arguments, - expression, sources_manager); + state().add_array_of(expression_result.get()), args, expr, + executor); } // IN PROGRESS // --- containers -Result type_check_array(const nodes::Container &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments) { +Result CheckTask::CheckArray(const nodes::Container &expr, + const Arguments &args) { MaybeResult last_expression_result; - for (size_t i = 0; i < expression.expressions_size(); ++i) { + for (size_t i = 0; i < expr.expressions_size(); ++i) { // elements should have same type, but type is not expected - auto expression_result = check(*expression.get_expression(i), - sources_manager, state, Arguments{}); + auto expression_result = Run(*expr.get_expression(i), {}); if (!last_expression_result.has_value()) { last_expression_result = expression_result; } else { if (last_expression_result.value().get() != expression_result.get()) { type_check_error("Elements in array should have same type", - *expression.get_expression(i), sources_manager); + *expr.get_expression(i), executor); // return TypeCheckResult::construct_invalid_result(); // max // possible checks, so no return } @@ -215,129 +204,121 @@ Result type_check_array(const nodes::Container &expression, } if (!last_expression_result.has_value()) { - type_check_error("Array with zero elements", expression, sources_manager); + type_check_error("Array with zero elements", expr, executor); return Result::invalid(); } - return type_check_from_arguments(sources_manager.types()->add_array_of( - last_expression_result.value().get()), - arguments, expression, sources_manager); + return type_check_from_arguments( + state().add_array_of(last_expression_result.value().get()), args, + expr, executor); } -Result type_check_block(const nodes::Container &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments) { +Result CheckTask::CheckBlock(const nodes::Container &expr, + const Arguments &args) { nodes::MaybeTypeProxy context_exit_type; { ContextHolder context_holder( - state, expression, *sources_manager.errors(), + state(), expr, &context_exit_type); // TODO: is brought type returned - for (size_t i = 0; i < expression.expressions_size(); ++i) { + for (size_t i = 0; i < expr.expressions_size(); ++i) { // result types in block are discarded - check(*expression.get_expression(i), sources_manager, state, Arguments{}); + Run(*expr.get_expression(i), {}); } } Result block_brought_type = context_exit_type.has_value() ? Result(context_exit_type.value()) - : Result(sources_manager.types()->primitive(builtin::Type::UNIT)); + : Result(state().primitive(builtin::Type::UNIT)); return type_check_from_arguments( - sources_manager.types()->add_array_of(block_brought_type.get()), - arguments, expression, sources_manager); + state().add_array_of(block_brought_type.get()), args, expr, + executor); } -Result check(const nodes::Container &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments) { - switch (expression.get_type()) { +Result CheckTask::operator()(const nodes::Container &expr, + const Arguments &args) { + switch (expr.get_type()) { case nodes::Container::ARRAY: - return type_check_array(expression, sources_manager, state, arguments); + return CheckArray(expr, args); case nodes::Container::BLOCK: - return type_check_block(expression, sources_manager, state, arguments); + return CheckBlock(expr, args); } } // --- modifiers -Result check(const nodes::Return &expression, SourcesManager &sources_manager, - State &state, const Arguments &arguments) { - auto returned_result = - check(*expression.get_expression(), sources_manager, state, Arguments{}); +Result CheckTask::operator()(const nodes::Return &expr, + const Arguments &args) { + auto returned_result = Run(*expr.get_expression(), {}); if (returned_result.is_invalid()) { return returned_result; } - switch (expression.get_type()) { + switch (expr.get_type()) { case nodes::Return::BRING: - if (state.bring_type(returned_result.get())) { - type_check_error("Different brought type to current one", expression, - sources_manager); + if (state().bring_type(returned_result.get())) { + type_check_error("Different brought type to current one", expr, executor); return Result::invalid(); } break; case nodes::Return::RETURN: - if (!state.return_type(returned_result.get())) { - type_check_error("Different returned type to current one", expression, - sources_manager); + if (!state().return_type(returned_result.get())) { + type_check_error("Different returned type to current one", expr, + executor); return Result::invalid(); } break; } return type_check_from_arguments( - sources_manager.types()->primitive(builtin::Type::UNIT), arguments, - expression, sources_manager); + state().primitive(builtin::Type::UNIT), args, expr, executor); } // TODO: warning if name is same to package prefix, function prefix, etc. ?? -Result check(const nodes::NameDefinition &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments) { - if (!arguments.get_passed().has_value()) { - type_check_error("Can't deduce type of new variable from context", - expression, sources_manager); +Result +CheckTask::operator()(const nodes::NameDefinition &expr, + const Arguments &args) { + if (!args.get_passed().has_value()) { + type_check_error("Can't deduce type of new variable from context", expr, + executor); } // assigned type shold be one of <-, <>, -- (can't be ->) - const auto variable_type = arguments.get_passed().value(); + const auto variable_type = args.get_passed().value(); if (nodes::utils::modifier_contains_OUT( variable_type.get() ->get_modifier())) { // TODO: utils::modifier_contains_OUT - type_check_error("Variable can't be assigned from out (->) value", - expression, sources_manager); + type_check_error("Variable can't be assigned from out (->) value", expr, + executor); } // variable accessible by reference by default ?? - sources_manager.types()->add_modification_of(variable_type, - nodes::Modifier::REF); + state().add_modification_of(variable_type, nodes::Modifier::REF); - if (!state.insert_variable(*expression.get_name()->get(), variable_type, - expression.get_modifier())) { - type_check_error("Variable is already defined in this context", expression, - sources_manager); + if (!state().insert_variable(*expr.get_name()->get(), variable_type, + expr.get_modifier())) { + type_check_error("Variable is already defined in this context", expr, + executor); } // Return BOOL as any := / =: expression return type_check_from_arguments( - sources_manager.types()->primitive(builtin::Type::BOOL), arguments, - expression, sources_manager); + state().primitive(builtin::Type::BOOL), args, expr, executor); } -Result type_check_array_access(const nodes::Access &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments) { +Result CheckTask::CheckArrayAccess(const nodes::Access &expr, + const Arguments &args) { auto index_result = - check(*expression.get_index(), sources_manager, state, - Arguments{}.expect_builtin(builtin::Type::INDEX, sources_manager)); + Run(*expr.get_index(), + Arguments{}.expect_builtin(builtin::Type::INDEX, executor)); auto value_result = - check(*expression.get_value(), sources_manager, state, - Arguments{}.expect_builtin(builtin::Type::ARRAY, sources_manager)); + Run(*expr.get_value(), + Arguments{}.expect_builtin(builtin::Type::ARRAY, executor)); if (index_result.is_invalid()) { return index_result; @@ -350,22 +331,20 @@ Result type_check_array_access(const nodes::Access &expression, // TODO: modifier checks ?? return type_check_from_arguments( - value_result.get().get()->get_parameter_proxy(0), arguments, expression, - sources_manager); + value_result.get().get()->get_parameter_proxy(0), args, expr, executor); } -Result type_check_tuple_access(const nodes::Access &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments) { +Result CheckTask::CheckTupleAccess(const nodes::Access &expr, + const Arguments &args) { auto value_result = - check(*expression.get_value(), sources_manager, state, - Arguments{}.expect_builtin(builtin::Type::TUPLE, sources_manager)); + Run(*expr.get_value(), + Arguments{}.expect_builtin(builtin::Type::TUPLE, executor)); if (value_result.is_invalid()) { return value_result; } - size_t index = *expression.get_index() + size_t index = *expr.get_index() ->get() .value() ->get() // Index type @@ -374,46 +353,40 @@ Result type_check_tuple_access(const nodes::Access &expression, // TODO: modifier checks ?? return type_check_from_arguments( - value_result.get().get()->get_parameter_proxy(index), arguments, - expression, sources_manager); + value_result.get().get()->get_parameter_proxy(index), args, expr, + executor); } -Result check(const nodes::Access &expression, SourcesManager &sources_manager, - State &state, const Arguments &arguments) { - switch (expression.get_type()) { +Result CheckTask::operator()(const nodes::Access &expr, + const Arguments &args) { + switch (expr.get_type()) { case nodes::Access::ARRAY: - return type_check_array_access(expression, sources_manager, state, - arguments); + return CheckArrayAccess(expr, args); case nodes::Access::TUPLE: - return type_check_tuple_access(expression, sources_manager, state, - arguments); + return CheckTupleAccess(expr, args); } } -Result check(const nodes::LoopControl &expression, - SourcesManager &sources_manager, State &, - const Arguments &arguments) { +Result CheckTask::operator()(const nodes::LoopControl &expr, + const Arguments &args) { return type_check_from_arguments( - sources_manager.types()->primitive(builtin::Type::UNIT), arguments, - expression, sources_manager); + state().primitive(builtin::Type::UNIT), args, expr, executor); } -Result check(const nodes::ModifierExpression &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments) { - auto modified_result = - check(*expression.get_expression(), sources_manager, state, Arguments{}); +Result CheckTask::operator()( + const nodes::ModifierExpression &expr, const Arguments &args) { + auto modified_result = Run(*expr.get_expression(), {}); if (modified_result.is_invalid()) { return Result::invalid(); } if (nodes::utils::is_suffix_modifier( - expression.get_modifier())) { // optional, result - // '?' - open optional / result in -> - // (execute or not execute pattern - // matching expression) / (value / - // return) (TODO: alternative for bring) + expr.get_modifier())) { // optional, result + // '?' - open optional / result in -> + // (execute or not execute pattern + // matching expression) / (value / + // return) (TODO: alternative for bring) // '!' - open optional / result -> value / panic @@ -424,29 +397,27 @@ Result check(const nodes::ModifierExpression &expression, modified_result.set(modified_result.get().get()->get_parameter_proxy(0)); break; default: - type_check_error("Can unwrap only Optional or Result", expression, - sources_manager); + type_check_error("Can unwrap only Optional or Result", expr, executor); return Result::invalid(); } } else { // TODO: check that modifier can be applied - modified_result.set(sources_manager.types()->add_modification_of( - modified_result.get(), expression.get_modifier())); + modified_result.set(state().add_modification_of( + modified_result.get(), expr.get_modifier())); } - return type_check_from_arguments(modified_result.get(), arguments, expression, - sources_manager); + return type_check_from_arguments(modified_result.get(), args, expr, executor); } // IN PROGRESS // --- other // TODO -Result check(const nodes::NameExpression &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments) { +Result +CheckTask::operator()(const nodes::NameExpression &expr, + const Arguments &args) { // TODO: constraints ?? - const auto name = expression.get_name(); + const auto name = expr.get_name(); { const auto fragments = name->get_fragments(); @@ -459,7 +430,7 @@ Result check(const nodes::NameExpression &expression, 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; @@ -483,8 +454,8 @@ Result check(const nodes::NameExpression &expression, // TODO: switch by type types: Variant, Tuple, ... // Tuple -> try to find field // Others -> try to open / builtin fields ? - const auto maybe_field_type = get_field_type_by_name( - type, *fragments[i].get(), expression, sources_manager); + const auto maybe_field_type = + get_field_type_by_name(type, *fragments[i].get(), expr, executor); if (maybe_field_type.has_value()) { type = maybe_field_type.value(); @@ -506,7 +477,7 @@ Result check(const nodes::NameExpression &expression, // TODO: check, if there is variable with this name // TODO: check var + fields const auto maybe_function_definition = - find_name_definition(*name->get(), expression, sources_manager); + find_name_definition(*name->get(), expr, executor); if (!maybe_function_definition.has_value()) { return Result::invalid(); } @@ -516,7 +487,7 @@ Result check(const nodes::NameExpression &expression, // TODO: count passed type, if needed // 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_given = expr.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 @@ -528,7 +499,7 @@ Result check(const nodes::NameExpression &expression, ? (" or " + std::to_string(arguments_defined - 1)) : ""} + ")", - expression, sources_manager); + expr, executor); return Result::invalid(); // TODO: try return correct type (function return type), when possible } @@ -544,11 +515,11 @@ Result check(const nodes::NameExpression &expression, if (!argument->get_type().has_value()) { type_check_error("Function argument type is not defined for argument " + std::to_string(i), - expression, sources_manager); + expr, executor); continue; } - const auto annotation = expression.get_argument_annotation(i); + const auto annotation = expr.get_argument_annotation(i); const auto expected_annotation = argument->get_annotation(); if (annotation.has_value() != expected_annotation.has_value()) { @@ -556,7 +527,7 @@ Result check(const nodes::NameExpression &expression, std::string{expected_annotation.has_value() ? *expected_annotation.value() : "[none]"}, - *expression.get_argument_value(i), sources_manager); + *expr.get_argument_value(i), executor); } if (annotation.has_value() && @@ -564,18 +535,18 @@ Result check(const nodes::NameExpression &expression, type_check_error( "Wrong function argument type annotation: " + *annotation.value() + " instead of " + *expected_annotation.value(), - *expression.get_argument_value(i), sources_manager); + *expr.get_argument_value(i), executor); } function_argument_results.push_back( - check(*expression.get_argument_value(i), sources_manager, state, - Arguments{}.expect(argument->get_type_proxy().value()))); + Run(*expr.get_argument_value(i), + Arguments{}.expect(argument->get_type_proxy().value()))); } if (function_definition->arguments_size() == 0) { type_check_error( - "Function arguments size is zero. Returned type is not defined", - expression, sources_manager); + "Function arguments size is zero. Returned type is not defined", expr, + executor); return Result::invalid(); } @@ -589,31 +560,30 @@ Result check(const nodes::NameExpression &expression, // TODO: invert modifier ?? if (!returned->get_type().has_value()) { type_check_error( - "Function argument type is not defined for returned type", expression, - sources_manager); + "Function argument type is not defined for returned type", expr, + executor); return Result::invalid(); } // TODO: invert modifier ?? // TODO: generic types should be deduced from arguments - return type_check_from_arguments(returned->get_type_proxy().value(), - arguments, expression, sources_manager); + return type_check_from_arguments(returned->get_type_proxy().value(), args, + expr, executor); } // checks for universal call syntax ?? - // TODO: riturn result + // TODO: return result } // IN PROGRESS // TODO -Result check(const nodes::Constructor &expression, - SourcesManager &sources_manager, State &state, - const Arguments &arguments) { +Result CheckTask::operator()(const nodes::Constructor &expr, + const Arguments &args) { // TODO: constraints ?? // TODO: use pass type - const auto maybe_type_definition = find_type_definition( - *expression.get_type()->get_name()->get(), expression, sources_manager); + const auto maybe_type_definition = + find_type_definition(*expr.get_type()->get_name()->get(), expr, executor); if (!maybe_type_definition.has_value()) { return Result::invalid(); } @@ -622,7 +592,7 @@ Result check(const nodes::Constructor &expression, if (!type_definition->get_type().has_value()) { type_check_error( "Type defenition for constructor type not found (declaration only)", - expression, sources_manager); + expr, executor); return Result::invalid(); } @@ -634,9 +604,9 @@ Result check(const nodes::Constructor &expression, // TODO: work with different parametric types: tuple, variant, ... - if (expression.arguments_size() == 0) { - type_check_error("Number of type constructor arguments should be > 0", - expression, sources_manager); + if (expr.arguments_size() == 0) { + type_check_error("Number of type constructor arguments should be > 0", expr, + executor); return Result::invalid(); // TODO: try return correct type (constructor's type), when possible (not // generic) @@ -649,13 +619,13 @@ Result check(const nodes::Constructor &expression, { // check arguments size, ets. switch (builtin_type) { case builtin::Type::TUPLE: - if (expression.arguments_size() != type.get()->parameters_size()) { + if (expr.arguments_size() != type.get()->parameters_size()) { type_check_error( "Number of type constructor arguments is different from expected " "(" + - std::to_string(expression.arguments_size()) + " instead of " + + std::to_string(expr.arguments_size()) + " instead of " + std::to_string(type.get()->parameters_size()) + ")", - expression, sources_manager); + expr, executor); return Result::invalid(); // TODO: try return correct type (constructor's type), when possible // (not generic) @@ -667,11 +637,11 @@ Result check(const nodes::Constructor &expression, case builtin::Type::ERROR: case builtin::Type::FUNCTION: case builtin::Type::NONE: - if (expression.arguments_size() != 1) { // TODO: better to_string + if (expr.arguments_size() != 1) { // TODO: better to_string type_check_error("Number of type constructor arguments should be = 1 " "(builtin type " + std::to_string(uint(builtin_type)) + ")", - expression, sources_manager); + expr, executor); return Result::invalid(); // TODO: try return correct type (constructor's type), when possible // (not generic) @@ -684,8 +654,8 @@ Result check(const nodes::Constructor &expression, if (builtin::types::get_parameters_count(builtin_type).has_value() && type.get()->parameters_size() != builtin::types::get_parameters_count(builtin_type).value()) { - type_check_error("Wrong amount of parametars for builtin type", - expression, sources_manager); + type_check_error("Wrong amount of parametars for builtin type", expr, + executor); return Result::invalid(); // TODO: try return correct type (constructor's type), when possible (not @@ -697,12 +667,12 @@ Result check(const nodes::Constructor &expression, { // check annotations const auto check_same_annotation = - [&expression, &sources_manager]( + [&expr, &executor = this->executor]( size_t i, std::optional expected_annotation, bool log_errors) { bool is_same = true; - const auto annotation = expression.get_argument_annotation(i); + const auto annotation = expr.get_argument_annotation(i); if (annotation.has_value() != expected_annotation.has_value()) { if (log_errors) { @@ -711,7 +681,7 @@ Result check(const nodes::Constructor &expression, std::string{expected_annotation.has_value() ? *expected_annotation.value() : "[none]"}, - *expression.get_argument_value(i), sources_manager); + *expr.get_argument_value(i), executor); } is_same = false; } @@ -722,8 +692,7 @@ Result check(const nodes::Constructor &expression, type_check_error("Wrong function argument type annotation: " + *annotation.value() + " instead of " + *expected_annotation.value(), - *expression.get_argument_value(i), - sources_manager); + *expr.get_argument_value(i), executor); } is_same = false; @@ -733,12 +702,12 @@ Result check(const nodes::Constructor &expression, }; const auto check_no_annotation = - [&expression, &sources_manager](size_t i, bool log_errors) { - if (expression.get_argument_annotation(i).has_value()) { + [&expr, &executor = this->executor](size_t i, bool log_errors) { + if (expr.get_argument_annotation(i).has_value()) { if (log_errors) { type_check_error( "Type constructor argument annotation not expected there", - *expression.get_argument_value(i), sources_manager); + *expr.get_argument_value(i), executor); } return false; } @@ -747,7 +716,7 @@ Result check(const nodes::Constructor &expression, switch (builtin_type) { case builtin::Type::TUPLE: - for (size_t i = 0; i < expression.arguments_size(); ++i) { + for (size_t i = 0; i < expr.arguments_size(); ++i) { check_same_annotation(i, type.get()->get_parameter(i)->get_annotation(), true /*log errors*/); } @@ -767,7 +736,7 @@ Result check(const nodes::Constructor &expression, !check_no_annotation(0, false /*do not log errors*/)) { type_check_error("Wrong type constructor argument annotation in " "constructor of variant type", - *expression.get_argument_value(0), sources_manager); + *expr.get_argument_value(0), executor); } break; case builtin::Type::ERROR: // no anotations ?? @@ -788,89 +757,85 @@ Result check(const nodes::Constructor &expression, { // type check arguments switch (builtin_type) { case builtin::Type::TUPLE: - for (size_t i = 0; i < expression.arguments_size(); ++i) { - check(*expression.get_argument_value(i), sources_manager, state, - Arguments{}.expect(type.get()->get_parameter_proxy(i))); + for (size_t i = 0; i < expr.arguments_size(); ++i) { + Run(*expr.get_argument_value(i), + Arguments{}.expect(type.get()->get_parameter_proxy(i))); } break; case builtin::Type::VARIANT: if (chosen_variant_option.has_value()) { - check(*expression.get_argument_value(0), sources_manager, state, - Arguments{}.expect(type.get()->get_parameter_proxy( - chosen_variant_option.value()))); + Run(*expr.get_argument_value(0), + Arguments{}.expect(type.get()->get_parameter_proxy( + chosen_variant_option.value()))); } else { // TODO: error, if there is more then one possible variant in // answer nodes::TypeProxies possible_options; for (size_t i = 0; i < type.get()->parameters_size(); ++i) { possible_options.push_back(type.get()->get_parameter_proxy(i)); } - check(*expression.get_argument_value(0), sources_manager, state, - Arguments{}.expect(possible_options)); + Run(*expr.get_argument_value(0), Arguments{}.expect(possible_options)); } break; case builtin::Type::OPTIONAL: // first parameter or NULL - check(*expression.get_argument_value(0), sources_manager, state, - Arguments{}.expect({type.get()->get_parameter_proxy(0), - sources_manager.types()->primitive( - builtin::Type::NULL_OPTION)})); + Run(*expr.get_argument_value(0), + Arguments{}.expect( + {type.get()->get_parameter_proxy(0), + state().primitive(builtin::Type::NULL_OPTION)})); break; case builtin::Type::RESULT: // first parameter or ERROR[second parameter] - check(*expression.get_argument_value(0), sources_manager, state, - Arguments{}.expect({type.get()->get_parameter_proxy(0), - sources_manager.types()->add_error_of( - type.get()->get_parameter_proxy(1))})); + Run(*expr.get_argument_value(0), + Arguments{}.expect({type.get()->get_parameter_proxy(0), + state().add_error_of( + type.get()->get_parameter_proxy(1))})); break; case builtin::Type::ERROR: // first parameter - check(*expression.get_argument_value(0), sources_manager, state, - Arguments{}.expect(type.get()->get_parameter_proxy(0))); + Run(*expr.get_argument_value(0), + Arguments{}.expect(type.get()->get_parameter_proxy(0))); break; case builtin::Type::FUNCTION: case builtin::Type::NONE: // type itself - check(*expression.get_argument_value(0), sources_manager, state, - Arguments{}.expect(type)); + Run(*expr.get_argument_value(0), Arguments{}.expect(type)); break; default: // array, basic types - type_check_error("Type can't be constructed", expression, - sources_manager); + type_check_error("Type can't be constructed", expr, executor); break; } } // TODO: deduce generic parts in type - return type_check_from_arguments(expression.get_type_proxy(), arguments, - expression, sources_manager); + return type_check_from_arguments(expr.get_type_proxy(), args, expr, executor); // TODO: add <- modifiier to type ?? } // IN PROGRESS // TODO -Result check(const nodes::Lambda &expression, SourcesManager &sources_manager, - State &state, const Arguments &arguments) { - if (arguments.get_expected().empty()) { +Result CheckTask::operator()(const nodes::Lambda &expr, + const Arguments &args) { + if (args.get_expected().empty()) { type_check_error("Can't deduce type of lambda function from context: no " "one type expected", - expression, sources_manager); + expr, executor); } - if (arguments.get_expected().size() != + if (args.get_expected().size() != 1) { // TODO: check if only one function argument type_check_error("Can't deduce type of lambda function from context; too " "much possible types", - expression, sources_manager); + expr, executor); } - const auto expected_type = arguments.get_expected().front(); + const auto expected_type = args.get_expected().front(); if (!expected_type.get()->is_builtin(builtin::Type::FUNCTION)) { - type_check_error("Type of lambda function should be function", expression, - sources_manager); + type_check_error("Type of lambda function should be function", expr, + executor); } // TODO: deal with return type (+1 sometimes), etc - const auto arguments_given = expression.arguments_size(); + const auto arguments_given = expr.arguments_size(); const auto arguments_defined = expected_type.get()->parameters_size(); if (arguments_given != arguments_defined) { type_check_error( @@ -881,43 +846,43 @@ Result check(const nodes::Lambda &expression, SourcesManager &sources_manager, ? (" or " + std::to_string(arguments_defined - 1)) : ""} + ")", - expression, sources_manager); + expr, executor); } // TODO: set another context (for expression typecheck and vars) for (size_t i = 0; i < arguments_given; ++i) { - if (!state.insert_variable(*expression.get_argument(i)->get(), - expected_type.get()->get_parameter_proxy(i), - nodes::NameDefinition::Modifier::LET)) { + if (!state().insert_variable( + *expr.get_argument(i)->get(), + expected_type.get()->get_parameter_proxy(i), + nodes::NameDefinition::Modifier::LET)) { // TODO: which modifier ?? - type_check_error("Variable is already defined in this context", - expression, sources_manager); + type_check_error("Variable is already defined in this context", expr, + executor); } } // TODO: out type is can be not last if (arguments_given + 1 == arguments_defined) { - check(*expression.get_expression(), sources_manager, state, - Arguments{}.expect( - expected_type.get()->get_parameter_proxy(arguments_defined - 1))); + Run(*expr.get_expression(), + Arguments{}.expect( + expected_type.get()->get_parameter_proxy(arguments_defined - 1))); } // TODO: needed ?? (only passed type check required ??) - return type_check_from_arguments(expected_type, arguments, expression, - sources_manager); + return type_check_from_arguments(expected_type, args, expr, executor); } // IN PROGRESS -Result check(const nodes::Extra &, SourcesManager &sources_manager, State &, - const Arguments &) { +Result CheckTask::operator()(const nodes::Extra &, + const Arguments &) { - return Result(sources_manager.types()->primitive(builtin::Type::UNIT)); + return Result(state().primitive(builtin::Type::UNIT)); } -Result check(const nodes::EmptyLines &, SourcesManager &sources_manager, - State &, const Arguments &) { +Result CheckTask::operator()(const nodes::EmptyLines &, + const Arguments &) { - return Result(sources_manager.types()->primitive(builtin::Type::UNIT)); + return Result(state().primitive(builtin::Type::UNIT)); } } // namespace type_check diff --git a/lang/type_check/src/type_check_utils.cpp b/lang/type_check/src/type_check_utils.cpp index 546d707..21a121c 100644 --- a/lang/type_check/src/type_check_utils.cpp +++ b/lang/type_check/src/type_check_utils.cpp @@ -20,7 +20,7 @@ nodes::TypeProxy check_same_to_pass_type_in_arguments( logc.Error({{message}} /* TODO: node */); } - return executor.state().primitive(builtin::Type::BOOL); + return executor.state().primitive(builtin::Type::BOOL); } bool check_no_pass_type_in_arguments(const Arguments &arguments, diff --git a/lang/utils/include/executor.hpp b/lang/utils/include/executor.hpp index a1d96b2..ad588ac 100644 --- a/lang/utils/include/executor.hpp +++ b/lang/utils/include/executor.hpp @@ -1,39 +1,27 @@ #pragma once -#include -#include - #include "log.hpp" namespace utils { -template class Task; +template class Task; template class ExecutorState { public: - struct Tag {}; - ExecutorState(State &&state) : state_(std::move(state)) {} - // - - // State &state(Tag) { return state; } - // const State &state(Tag) const { return state; } - protected: State state_; }; template class Executor : public ExecutorState... { - friend class Task; - public: Executor(Log &&log, States &&...states) : ExecutorState(std::move(states))..., log_(std::move(log)) {} // - template T New(Args... args) { + template T Run(Args... args) { return T(*this, args...); } @@ -51,17 +39,22 @@ private: Log log_; }; -template class Task { +template class Task { public: - Task(Executor &executor) : executor(executor) {} + Task(Exec &executor) : executor(executor) {} virtual ~Task() {} // - template T New(Args... args) { - return executor.template New(std::move(args)...); - } + // template Ret Run(const N& node, NArgs&& args) { + // Task task(executor); + // return task(node, std::forward(args)); + // } + + // + + virtual Ret operator()(const Node& node, const Args& args) = 0; // @@ -74,7 +67,7 @@ public: const Log &log() const { return executor.log_; } public: - Executor &executor; + Exec &executor; }; } // namespace utils diff --git a/lang/utils/include/utils.hpp b/lang/utils/include/utils.hpp index 7061251..8e556df 100644 --- a/lang/utils/include/utils.hpp +++ b/lang/utils/include/utils.hpp @@ -2,7 +2,6 @@ #include #include -#include namespace error_handling {