diff --git a/lang/app/sources_manager.hpp b/lang/app/sources_manager.hpp index 436318c..ac56fed 100644 --- a/lang/app/sources_manager.hpp +++ b/lang/app/sources_manager.hpp @@ -20,18 +20,21 @@ using Exprs = nodes::NodeStorage; // nodes::ExprStorage; using Types = nodes::TypeStorage; using Names = names::NameTree; using Positions = core::DependentStorage; +using NodeTypes = + core::DependentStorage; // deduce type for each node using Printer = printers::Printer; // TODO: partial host ?? (part of params are stored in each executor, use if // constexpr requires) (for Printer, State, ...) using ExecutorHost = - core::ExecutorHost; class SourcesManager { public: SourcesManager(Log &&log, Printer &&printer) - : executor_host_(std::move(log), {}, {}, {}, {}, {}, std::move(printer)), + : executor_host_(std::move(log), {}, {}, {}, {}, {}, {}, + std::move(printer)), statements_{} {} void AddFile(const std::string &filename) { diff --git a/lang/builders/include/builders_utils.hpp b/lang/builders/include/builders_utils.hpp index 5c75857..a7da81b 100644 --- a/lang/builders/include/builders_utils.hpp +++ b/lang/builders/include/builders_utils.hpp @@ -55,8 +55,9 @@ template struct BuilderTaskUtils : public Task { return value; } - template Node Build(T value, utils::Pos pos) { - auto id = this->template state().Insert(std::move(value)); + template Node Build(T value, bool is_scoped, utils::Pos pos) { + auto id = + this->template state().Insert({std::move(value), is_scoped}); this->template state().ForceInsert(id, pos); return Ext(id); } diff --git a/lang/builders/include/expression_builders.hpp b/lang/builders/include/expression_builders.hpp index ece199c..b85337b 100644 --- a/lang/builders/include/expression_builders.hpp +++ b/lang/builders/include/expression_builders.hpp @@ -96,7 +96,7 @@ struct BuilderTask // '{' (expression ';')* '}' // or // '[[' expression+ ']]' - Node operator()(const ParserNode &parser_node, const Args &) override { + Node operator()(const ParserNode &parser_node, const Args &args) override { Log::Context logc(executor.log(), Log::Area::kParse); const auto kind = std::is_same_v @@ -117,7 +117,7 @@ struct BuilderTask .kind = kind, .exprs = std::move(exprs), }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } }; @@ -172,7 +172,7 @@ struct BuilderTask // _reference_ expression // or // expression ('?' | '!') - Node operator()(const ParserNode &parser_node, const Args &) override { + Node operator()(const ParserNode &parser_node, const Args &args) override { Log::Context logc(executor.log(), Log::Area::kParse); const size_t modifier_pos = @@ -184,7 +184,7 @@ struct BuilderTask RunOther(parser_node.nth_child(modifier_pos)), .expr = Run(parser_node.nth_named_child(0)), }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } }; diff --git a/lang/builders/src/expression_builders.cpp b/lang/builders/src/expression_builders.cpp index 8d2bf7c..a7e0330 100644 --- a/lang/builders/src/expression_builders.cpp +++ b/lang/builders/src/expression_builders.cpp @@ -91,52 +91,53 @@ Node BuilderTask::operator()(const ParserNode &parser_node, nodes::NameExpression{ .name = RunOther(parser_node), }, - parser_node.get_pos()); // TODO: is_scoped + is_scoped, parser_node.get_pos()); case tokens::Type::CONSTRUCTOR: return Run(parser_node); case tokens::Type::LAMBDA: return Run(parser_node); // --- literals case tokens::Type::FLOAT_LITERAL: - return Build(RunOther(parser_node), + return Build(RunOther(parser_node), is_scoped, parser_node.get_pos()); case tokens::Type::DOUBLE_LITERAL: - return Build(RunOther(parser_node), + return Build(RunOther(parser_node), is_scoped, parser_node.get_pos()); case tokens::Type::INT_LITERAL: - return Build(RunOther(parser_node), + return Build(RunOther(parser_node), is_scoped, parser_node.get_pos()); case tokens::Type::LONG_LITERAL: - return Build(RunOther(parser_node), + return Build(RunOther(parser_node), is_scoped, parser_node.get_pos()); case tokens::Type::INDEX_LITERAL: - return Build(RunOther(parser_node), + return Build(RunOther(parser_node), is_scoped, parser_node.get_pos()); case tokens::Type::STRING_LITERAL: - return Build(RunOther(parser_node), + return Build(RunOther(parser_node), is_scoped, parser_node.get_pos()); case tokens::Type::UNICODE_STRING_LITERAL: return Build(RunOther(parser_node), - parser_node.get_pos()); + is_scoped, parser_node.get_pos()); case tokens::Type::CHAR_LITERAL: - return Build(RunOther(parser_node), + return Build(RunOther(parser_node), is_scoped, parser_node.get_pos()); case tokens::Type::UNICODE_LITERAL: return Build(RunOther(parser_node), - parser_node.get_pos()); + is_scoped, parser_node.get_pos()); case tokens::Type::BOOL_LITERAL: - return Build(RunOther(parser_node), + return Build(RunOther(parser_node), is_scoped, parser_node.get_pos()); case tokens::Type::UNIT_LITERAL: - return Build(RunOther(parser_node), + return Build(RunOther(parser_node), is_scoped, parser_node.get_pos()); case tokens::Type::NULL_LITERAL: - return Build(RunOther(parser_node), + return Build(RunOther(parser_node), is_scoped, parser_node.get_pos()); case tokens::Type::EXTRA: - return Build(RunOther(parser_node), parser_node.get_pos()); + return Build(RunOther(parser_node), is_scoped, + parser_node.get_pos()); case tokens::Type::EMPTY_LINES: - return Build(RunOther(parser_node), + return Build(RunOther(parser_node), is_scoped, parser_node.get_pos()); default: break; @@ -152,7 +153,7 @@ Node BuilderTask::operator()(const ParserNode &parser_node, // (':=' | '=:') expression (('??' | 'if') expression)? (_do_ expression)? Node BuilderTask::operator()(const ParserNode &parser_node, - const Args &) { + const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); std::string case_kind = parser_node.nth_child(0).get_value(); @@ -186,12 +187,12 @@ Node BuilderTask::operator()(const ParserNode &parser_node, ? Run(expression_node.value()) : std::optional(), }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } // expression case+ Node BuilderTask::operator()(const ParserNode &parser_node, - const Args &) { + const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); std::vector cases; // TODO @@ -209,13 +210,13 @@ Node BuilderTask::operator()(const ParserNode &parser_node, 0)), // TODO: is_scoped info (always false ??) .cases = std::move(cases), }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } // ('??' | 'if') expression _do_ expression (('!!' | 'elif') expression _do_ // expression)* (('!!=>', 'else') expression)? Node BuilderTask::operator()(const ParserNode &parser_node, - const Args &) { + const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); size_t named_child_count = parser_node.named_child_count(); @@ -243,31 +244,31 @@ Node BuilderTask::operator()(const ParserNode &parser_node, named_child_count - 1)) : std::optional(), }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } // ('@' | 'for') (expression | expression ':' expression)? _do_ expression Node BuilderTask::operator()(const ParserNode &parser_node, - const Args &) { + const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); size_t named_child_count = parser_node.named_child_count(); if (named_child_count == 1) { // body return Build(nodes::Loop(Run(parser_node.nth_named_child(0))), - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } else if (named_child_count == 2) { // condition, // body return Build(nodes::Loop(Run(parser_node.nth_named_child(0)), Run(parser_node.nth_named_child(1))), - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } else if (named_child_count == 3) { // variable, // interval, // body return Build(nodes::Loop(Run(parser_node.nth_named_child(0)), Run(parser_node.nth_named_child(1)), Run(parser_node.nth_named_child(2))), - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } else { logc.Fatal({{"Unexpected named expression amount in loop"}}, parser_node.get_pos()); @@ -281,16 +282,16 @@ Node BuilderTask::operator()(const ParserNode &parser_node, // expression ',' expression Node BuilderTask::operator()( - const ParserNode &parser_node, const Args &) { + const ParserNode &parser_node, const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); - std::vector, nodes::NodeId>> args; + std::vector, nodes::NodeId>> args_nodes; - args.emplace_back(std::nullopt, - Run(parser_node.nth_named_child(0))); + args_nodes.emplace_back(std::nullopt, + Run(parser_node.nth_named_child(0))); - args.emplace_back(std::nullopt, - Run(parser_node.nth_named_child(1))); + args_nodes.emplace_back(std::nullopt, + Run(parser_node.nth_named_child(1))); return Build( nodes::NameExpression{ @@ -300,37 +301,38 @@ Node BuilderTask::operator()( .kind = nodes::Identifier::kSimpleName, .value = ",", }, - .args = std::move(args), + .args = std::move(args_nodes), .prefix = {}, .is_point_call = false, .is_operator_call = true, }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } // expression operator expression Node BuilderTask::operator()( - const ParserNode &parser_node, const Args &) { + const ParserNode &parser_node, const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); auto name_node = parser_node.child_by_field_name("name"); - std::vector, nodes::NodeId>> args; + std::vector, nodes::NodeId>> args_nodes; - args.emplace_back(std::nullopt, - Run(name_node.previous_named_sibling())); + args_nodes.emplace_back(std::nullopt, + Run(name_node.previous_named_sibling())); - args.emplace_back(std::nullopt, Run(name_node.next_named_sibling())); + args_nodes.emplace_back(std::nullopt, + Run(name_node.next_named_sibling())); return Build( nodes::NameExpression{ .name = RunOther(name_node), - .args = std::move(args), + .args = std::move(args_nodes), .prefix = {}, .is_point_call = false, .is_operator_call = true, }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } // --- continers @@ -341,7 +343,7 @@ Node BuilderTask::operator()( // ('return' | 'bring') expression Node BuilderTask::operator()(const ParserNode &parser_node, - const Args &) { + const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); std::string modifier = parser_node.nth_child(0).get_value(); @@ -352,12 +354,12 @@ Node BuilderTask::operator()(const ParserNode &parser_node, : nodes::Return::BRING, .expr = Run(parser_node.nth_named_child(0)), }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } // _var_let_ (simple_name_identifier | placeholder) Node BuilderTask::operator()( - const ParserNode &parser_node, const Args &) { + const ParserNode &parser_node, const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); std::string modifier = parser_node.nth_child(0).get_value(); @@ -371,24 +373,24 @@ Node BuilderTask::operator()( : nodes::NameDefinition::VAR, .name = RunOther(name_node), }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } // IN PROGRESS // expression '[' expression ']' Node BuilderTask::operator()( - const ParserNode &parser_node, const Args &) { + const ParserNode &parser_node, const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); return Build( nodes::Access{.kind = nodes::Access::ARRAY, .value = Run(parser_node.nth_named_child(0)), .index = Run(parser_node.nth_named_child(1))}, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } // expression '.' number_literal Node BuilderTask::operator()( - const ParserNode &parser_node, const Args &) { + const ParserNode &parser_node, const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); auto const node = Build( @@ -400,14 +402,14 @@ Node BuilderTask::operator()( // .index = Build(build_index_literal(parser_node.nth_named_child( // 1)) /*, false}*/, // ?? is_scoped ?? }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); return node; } // 'break' | 'continue' Node BuilderTask::operator()(const ParserNode &parser_node, - const Args &) { + const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); return Build( @@ -416,7 +418,7 @@ Node BuilderTask::operator()(const ParserNode &parser_node, ? nodes::LoopControl::BREAK : nodes::LoopControl::CONTINUE, }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } // // ModifierExpression -> .hpp @@ -446,10 +448,10 @@ void build_args_until_end(ParserNode first_parse_node, Executor &executor, // (type '.' simple_name | expression '.' simple_name | name | '(' operator // ')') (annotation? expression)* Node BuilderTask::operator()( - const ParserNode &parser_node, const Args &) { + const ParserNode &parser_node, const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); - std::vector args; + std::vector args_nodes; std::optional prefix; @@ -474,60 +476,60 @@ Node BuilderTask::operator()( prefix_node = current_node; } else { is_point_call = true; - args.emplace_back(std::nullopt, Run(current_node)); + args_nodes.emplace_back(std::nullopt, Run(current_node)); } } - build_args_until_end(name_node.next_named_sibling(), executor, args); + build_args_until_end(name_node.next_named_sibling(), executor, args_nodes); return Build( nodes::NameExpression{ .name = RunOther(name_node), - .args = std::move(args), + .args = std::move(args_nodes), .prefix = prefix_node.has_value() ? RunOther(prefix_node.value()) : nodes::MaybeType(), .is_point_call = is_point_call, .is_operator_call = false, }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } // type (annotation? expression)* Node BuilderTask::operator()(const ParserNode &parser_node, - const Args &) { + const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); - std::vector args; + std::vector args_nodes; build_args_until_end(parser_node .child_by_field_name("ty" "p" "e") .next_named_sibling(), - executor, args); + executor, args_nodes); return Build( nodes::Constructor{ .type = RunOther(parser_node.child_by_field_name("type")), - .args = std::move(args), + .args = std::move(args_nodes), }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } // '\\' argument_name* _do_ expression Node BuilderTask::operator()(const ParserNode &parser_node, - const Args &) { + const Args &args) { Log::Context logc(executor.log(), Log::Area::kParse); - std::vector args; + std::vector args_nodes; auto current_node = parser_node.nth_child(1); // next to '\\', not null ('=>' should present) while (current_node.is_named()) { // until _do_ - args.emplace_back(RunOther(current_node)); + args_nodes.emplace_back(RunOther(current_node)); current_node = current_node.next_sibling(); } @@ -536,10 +538,10 @@ Node BuilderTask::operator()(const ParserNode &parser_node, return Build( nodes::Lambda{ - .args = std::move(args), + .args = std::move(args_nodes), .expr = Run(current_node), }, - parser_node.get_pos()); + args.is_scoped, parser_node.get_pos()); } } // namespace builders diff --git a/lang/type_check/include/type_check_utils.hpp b/lang/type_check/include/type_check_utils.hpp index cf03f05..8889aff 100644 --- a/lang/type_check/include/type_check_utils.hpp +++ b/lang/type_check/include/type_check_utils.hpp @@ -25,8 +25,8 @@ public: public: State(Log &log) : log_(log) {} - bool insert_variable(const std::string &name, nodes::Type type, - nodes::NameDefinition::Kind modifier) { + bool InsertVariable(const std::string &name, nodes::Type type, + nodes::NameDefinition::Kind modifier) { Log::Context logc(log_, Log::Area::kTypeCheck); if (contexts_.empty()) { @@ -39,7 +39,7 @@ public: .second; } - std::optional find_variable(const std::string &name) { + std::optional FindVariable(const std::string &name) { for (ssize_t i = contexts_.size(); i >= 0; --i) { auto iter = contexts_[i].variables.find(name); if (iter != contexts_[i].variables.end()) { @@ -50,7 +50,7 @@ public: return std::nullopt; } - bool bring_type(nodes::Type type) { + bool BringType(nodes::Type type) { Log::Context logc(log_, Log::Area::kTypeCheck); if (contexts_.empty()) { @@ -66,7 +66,7 @@ public: return true; } - bool return_type(nodes::Type type) { + bool ReturnType(nodes::Type type) { Log::Context logc(log_, Log::Area::kTypeCheck); if (contexts_.empty()) { @@ -83,7 +83,7 @@ public: } private: - void enter_context(const utils::Pos &pos) { + void EnterContext(const utils::Pos &pos) { Log::Context logc(log_, Log::Area::kTypeCheck); contexts_.emplace_back(pos); @@ -164,10 +164,14 @@ using Exprs = nodes::NodeStorage; using Types = nodes::TypeStorage; using Names = names::NameTree; using Positions = core::DependentStorage; +using NodeTypes = + core::DependentStorage; // deduce type for each node -using Executor = core::Executor; +using Executor = + core::Executor; -using Node = nodes::Node_>; +using Node = + nodes::Node_, nodes::NodePart>; // @@ -175,52 +179,52 @@ class Args { public: Args(storage::Id current_id) : current_id(current_id) {}; - Args expect_builtin(builtin::Type type, Executor &executor) const { + Args ExpectBuiltin(builtin::Type type, Executor &executor) const { Args copy(*this); copy.expected_types_ = {executor.state().primitive(type)}; return copy; } - Args pass_builtin(builtin::Type type, Executor &executor) const { + Args PassBuiltin(builtin::Type type, Executor &executor) const { Args copy(*this); copy.passed_type_ = executor.state().primitive(type); return copy; } - Args expect(nodes::Types types) const { + Args Expect(nodes::Types types) const { Args copy(*this); copy.expected_types_ = types; return copy; } - Args expect(nodes::MaybeType type) const { + Args Expect(nodes::MaybeType type) const { Args copy(*this); copy.expected_types_ = (type.has_value() ? nodes::Types{type.value()} : nodes::Types{}); return copy; } - Args pass(nodes::MaybeType type) const { + Args Pass(nodes::MaybeType type) const { Args copy(*this); copy.passed_type_ = type; return copy; } - Args without_expect() const { + Args WithoutExpect() const { Args copy(*this); copy.expected_types_ = {}; return copy; } - Args without_pass() const { + Args WithoutPass() const { Args copy(*this); copy.passed_type_ = {}; return copy; } - nodes::Types get_expected() const { return expected_types_; }; + nodes::Types expected() const { return expected_types_; }; - nodes::MaybeType get_passed() const { return passed_type_; }; + nodes::MaybeType passed() const { return passed_type_; }; // TODO: add check, that there is no passed type for some nodes ?? // TODO: args builder ?? @@ -240,7 +244,7 @@ public: ContextHolder(State &state, const utils::Pos &pos, nodes::MaybeType *context_exit_type) : state_(state), context_exit_type_(context_exit_type) { - state.enter_context(pos); + state.EnterContext(pos); } ContextHolder(const ContextHolder &) = delete; @@ -273,14 +277,14 @@ public: // - nodes::Type &get() { + nodes::Type &Get() { utils::Assert(type_.has_value(), "Access to invalid type in TypeCheckResult"); return type_.value(); } - const nodes::Type &get() const { + const nodes::Type &Get() const { utils::Assert(type_.has_value(), "Access to invalid type in TypeCheckResult"); @@ -288,7 +292,15 @@ public: return type_.value(); } - void set(nodes::Type type) { type_ = type; } + // + + nodes::MaybeType &MaybeGet() { return type_; } + + const nodes::MaybeType &MaybeGet() const { return type_; } + + // + + void Set(nodes::Type type) { type_ = type; } // @@ -305,7 +317,7 @@ using MaybeResult = std::optional; // -nodes::Type check_same_to_pass_type_in_args( +nodes::Type CheckSameToPassTypeInArgs( nodes::Type type, const Args &args, const utils::Pos &pos, Executor &executor, const std::string &message = "Different type with passed one", @@ -316,37 +328,31 @@ nodes::Type check_same_to_pass_type_in_args( // SourcesManager &sources_manager, // const std::string &message = "Type can't be passed to this node"); -Result type_same_to_expected( +Result CheckTypeSameToExpected( nodes::Type type, const Args &args, const utils::Pos &pos, Executor &executor, const std::string &message = "Different type with expected one", bool handle_errors = true); -Result type_check_from_args(nodes::Type type, const Args &args, - const utils::Pos &pos, Executor &executor, - bool handle_errors = true); - std::optional -find_type_definition(const std::string &name, const utils::Pos &pos, - Executor &executor, bool handle_errors = true); +FindTypeDefinition(const std::string &name, const utils::Pos &pos, + Executor &executor, bool handle_errors = true); std::optional -find_name_definition(const std::string &name, const utils::Pos &pos, - Executor &executor, bool handle_errors = true); +FindNameDefinition(const std::string &name, const utils::Pos &pos, + Executor &executor, bool handle_errors = true); -nodes::MaybeType unfold_user_defined_type(nodes::Type type, - const utils::Pos &pos, - Executor &executor, - bool handle_errors = true); +nodes::MaybeType UnfoldUserDefinedType(nodes::Type type, const utils::Pos &pos, + Executor &executor, + bool handle_errors = true); -nodes::MaybeType get_field_type_by_name(nodes::Type type, - const std::string &field, - const utils::Pos &pos, - Executor &executor, - bool handle_errors = true); +nodes::MaybeType FieldTypeByName(nodes::Type type, const std::string &field, + const utils::Pos &pos, Executor &executor, + bool handle_errors = true); -void type_check_error(const std::string &message, const utils::Pos &pos, - Executor &executor, bool handle_error = true); +inline nodes::MaybeType Curry(MaybeResult result) { + return result.has_value() ? result->Get() : nodes::MaybeType{}; +} // @@ -366,12 +372,47 @@ template struct CheckTaskBase : public Task { Node Ext(storage::Id id) { return Node(id, this->template state(), - this->template state()); + this->template state(), + this->template state()); } utils::Pos PosOf(storage::Id id) { return Ext(id).template part(); } + + // + + void TypeCheckError(const std::string &message, const utils::Pos &, + bool handle_errors = true) { + Log::Context logc(Task::executor.log(), Log::Area::kTypeCheck); + + if (not handle_errors) { + return; + } + + logc.Error({{message}} /* TODO: use pos */); + } + + Result TypeCheckFromArgs(nodes::Type type, const Args &args, + const utils::Pos &pos, bool handle_errors = true) { + Log::Context logc(Task::executor.log(), Log::Area::kTypeCheck); + + /* TODO FIXME */ + logc.Fatal({{"Not implemented yet"}}); + throw std::exception(); // unreachable + } + + bool CheckNoPassTypeInArgs(const Args &args, const utils::Pos &pos, + const std::string &message, bool handle_errors) { + Log::Context logc(Task::executor.log(), Log::Area::kTypeCheck); + + if (args.passed().has_value()) { + TypeCheckError(message, pos, handle_errors); + return false; + } + + return true; + } }; } // namespace type_check diff --git a/lang/type_check/src/basic_type_check.cpp b/lang/type_check/src/basic_type_check.cpp index 2b197f0..6a27d8c 100644 --- a/lang/type_check/src/basic_type_check.cpp +++ b/lang/type_check/src/basic_type_check.cpp @@ -4,6 +4,8 @@ namespace type_check { nodes::Type get_literal_type(const nodes::Literal &literal, Executor &executor) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + switch (literal.value.index()) { case 0: // float return executor.state().primitive(builtin::Type::FLOAT); @@ -39,9 +41,11 @@ nodes::Type get_literal_type(const nodes::Literal &literal, Result CheckTask::operator()(const nodes::Literal &literal, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + auto const type = get_literal_type(literal, this->executor); - return type_same_to_expected(type, args, {}, - this->executor); // TODO: add pos ?? + return CheckTypeSameToExpected(type, args, {}, + this->executor); // TODO: add pos ?? } } // namespace type_check diff --git a/lang/type_check/src/expression_type_check.cpp b/lang/type_check/src/expression_type_check.cpp index ab08d0f..600b1d5 100644 --- a/lang/type_check/src/expression_type_check.cpp +++ b/lang/type_check/src/expression_type_check.cpp @@ -35,16 +35,19 @@ Result CheckTask::operator()(const nodes::NodeData &expr, Result CheckTask::operator()(const nodes::Match &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); const auto current_pos = PosOf(args.current_id); + // + Result value_result = Run(expr.value, {expr.value}); // x :=/=: ... if (value_result.is_invalid()) { - type_check_error("Match value is invalid", current_pos, executor); + TypeCheckError("Match value is invalid", current_pos); } - MaybeResult expression_result; + MaybeResult expr_result; bool at_least_one_case_with_expression = false; bool at_least_one_case_without_expression = false; @@ -54,95 +57,101 @@ Result CheckTask::operator()(const nodes::Match &expr, Ext(current_case_id).get(); // :=/=: x ... - Run(current_case.value, - Args{current_case.value} - .expect_builtin(builtin::Type::BOOL, executor) - .pass(value_result.is_invalid() ? nodes::MaybeType{} - : expression_result.value().get())); - // TODO: use type modifiers ?? + switch ( + current_case.kind) { // TODO: FIXME think about passed, brought types + case nodes::Match::Case::PATTERN_VALUE: + if (not value_result.is_invalid()) { + Run(current_case.value, + Args{current_case.value} + .ExpectBuiltin(builtin::Type::BOOL, executor) + .Pass(value_result.Get())); + } + break; + case nodes::Match::Case::VALUE_PATTERN: + Run(current_case.value, Args{current_case.value} + .ExpectBuiltin(builtin::Type::BOOL, executor) + .Pass(value_result.MaybeGet())); + break; + } // ... ?? x ... if (current_case.condition.has_value()) { - Run(current_case.condition.value(), - Args{current_case.condition.value()}.expect_builtin( - builtin::Type::BOOL, executor)); + const auto &cond = current_case.condition.value(); + Run(cond, Args{cond}.ExpectBuiltin(builtin::Type::BOOL, executor)); } // ... -> x if (current_case.expr.has_value()) { + const auto &expr = current_case.expr.value(); at_least_one_case_with_expression = true; - Result case_result = Run(current_case.expr.value(), - Args{current_case.expr.value()}.expect( - expression_result.has_value() - ? expression_result.value().get() - : nodes::MaybeType{})); - if (!expression_result.has_value() && !case_result.is_invalid()) { - expression_result = std::move(case_result); + Result case_result = Run(expr, Args{expr}.Expect(Curry(expr_result))); + + if (not expr_result.has_value() and not case_result.is_invalid()) { + expr_result = std::move(case_result); } } else { at_least_one_case_without_expression = true; } } - if (at_least_one_case_with_expression && + if (at_least_one_case_with_expression and at_least_one_case_without_expression) { - type_check_error( + TypeCheckError( "All cases should be with or without expression at the same time", - current_pos, executor); - expression_result = Result::invalid(); + current_pos); + expr_result = Result::invalid(); } - if (!expression_result.has_value()) { - expression_result = Result{state().primitive(builtin::Type::UNIT)}; + if (not expr_result.has_value()) { + expr_result = Result{state().primitive(builtin::Type::UNIT)}; } - return type_check_from_args( - state().add_array_of(expression_result.value().get()), args, - current_pos, executor); + return TypeCheckFromArgs(expr_result.value().Get(), args, current_pos); } Result CheckTask::operator()(const nodes::Condition &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); const auto current_pos = PosOf(args.current_id); - MaybeResult expression_result; + // + + MaybeResult expr_result; for (const auto ¤t_case : expr.cases) { + // condition Run(current_case.first, - Args{current_case.first}.expect_builtin(builtin::Type::BOOL, executor)); + Args{current_case.first}.ExpectBuiltin(builtin::Type::BOOL, executor)); + // expression Result case_result = Run(current_case.second, - Args{current_case.second}.expect( - expression_result.has_value() ? expression_result.value().get() - : nodes::MaybeType{})); + Args{current_case.second}.Expect(Curry(expr_result))); - if (!expression_result.has_value() && !case_result.is_invalid()) { - expression_result = std::move(case_result); + if (not expr_result.has_value() and not case_result.is_invalid()) { + expr_result = std::move(case_result); } } if (expr.else_case.has_value()) { Run(expr.else_case.value(), - Args{expr.else_case.value()}.expect( - expression_result.has_value() ? expression_result.value().get() - : nodes::MaybeType{})); + Args{expr.else_case.value()}.Expect(Curry(expr_result))); } - if (!expression_result.has_value()) { - type_check_error("There should be at least one case in if statement", - current_pos, executor); - expression_result = Result::invalid(); + if (!expr_result.has_value()) { + TypeCheckError("There should be at least one case in if statement", + current_pos); + expr_result = Result::invalid(); } - return type_check_from_args( - state().add_array_of(expression_result.value().get()), args, - current_pos, executor); + return TypeCheckFromArgs(expr_result.value().Get(), args, current_pos); } Result CheckTask::operator()(const nodes::Loop &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + const auto current_pos = PosOf(args.current_id); // TODO: ranges ?? @@ -157,7 +166,7 @@ Result CheckTask::operator()(const nodes::Loop &expr, case nodes::Loop::LOOP: // infinity loop, no params break; case nodes::Loop::WHILE: - Run(expr.condition.value(), Args{expr.condition.value()}.expect_builtin( + Run(expr.condition.value(), Args{expr.condition.value()}.ExpectBuiltin( builtin::Type::BOOL, executor)); // --- type check is independent from loop itself --- @@ -169,7 +178,7 @@ Result CheckTask::operator()(const nodes::Loop &expr, case nodes::Loop::FOR: // TODO: expect range ?? interval_result = - Run(expr.interval.value(), Args{expr.interval.value()}.expect_builtin( + Run(expr.interval.value(), Args{expr.interval.value()}.ExpectBuiltin( builtin::Type::ARRAY, executor)); if (interval_result.value().is_invalid()) { @@ -180,8 +189,8 @@ Result CheckTask::operator()(const nodes::Loop &expr, variable_result = Run(expr.variable.value(), - Args{expr.variable.value()}.expect( - interval_result.value().get().get()->get_parameter_proxy(0))); + Args{expr.variable.value()}.Expect( + interval_result.value().Get().get()->get_parameter_proxy(0))); // --- type check is independent from loop itself --- // if (variable_result.value().is_invalid()) { @@ -196,15 +205,16 @@ Result CheckTask::operator()(const nodes::Loop &expr, // TODO: modifier checks ??, modifiers ?? - return type_check_from_args( - state().add_array_of(expression_result.get()), args, current_pos, - executor); + return TypeCheckFromArgs(state().add_array_of(expression_result.Get()), + args, current_pos); } // IN PROGRESS // --- containers Result CheckTask::CheckArray(const nodes::Container &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + const auto current_pos = PosOf(args.current_id); MaybeResult last_expr_result; @@ -216,9 +226,9 @@ Result CheckTask::CheckArray(const nodes::Container &expr, if (!last_expr_result.has_value()) { last_expr_result = expr_result; } else { - if (last_expr_result.value().get() != expr_result.get()) { - type_check_error("Elements in array should have same type", - PosOf(args.current_id), executor); + if (last_expr_result.value().Get() != expr_result.Get()) { + TypeCheckError("Elements in array should have same type", + PosOf(args.current_id)); // return TypeCheckResult::construct_invalid_result(); // max // possible checks, so no return } @@ -226,17 +236,19 @@ Result CheckTask::CheckArray(const nodes::Container &expr, } if (!last_expr_result.has_value()) { - type_check_error("Array with zero elements", current_pos, executor); + TypeCheckError("Array with zero elements", current_pos); return Result::invalid(); } - return type_check_from_args( - state().add_array_of(last_expr_result.value().get()), args, - current_pos, executor); + return TypeCheckFromArgs( + state().add_array_of(last_expr_result.value().Get()), args, + current_pos); } Result CheckTask::CheckBlock(const nodes::Container &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + const auto current_pos = PosOf(args.current_id); nodes::MaybeType context_exit_type; @@ -257,9 +269,8 @@ Result CheckTask::CheckBlock(const nodes::Container &expr, ? Result(context_exit_type.value()) : Result(state().primitive(builtin::Type::UNIT)); - return type_check_from_args( - state().add_array_of(block_brought_type.get()), args, current_pos, - executor); + return TypeCheckFromArgs( + state().add_array_of(block_brought_type.Get()), args, current_pos); } Result CheckTask::operator()(const nodes::Container &expr, @@ -276,6 +287,8 @@ Result CheckTask::operator()(const nodes::Container &expr, Result CheckTask::operator()(const nodes::Return &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + const auto current_pos = PosOf(args.current_id); auto returned_result = Run(expr.expr, {expr.expr}); @@ -286,70 +299,71 @@ Result CheckTask::operator()(const nodes::Return &expr, switch (expr.kind) { case nodes::Return::BRING: - if (state().bring_type(returned_result.get())) { - type_check_error("Different brought type to current one", current_pos, - executor); + if (state().BringType(returned_result.Get())) { + TypeCheckError("Different brought type to current one", current_pos); return Result::invalid(); } break; case nodes::Return::RETURN: - if (!state().return_type(returned_result.get())) { - type_check_error("Different returned type to current one", current_pos, - executor); + if (!state().ReturnType(returned_result.Get())) { + TypeCheckError("Different returned type to current one", current_pos); return Result::invalid(); } break; } - return type_check_from_args(state().primitive(builtin::Type::UNIT), - args, current_pos, executor); + return TypeCheckFromArgs(state().primitive(builtin::Type::UNIT), args, + current_pos); } // TODO: warning if name is same to package prefix, function prefix, etc. ?? Result CheckTask::operator()(const nodes::NameDefinition &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + const auto current_pos = PosOf(args.current_id); - if (!args.get_passed().has_value()) { - type_check_error("Can't deduce type of new variable from context", - current_pos, executor); + if (!args.passed().has_value()) { + TypeCheckError("Can't deduce type of new variable from context", + current_pos); } // assigned type shold be one of <-, <>, -- (can't be ->) - const auto variable_type = args.get_passed().value(); + const auto variable_type = args.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", - current_pos, executor); + TypeCheckError("Variable can't be assigned from out (->) value", + current_pos); } // variable accessible by reference by default ?? state().add_modification_of(variable_type, nodes::Modifier::REF); - if (!state().insert_variable(expr.name.value, variable_type, - expr.kind)) { - type_check_error("Variable is already defined in this context", current_pos, - executor); + if (!state().InsertVariable(expr.name.value, variable_type, + expr.kind)) { + TypeCheckError("Variable is already defined in this context", current_pos); } // Return BOOL as any := / =: expression - return type_check_from_args(state().primitive(builtin::Type::BOOL), - args, current_pos, executor); + return TypeCheckFromArgs(state().primitive(builtin::Type::BOOL), args, + current_pos); } Result CheckTask::CheckArrayAccess(const nodes::Access &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + const auto current_pos = PosOf(args.current_id); auto index_result = Run(expr.index, - Args{expr.index}.expect_builtin(builtin::Type::INDEX, executor)); + Args{expr.index}.ExpectBuiltin(builtin::Type::INDEX, executor)); auto value_result = Run(expr.value, - Args{expr.value}.expect_builtin(builtin::Type::ARRAY, executor)); + Args{expr.value}.ExpectBuiltin(builtin::Type::ARRAY, executor)); if (index_result.is_invalid()) { return index_result; @@ -361,17 +375,19 @@ Result CheckTask::CheckArrayAccess(const nodes::Access &expr, // TODO: modifier checks ?? - return type_check_from_args(value_result.get().get()->get_parameter_proxy(0), - args, current_pos, executor); + return TypeCheckFromArgs(value_result.Get().get()->get_parameter_proxy(0), + args, current_pos); } Result CheckTask::CheckTupleAccess(const nodes::Access &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + const auto current_pos = PosOf(args.current_id); auto value_result = Run(expr.value, - Args{expr.value}.expect_builtin(builtin::Type::TUPLE, executor)); + Args{expr.value}.ExpectBuiltin(builtin::Type::TUPLE, executor)); if (value_result.is_invalid()) { return value_result; @@ -384,13 +400,14 @@ Result CheckTask::CheckTupleAccess(const nodes::Access &expr, // TODO: modifier checks ?? - return type_check_from_args( - value_result.get().get()->get_parameter_proxy(index), args, current_pos, - executor); + return TypeCheckFromArgs(value_result.Get().get()->get_parameter_proxy(index), + args, current_pos); } Result CheckTask::operator()(const nodes::Access &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + switch (expr.kind) { case nodes::Access::ARRAY: return CheckArrayAccess(expr, args); @@ -401,14 +418,18 @@ Result CheckTask::operator()(const nodes::Access &expr, Result CheckTask::operator()(const nodes::LoopControl &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + const auto current_pos = PosOf(args.current_id); - return type_check_from_args(state().primitive(builtin::Type::UNIT), - args, current_pos, executor); + return TypeCheckFromArgs(state().primitive(builtin::Type::UNIT), args, + current_pos); } Result CheckTask::operator()( const nodes::ModifierExpression &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + const auto current_pos = PosOf(args.current_id); auto modified_result = Run(expr.expr, {expr.expr}); @@ -426,25 +447,23 @@ Result CheckTask::operator()( // '!' - open optional / result -> value / panic - switch (modified_result.get().get()->to_builtin()) { + switch (modified_result.Get().get()->to_builtin()) { case builtin::Type::OPTIONAL: case builtin::Type::RESULT: // TODO: how to unwrap external modifier ?? - modified_result.set(modified_result.get().get()->get_parameter_proxy(0)); + modified_result.Set(modified_result.Get().get()->get_parameter_proxy(0)); break; default: - type_check_error("Can unwrap only Optional or Result", current_pos, - executor); + TypeCheckError("Can unwrap only Optional or Result", current_pos); return Result::invalid(); } } else { // TODO: check that modifier can be applied - modified_result.set(state().add_modification_of( - modified_result.get(), expr.modifier)); + modified_result.Set(state().add_modification_of( + modified_result.Get(), expr.modifier)); } - return type_check_from_args(modified_result.get(), args, current_pos, - executor); + return TypeCheckFromArgs(modified_result.Get(), args, current_pos); } // IN PROGRESS // --- other @@ -453,6 +472,8 @@ Result CheckTask::operator()( Result CheckTask::operator()(const nodes::NameExpression &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + const auto current_pos = PosOf(args.current_id); // TODO: constraints ?? @@ -470,7 +491,7 @@ CheckTask::operator()(const nodes::NameExpression &expr, current_prefix.append_after(fragments[i]); } - maybe_variable = state().find_variable(current_prefix.value); + maybe_variable = state().FindVariable(current_prefix.value); if (maybe_variable.has_value()) { break; @@ -494,8 +515,8 @@ CheckTask::operator()(const nodes::NameExpression &expr, // 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].value, current_pos, executor); + const auto maybe_field_type = + FieldTypeByName(type, fragments[i].value, current_pos, executor); if (maybe_field_type.has_value()) { type = maybe_field_type.value(); @@ -517,7 +538,7 @@ CheckTask::operator()(const nodes::NameExpression &expr, // TODO: check, if there is variable with this name // TODO: check var + fields const auto maybe_function_definition = - find_name_definition(name.value, current_pos, executor); + FindNameDefinition(name.value, current_pos, executor); if (!maybe_function_definition.has_value()) { return Result::invalid(); } @@ -531,15 +552,13 @@ CheckTask::operator()(const nodes::NameExpression &expr, const auto args_defined = function_definition->args.size(); if (args_given + 1 < args_defined || args_given > args_defined) { // other, when there is passed type - type_check_error( - "Number of function args is different from expected (" + - std::to_string(args_given) + " instead of " + - std::to_string(args_defined) + - std::string{args_defined > 0 - ? (" or " + std::to_string(args_defined - 1)) - : ""} + - ")", - current_pos, executor); + TypeCheckError(std::format("Number of function args is different from " + "expected ({} instead of {}{})", + args_given, args_defined, + args_defined > 0 + ? (" or " + std::to_string(args_defined - 1)) + : ""), + current_pos); return Result::invalid(); // TODO: try return correct type (function return type), when possible } @@ -553,9 +572,10 @@ CheckTask::operator()(const nodes::NameExpression &expr, function_definition->args.at(i); if (!argument.type.has_value()) { - type_check_error("Function argument type is not defined for argument " + - std::to_string(i), - current_pos, executor); + TypeCheckError( + std::format("Function argument type is not defined for argument {}", + i), + current_pos); continue; } @@ -563,30 +583,31 @@ CheckTask::operator()(const nodes::NameExpression &expr, const auto expected_annotation = argument.annotation; if (annotation.has_value() != expected_annotation.has_value()) { - type_check_error("Wrong function argument annotation: should be " + - std::string{expected_annotation.has_value() - ? expected_annotation.value() - : "[none]"}, - PosOf(expr.args.at(i).second), executor); + TypeCheckError("Wrong function argument annotation: should be " + + std::string{expected_annotation.has_value() + ? expected_annotation.value() + : "[none]"}, + PosOf(expr.args.at(i).second)); } if (annotation.has_value() && annotation.value() != expected_annotation.value()) { - type_check_error( - "Wrong function argument type annotation: " + annotation.value() + - " instead of " + expected_annotation.value(), - PosOf(expr.args.at(i).second), executor); + TypeCheckError( + std::format( + "Wrong function argument type annotation: {} instead of {}", + annotation.value(), expected_annotation.value()), + PosOf(expr.args.at(i).second)); } function_argument_results.push_back( Run(expr.args.at(i).second, - Args{expr.args.at(i).second}.expect(argument.type.value()))); + Args{expr.args.at(i).second}.Expect(argument.type.value()))); } if (function_definition->args.size() == 0) { - type_check_error( + TypeCheckError( "Function arguments size is zero. Returned type is not defined", - current_pos, executor); + current_pos); return Result::invalid(); } @@ -598,16 +619,14 @@ CheckTask::operator()(const nodes::NameExpression &expr, // TODO: invert modifier ?? if (!returned.type.has_value()) { - type_check_error( - "Function argument type is not defined for returned type", - current_pos, executor); + TypeCheckError("Function argument type is not defined for returned type", + current_pos); return Result::invalid(); } // TODO: invert modifier ?? // TODO: generic types should be deduced from args - return type_check_from_args(returned.type.value(), args, current_pos, - executor); + return TypeCheckFromArgs(returned.type.value(), args, current_pos); } // checks for universal call syntax ?? @@ -618,12 +637,14 @@ CheckTask::operator()(const nodes::NameExpression &expr, // TODO Result CheckTask::operator()(const nodes::Constructor &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + const auto current_pos = PosOf(args.current_id); // TODO: constraints ?? // TODO: use pass type - const auto maybe_type_definition = find_type_definition( + const auto maybe_type_definition = FindTypeDefinition( expr.type.get()->get_name()->value, current_pos, executor); if (!maybe_type_definition.has_value()) { return Result::invalid(); @@ -631,9 +652,9 @@ Result CheckTask::operator()(const nodes::Constructor &expr, const nodes::TypeDefinition *type_definition = maybe_type_definition.value(); if (!type_definition->type.has_value()) { - type_check_error( + TypeCheckError( "Type defenition for constructor type not found (declaration only)", - current_pos, executor); + current_pos); return Result::invalid(); } @@ -646,8 +667,8 @@ Result CheckTask::operator()(const nodes::Constructor &expr, // TODO: work with different parametric types: tuple, variant, ... if (expr.args.size() == 0) { - type_check_error("Number of type constructor arguments should be > 0", - current_pos, executor); + TypeCheckError("Number of type constructor arguments should be > 0", + current_pos); return Result::invalid(); // TODO: try return correct type (constructor's type), when possible (not // generic) @@ -661,12 +682,12 @@ Result CheckTask::operator()(const nodes::Constructor &expr, switch (builtin_type) { case builtin::Type::TUPLE: if (expr.args.size() != type.get()->parameters_size()) { - type_check_error( + TypeCheckError( "Number of type constructor arguments is different from expected " "(" + std::to_string(expr.args.size()) + " instead of " + std::to_string(type.get()->parameters_size()) + ")", - current_pos, executor); + current_pos); return Result::invalid(); // TODO: try return correct type (constructor's type), when possible // (not generic) @@ -679,10 +700,10 @@ Result CheckTask::operator()(const nodes::Constructor &expr, case builtin::Type::FUNCTION: case builtin::Type::NONE: if (expr.args.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)) + ")", - current_pos, executor); + TypeCheckError(std::format("Number of type constructor arguments " + "should be = 1 (builtin type {})", + uint(builtin_type)), + current_pos); return Result::invalid(); // TODO: try return correct type (constructor's type), when possible // (not generic) @@ -695,8 +716,8 @@ Result CheckTask::operator()(const nodes::Constructor &expr, 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", - current_pos, executor); + TypeCheckError("Wrong amount of parametars for builtin type", + current_pos); return Result::invalid(); // TODO: try return correct type (constructor's type), when possible (not @@ -717,12 +738,12 @@ Result CheckTask::operator()(const nodes::Constructor &expr, if (annotation.has_value() != expected_annotation.has_value()) { if (log_errors) { - type_check_error( + TypeCheckError( "Wrong type constructor argument annotation: should be " + std::string{expected_annotation.has_value() ? *expected_annotation.value() : "[none]"}, - PosOf(expr.args.at(i).second), executor); + PosOf(expr.args.at(i).second)); } is_same = false; } @@ -730,10 +751,10 @@ Result CheckTask::operator()(const nodes::Constructor &expr, if (annotation.has_value() && annotation.value() != *expected_annotation.value()) { if (log_errors) { - type_check_error("Wrong function argument type annotation: " + - annotation.value() + " instead of " + - *expected_annotation.value(), - PosOf(expr.args.at(i).second), executor); + TypeCheckError("Wrong function argument type annotation: " + + annotation.value() + " instead of " + + *expected_annotation.value(), + PosOf(expr.args.at(i).second)); } is_same = false; @@ -745,9 +766,9 @@ Result CheckTask::operator()(const nodes::Constructor &expr, const auto check_no_annotation = [&expr, this](size_t i, bool log_errors) { if (expr.args.at(i).first.has_value()) { if (log_errors) { - type_check_error( + TypeCheckError( "Type constructor argument annotation not expected there", - PosOf(expr.args.at(i).second), executor); + PosOf(expr.args.at(i).second)); } return false; } @@ -774,9 +795,9 @@ Result CheckTask::operator()(const nodes::Constructor &expr, if (!chosen_variant_option.has_value() && !check_no_annotation(0, false /*do not log errors*/)) { - type_check_error("Wrong type constructor argument annotation in " - "constructor of variant type", - PosOf(expr.args.front().second), executor); + TypeCheckError("Wrong type constructor argument annotation in " + "constructor of variant type", + PosOf(expr.args.front().second)); } break; case builtin::Type::ERROR: // no anotations ?? @@ -798,13 +819,13 @@ Result CheckTask::operator()(const nodes::Constructor &expr, switch (builtin_type) { case builtin::Type::TUPLE: for (size_t i = 0; i < expr.args.size(); ++i) { - Run(expr.args.at(i).second, Args{expr.args.at(i).second}.expect( + Run(expr.args.at(i).second, Args{expr.args.at(i).second}.Expect( type.get()->get_parameter_proxy(i))); } break; case builtin::Type::VARIANT: if (chosen_variant_option.has_value()) { - Run(expr.args.front().second, Args{expr.args.front().second}.expect( + Run(expr.args.front().second, Args{expr.args.front().second}.Expect( type.get()->get_parameter_proxy( chosen_variant_option.value()))); } else { // TODO: error, if there is more then one possible variant in @@ -814,43 +835,43 @@ Result CheckTask::operator()(const nodes::Constructor &expr, possible_options.push_back(type.get()->get_parameter_proxy(i)); } Run(expr.args.front().second, - Args{expr.args.front().second}.expect(possible_options)); + Args{expr.args.front().second}.Expect(possible_options)); } break; case builtin::Type::OPTIONAL: // first parameter or NULL Run(expr.args.front().second, - Args{expr.args.front().second}.expect( + Args{expr.args.front().second}.Expect( {type.get()->get_parameter_proxy(0), state().primitive(builtin::Type::NULL_OPTION)})); break; case builtin::Type::RESULT: // first parameter or ERROR[second parameter] Run(expr.args.front().second, - Args{expr.args.front().second}.expect( + Args{expr.args.front().second}.Expect( {type.get()->get_parameter_proxy(0), state().add_error_of( type.get()->get_parameter_proxy(1))})); break; case builtin::Type::ERROR: // first parameter - Run(expr.args.front().second, Args{expr.args.front().second}.expect( + Run(expr.args.front().second, Args{expr.args.front().second}.Expect( type.get()->get_parameter_proxy(0))); break; case builtin::Type::FUNCTION: case builtin::Type::NONE: // type itself Run(expr.args.front().second, - Args{expr.args.front().second}.expect(type)); + Args{expr.args.front().second}.Expect(type)); break; default: // array, basic types - type_check_error("Type can't be constructed", current_pos, executor); + TypeCheckError("Type can't be constructed", current_pos); break; } } // TODO: deduce generic parts in type - return type_check_from_args(expr.type, args, current_pos, executor); + return TypeCheckFromArgs(expr.type, args, current_pos); // TODO: add <- modifiier to type ?? } // IN PROGRESS @@ -858,71 +879,74 @@ Result CheckTask::operator()(const nodes::Constructor &expr, // TODO Result CheckTask::operator()(const nodes::Lambda &expr, const Args &args) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + const auto current_pos = PosOf(args.current_id); - if (args.get_expected().empty()) { - type_check_error("Can't deduce type of lambda function from context: no " - "one type expected", - current_pos, executor); + if (args.expected().empty()) { + TypeCheckError("Can't deduce type of lambda function from context: no " + "one type expected", + current_pos); } - if (args.get_expected().size() != + if (args.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", - current_pos, executor); + TypeCheckError("Can't deduce type of lambda function from context; too " + "much possible types", + current_pos); } - const auto expected_type = args.get_expected().front(); + const auto expected_type = args.expected().front(); if (!expected_type.get()->is_builtin(builtin::Type::FUNCTION)) { - type_check_error("Type of lambda function should be function", current_pos, - executor); + TypeCheckError("Type of lambda function should be function", current_pos); } // TODO: deal with return type (+1 sometimes), etc const auto args_given = expr.args.size(); const auto args_defined = expected_type.get()->parameters_size(); if (args_given != args_defined) { - type_check_error( - "Number of function arguments is different from expected (" + - std::to_string(args_given) + " instead of " + - std::to_string(args_defined) + - std::string{args_defined > 0 - ? (" or " + std::to_string(args_defined - 1)) - : ""} + - ")", - current_pos, executor); + TypeCheckError(std::format("Number of function arguments is different from " + "expected ({} istead of {}{})", + args_given, args_defined, + args_defined > 0 + ? (" or " + std::to_string(args_defined - 1)) + : ""), + current_pos); } // TODO: set another context (for expression typecheck and vars) for (size_t i = 0; i < args_given; ++i) { - if (!state().insert_variable( + if (!state().InsertVariable( expr.args.at(i).value, expected_type.get()->get_parameter_proxy(i), nodes::NameDefinition::Kind::LET)) { // TODO: which modifier ?? - type_check_error("Variable is already defined in this context", - current_pos, executor); + TypeCheckError("Variable is already defined in this context", + current_pos); } } // TODO: out type is can be not last if (args_given + 1 == args_defined) { Run(expr.expr, - Args{expr.expr}.expect( + Args{expr.expr}.Expect( expected_type.get()->get_parameter_proxy(args_defined - 1))); } // TODO: needed ?? (only passed type check required ??) - return type_check_from_args(expected_type, args, current_pos, executor); + return TypeCheckFromArgs(expected_type, args, current_pos); } // IN PROGRESS Result CheckTask::operator()(const nodes::Extra &, const Args &) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + return Result(state().primitive(builtin::Type::UNIT)); } Result CheckTask::operator()(const nodes::EmptyLines &, const Args &) { + Log::Context logc(executor.log(), Log::Area::kTypeCheck); + return Result(state().primitive(builtin::Type::UNIT)); } diff --git a/lang/type_check/src/type_check_utils.cpp b/lang/type_check/src/type_check_utils.cpp index 722d8e2..1b837ce 100644 --- a/lang/type_check/src/type_check_utils.cpp +++ b/lang/type_check/src/type_check_utils.cpp @@ -6,43 +6,29 @@ namespace type_check { // pass type -> compare types, return bool // no pass type -> return type -nodes::Type check_same_to_pass_type_in_args(nodes::Type type, const Args &args, - const utils::Pos &, - Executor &executor, - const std::string &message, - bool handle_errors) { +nodes::Type CheckSameToPassTypeInArgs(nodes::Type type, const Args &args, + const utils::Pos &, Executor &executor, + const std::string &message, + bool handle_errors) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - if (not args.get_passed().has_value()) { + if (not args.passed().has_value()) { return type; } - if (type != args.get_passed().value() and handle_errors) { + if (type != args.passed().value() and handle_errors) { logc.Error({{message}} /* TODO: node */); } return executor.state().primitive(builtin::Type::BOOL); } -bool check_no_pass_type_in_args(const Args &args, const utils::Pos &pos, - Executor &executor, const std::string &message, - bool handle_errors) { +Result CheckTypeSameToExpected(nodes::Type type, const Args &args, + const utils::Pos &, Executor &executor, + const std::string &message, bool handle_errors) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - if (args.get_passed().has_value()) { - type_check_error(message, pos, executor, handle_errors); - return false; - } - - return true; -} - -Result type_same_to_expected(nodes::Type type, const Args &args, - const utils::Pos &, Executor &executor, - const std::string &message, bool handle_errors) { - Log::Context logc(executor.log(), Log::Area::kTypeCheck); - - const auto &expected = args.get_expected(); + const auto &expected = args.expected(); if (expected.empty()) { return Result{type}; @@ -60,22 +46,12 @@ Result type_same_to_expected(nodes::Type type, const Args &args, return Result{expected.front()}; // any can be choosen } -Result type_check_from_args(nodes::Type /*type*/, const Args & /*args*/, - const utils::Pos &, Executor &executor, - bool /*handle_errors*/) { - Log::Context logc(executor.log(), Log::Area::kTypeCheck); - - /* TODO FIXME */ - logc.Fatal({{"Not implemented yet"}}); - throw std::exception(); // unreachable -} - template std::optional -find_statement(const std::string &name, const utils::Pos &, Executor &executor, - const std::string &message_not_found, - const std::string &message_different_statement, - bool handle_errors) { +FindStatement(const std::string &name, const utils::Pos &, Executor &executor, + const std::string &message_not_found, + const std::string &message_different_statement, + bool handle_errors) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); const auto maybe_any_statement = executor.state().find(name); @@ -98,32 +74,32 @@ find_statement(const std::string &name, const utils::Pos &, Executor &executor, } std::optional -find_type_definition(const std::string &name, const utils::Pos &pos, - Executor &executor, bool handle_errors) { +FindTypeDefinition(const std::string &name, const utils::Pos &pos, + Executor &executor, bool handle_errors) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - return find_statement( + return FindStatement( name, pos, executor, "No type definition found in name tree", "Node in name tree is not type definition", handle_errors); } std::optional -find_name_definition(const std::string &name, const utils::Pos &pos, - Executor &executor, bool handle_errors) { +FindNameDefinition(const std::string &name, const utils::Pos &pos, + Executor &executor, bool handle_errors) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - return find_statement( + return FindStatement( name, pos, executor, "No name definition found in name tree", "Node in name tree is not name definition", handle_errors); } -std::optional unfold_user_defined_type(nodes::Type type, - const utils::Pos &pos, - Executor &executor, - bool handle_errors) { +std::optional UnfoldUserDefinedType(nodes::Type type, + const utils::Pos &pos, + Executor &executor, + bool handle_errors) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - const auto maybe_type_definition = find_type_definition( + const auto maybe_type_definition = FindTypeDefinition( type.get()->get_name()->value, pos, executor, handle_errors); if (!maybe_type_definition.has_value()) { @@ -146,11 +122,9 @@ std::optional unfold_user_defined_type(nodes::Type type, return maybe_type_definition.value()->type.value(); } -std::optional get_field_type_by_name(nodes::Type type, - const std::string &field, - const utils::Pos &pos, - Executor &executor, - bool handle_errors) { +std::optional +FieldTypeByName(nodes::Type type, const std::string &field, + const utils::Pos &pos, Executor &executor, bool handle_errors) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); switch (type.get()->to_builtin()) { @@ -170,13 +144,13 @@ std::optional get_field_type_by_name(nodes::Type type, // remove recursion ?? const auto maybe_internal_type = - unfold_user_defined_type(type, pos, executor, handle_errors); + UnfoldUserDefinedType(type, pos, executor, handle_errors); if (!maybe_internal_type.has_value()) { return std::nullopt; } - return get_field_type_by_name(maybe_internal_type.value(), field, pos, - executor, handle_errors); + return FieldTypeByName(maybe_internal_type.value(), field, pos, executor, + handle_errors); } default: // variant, function, optional, result, error (TODO: add message // field?), array (TODO: add length field ?), basic types @@ -191,16 +165,4 @@ std::optional get_field_type_by_name(nodes::Type type, } } -// FIXME: replace with direct log calls -void type_check_error(const std::string &message, const utils::Pos &, - Executor &executor, bool handle_error) { - Log::Context logc(executor.log(), Log::Area::kTypeCheck); - - if (!handle_error) { - return; - } - - logc.Error({{message}} /* TODO: use pos */); -} - } // namespace type_check diff --git a/lang/utils/include/counter.hpp b/lang/utils/include/counter.hpp index a2457c9..793d691 100644 --- a/lang/utils/include/counter.hpp +++ b/lang/utils/include/counter.hpp @@ -3,6 +3,8 @@ #include "core_utils.hpp" #include "log.hpp" +// TODO: use Counter for Tasks + namespace core { template diff --git a/lang/utils/src/log.cpp b/lang/utils/src/log.cpp index 5ab6f2f..2b20ae2 100644 --- a/lang/utils/src/log.cpp +++ b/lang/utils/src/log.cpp @@ -7,8 +7,9 @@ namespace utils { std::string to_string(const std::source_location &source_location) { - return std::format("{}:{} {}", source_location.file_name(), - source_location.line(), source_location.function_name()); + return std::format( + "{}:{}" /* {}"*/, source_location.file_name(), + source_location.line() /*, source_location.function_name()*/); } std::string to_string(Pos::Point point) {