diff --git a/include/nodes/basic_nodes.hpp b/include/nodes/basic_nodes.hpp index 69dd4a6..4f2b85e 100644 --- a/include/nodes/basic_nodes.hpp +++ b/include/nodes/basic_nodes.hpp @@ -282,7 +282,7 @@ public: value_ += NAME_DELIMITER + *identifier.get(); } - std::vector git_fragments() const { + std::vector get_fragments() const { std::vector fragments; for (auto &&fragment_name : std::ranges::views::split(value_, NAME_DELIMITER)) { diff --git a/include/type_check_utils.hpp b/include/type_check_utils.hpp index b9dfb75..7e8e079 100644 --- a/include/type_check_utils.hpp +++ b/include/type_check_utils.hpp @@ -15,6 +15,12 @@ class ContextHolder; class State { friend ContextHolder; +public: + struct VariableInfo { + nodes::TypeProxy type; + nodes::NameDefinition::Modifier modifier; + }; + public: bool insert_variable(const std::string &name, nodes::TypeProxy type, nodes::NameDefinition::Modifier modifier) { @@ -23,10 +29,10 @@ public: "Insert variable into contexts_ with zero elements in State"); } - return contexts_.back().variables.insert({name, {type, modifier}}).second; + return contexts_.back().variables.insert({name, VariableInfo{type, modifier}}).second; } - std::optional> + std::optional find_variable(const std::string &name) { for (ssize_t i = contexts_.size(); i >= 0; --i) { auto iter = contexts_[i].variables.find(name); @@ -128,8 +134,7 @@ public: public: nodes::MaybeTypeProxy brought_type; nodes::MaybeTypeProxy returned_type; - std::unordered_map> + std::unordered_map variables; private: @@ -168,7 +173,8 @@ public: Arguments expect(nodes::MaybeTypeProxy type) const { Arguments copy(*this); - copy.expected_types_ = (type.has_value() ? nodes::TypeProxies{type.value()} : nodes::TypeProxies{}); + copy.expected_types_ = (type.has_value() ? nodes::TypeProxies{type.value()} + : nodes::TypeProxies{}); return copy; } @@ -241,13 +247,14 @@ nodes::TypeProxy check_same_to_pass_type_in_arguments( // const std::string &message = "Type can't be passed to this node"); nodes::TypeCheckResult type_same_to_expected( - nodes::TypeProxy type, const Arguments& argumensr, - const nodes::Node &node, SourcesManager &sources_manager, + nodes::TypeProxy type, const Arguments &argumensr, const nodes::Node &node, + SourcesManager &sources_manager, const std::string &message = "Different type with expected one"); -nodes::TypeCheckResult type_check_from_arguments( - nodes::TypeProxy type, const Arguments& arguments, - const nodes::Node &node, SourcesManager &sources_manager); +nodes::TypeCheckResult +type_check_from_arguments(nodes::TypeProxy type, const Arguments &arguments, + const nodes::Node &node, + SourcesManager &sources_manager); std::optional find_type_definition_handle_errors(const std::string &name, diff --git a/src/expression_type_check.cpp b/src/expression_type_check.cpp index 413c8d5..1acb36b 100644 --- a/src/expression_type_check.cpp +++ b/src/expression_type_check.cpp @@ -543,7 +543,45 @@ type_check_name_expression(const nodes::NameExpression &expression, // TODO: constraints ?? const auto name = expression.get_name(); - for (size_t i = 0; i < /*fragments_count*/; ++i) { // go in prefixes and try to find matching var name + + { + const auto fragments = name->get_fragments(); + nodes::Identifier current_prefix = fragments.front(); + std::optional maybe_variable; + size_t i = 0; + for (; i < fragments.size(); ++i) { // go in prefixes and try to find matching var namei + if (i > 0) { + current_prefix.append_after(fragments[i]); + } + + maybe_variable = state.find_variable(*current_prefix.get()); + + if (maybe_variable.has_value()) { + break; + } + } + + if (maybe_variable.has_value()) { + auto& type = maybe_variable.value().type; + for (size_t j = i + 1; j < fragments.size(); ++i) { + // TODO: switch by type types: Variant, Tuple, ... + // Tuple -> try to find field + // Others -> try to open / builtin fields ? + const auto maybe_field = type.get()->get_parameter_proxy_by_name(*fragments[j].get()); + + if (maybe_field.has_value()) { + type = maybe_field.value(); + continue; + } + + if (j + 1 == fragments.size()) { // then this can be method call + // TODO: try to fond method or local function + } + + // fields for the names should be found + // last segment can be function name + } + } } // --- TODO --- deal with passed type --- TODO --- (additional argument)