diff --git a/include/basic_type_check.hpp b/include/basic_type_check.hpp index d8d7eef..5ddd838 100644 --- a/include/basic_type_check.hpp +++ b/include/basic_type_check.hpp @@ -6,7 +6,9 @@ namespace type_check { // IN PROGRESS: modifiers ?? -nodes::TypeCheckResult type_check_literal(const nodes::Literal &literal, - SourcesManager &sources_manager); +nodes::TypeCheckResult +type_check_literal(const nodes::Literal &literal, + SourcesManager &sources_manager, + nodes::MaybeTypeProxy expected_type); } // namespace type_check diff --git a/include/expression_type_check.hpp b/include/expression_type_check.hpp index caa6ceb..1bec090 100644 --- a/include/expression_type_check.hpp +++ b/include/expression_type_check.hpp @@ -11,21 +11,22 @@ namespace type_check { +// TODO: make context stack o top of RAII class State { public: bool insert_variable(const std::string &name, nodes::TypeProxy type) { - if (contexts_.size() == 0) { + if (contexts_.empty()) { error_handling::handle_general_error( "Insert variable into contexts_ with zero elements in State"); } - return contexts_.back().insert({name, type}).second; + return contexts_.back().variables.insert({name, type}).second; } - std::optional find_variable(const std::string &name) { + nodes::MaybeTypeProxy find_variable(const std::string &name) { for (ssize_t i = contexts_.size(); i >= 0; --i) { - auto iter = contexts_[i].find(name); - if (iter != contexts_[i].end()) { + auto iter = contexts_[i].variables.find(name); + if (iter != contexts_[i].variables.end()) { return iter->second; } } @@ -33,84 +34,136 @@ public: return std::nullopt; } - void enter_context() { contexts_.emplace_back(); } + void enter_context(const nodes::Node& node) { contexts_.emplace_back(node); } - void exit_context() { - if (contexts_.size() == 0) { + // returns brought type, return type is merged with next context or with + // brought type in last context + nodes::MaybeTypeProxy exit_context() { + if (contexts_.empty()) { error_handling::handle_general_error( "Pop from contexts_ with zero elements in State"); } + const auto brought_type = contexts_.back().brought_type; + const auto returned_type = contexts_.back().returned_type; contexts_.pop_back(); + + if (contexts_.empty()) { + // TODO: merge returned and brought types + } else { + // TODO: merge to previous + } + + return brought_type; + } + + bool bring_type(nodes::TypeProxy type) { + if (contexts_.empty()) { + error_handling::handle_general_error( + "Set brought type to contexts_ with zero elements in State"); + } + auto &brought_type = contexts_.back().brought_type; + if (brought_type.has_value() &&) { + // TODO + return false; + } + brought_type = type; + return true; + } + + bool return_type(nodes::TypeProxy type) { + if (contexts_.empty()) { + error_handling::handle_general_error( + "Set returned type to contexts_ with zero elements in State"); + } + auto &returned_type = contexts_.back().returned_type; + if (returned_type.has_value() &&) { + // TODO + return false; + } + returned_type = type; + return true; } public: - std::optional brought_type; - std::optional returned_type; + class Context { + public: + Context(const nodes::Node& node) : node(node) {} + + public: + nodes::MaybeTypeProxy brought_type; + nodes::MaybeTypeProxy returned_type; + std::unordered_map variables; + const nodes::Node& node; + }; private: - std::vector> contexts_ = { - {}}; + std::vector contexts_ = {{}}; +}; + +class Arguments { +public: + nodes::MaybeTypeProxy expected_type = {}; }; nodes::TypeCheckResult type_check_expression(const nodes::Expression &expression, - SourcesManager &sources_manager, State &state); + SourcesManager &sources_manager, State &state, const Arguments& arguments = {}); // --- flow control nodes::TypeCheckResult type_check_match(const nodes::Match &expression, SourcesManager &sources_manager, - State &state); + State &state, const Arguments& arguments = {}); nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression, SourcesManager &sources_manager, - State &state); + State &state, const Arguments& arguments = {}); nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, SourcesManager &sources_manager, - State &state); + State &state, const Arguments& arguments = {}); // --- containers nodes::TypeCheckResult type_check_container(const nodes::Container &expression, SourcesManager &sources_manager, - State &state); + State &state, const Arguments& arguments = {}); // --- modifiers nodes::TypeCheckResult type_check_return(const nodes::Return &expression, SourcesManager &sources_manager, - State &state); + State &state, const Arguments& arguments = {}); nodes::TypeCheckResult type_check_name_definition(const nodes::NameDefinition &expression, - SourcesManager &sources_manager, State &state); + SourcesManager &sources_manager, State &state, const Arguments& arguments = {}); nodes::TypeCheckResult type_check_access(const nodes::Access &expression, SourcesManager &sources_manager, - State &state); + State &state, const Arguments& arguments = {}); nodes::TypeCheckResult type_check_loop_control(const nodes::LoopControl &expression, - SourcesManager &sources_manager, State &state); + SourcesManager &sources_manager, State &state, const Arguments& arguments = {}); nodes::TypeCheckResult type_check_modifier_expression(const nodes::ModifierExpression &expression, - SourcesManager &sources_manager, State &state); + SourcesManager &sources_manager, State &state, const Arguments& arguments = {}); // --- other nodes::TypeCheckResult type_check_name_expression(const nodes::NameExpression &expression, - SourcesManager &sources_manager, State &state); + SourcesManager &sources_manager, State &state, const Arguments& arguments = {}); nodes::TypeCheckResult type_check_constructor(const nodes::Constructor &expression, - SourcesManager &sources_manager, State &state); + SourcesManager &sources_manager, State &state, const Arguments& arguments = {}); nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression, SourcesManager &sources_manager, - State &state); + State &state, const Arguments& arguments = {}); } // namespace type_check diff --git a/include/nodes/type_nodes.hpp b/include/nodes/type_nodes.hpp index e3cb225..dbc82cb 100644 --- a/include/nodes/type_nodes.hpp +++ b/include/nodes/type_nodes.hpp @@ -26,6 +26,8 @@ public: const Type *get() const; + bool operator==(const TypeProxy& other) const; + private: TypeProxy(TypeStorage &type_storage, size_t id) : type_storage_(&type_storage), id_(id) {} @@ -35,6 +37,8 @@ private: size_t id_; }; +using MaybeTypeProxy = std::optional; + class Type { public: Type(Identifier &&identifier, Modifier modifier = nodes::Modifier::CONST, diff --git a/src/basic_type_check.cpp b/src/basic_type_check.cpp index 84687c9..8ef990a 100644 --- a/src/basic_type_check.cpp +++ b/src/basic_type_check.cpp @@ -2,63 +2,62 @@ namespace type_check { -nodes::TypeCheckResult type_check_literal(const nodes::Literal &literal, - SourcesManager &sources_manager) { +nodes::TypeProxy get_literal_type(const nodes::Literal &literal, + SourcesManager &sources_manager) { switch (literal.get_any()->index()) { case 0: // float - return nodes::TypeCheckResult( - sources_manager.get_type_storage()->primitive_type( - builtin::types::Type::FLOAT)); + return sources_manager.get_type_storage()->primitive_type( + builtin::types::Type::FLOAT); case 1: // double - return nodes::TypeCheckResult( - sources_manager.get_type_storage()->primitive_type( - builtin::types::Type::DOUBLE)); + return sources_manager.get_type_storage()->primitive_type( + builtin::types::Type::DOUBLE); case 2: // int32_t - return nodes::TypeCheckResult( - sources_manager.get_type_storage()->primitive_type( - builtin::types::Type::INT)); + return sources_manager.get_type_storage()->primitive_type( + builtin::types::Type::INT); case 3: // int64_t - return nodes::TypeCheckResult( - sources_manager.get_type_storage()->primitive_type( - builtin::types::Type::LONG)); + return sources_manager.get_type_storage()->primitive_type( + builtin::types::Type::LONG); case 4: // size_t - return nodes::TypeCheckResult( - sources_manager.get_type_storage()->primitive_type( - builtin::types::Type::INDEX)); + return sources_manager.get_type_storage()->primitive_type( + builtin::types::Type::INDEX); case 5: // std::string - return nodes::TypeCheckResult( - sources_manager.get_type_storage()->add_array_of( - sources_manager.get_type_storage()->primitive_type( - builtin::types::Type::CHAR))); - case 6: // unicode_string - return nodes::TypeCheckResult( - sources_manager.get_type_storage()->add_array_of( - sources_manager.get_type_storage()->primitive_type( - builtin::types::Type::UNICODE))); - case 7: // char - return nodes::TypeCheckResult( + return sources_manager.get_type_storage()->add_array_of( sources_manager.get_type_storage()->primitive_type( builtin::types::Type::CHAR)); - case 8: // unicode - return nodes::TypeCheckResult( + case 6: // unicode_string + return sources_manager.get_type_storage()->add_array_of( sources_manager.get_type_storage()->primitive_type( builtin::types::Type::UNICODE)); + case 7: // char + return sources_manager.get_type_storage()->primitive_type( + builtin::types::Type::CHAR); + case 8: // unicode + return sources_manager.get_type_storage()->primitive_type( + builtin::types::Type::UNICODE); case 9: // bool - return nodes::TypeCheckResult( - sources_manager.get_type_storage()->primitive_type( - builtin::types::Type::BOOL)); + return sources_manager.get_type_storage()->primitive_type( + builtin::types::Type::BOOL); case 10: // unit - return nodes::TypeCheckResult( - sources_manager.get_type_storage()->primitive_type( - builtin::types::Type::UNIT)); + return sources_manager.get_type_storage()->primitive_type( + builtin::types::Type::UNIT); case 11: // null - return nodes::TypeCheckResult( - sources_manager.get_type_storage()->primitive_type( - builtin::types::Type::NULL_OPTION)); + return sources_manager.get_type_storage()->primitive_type( + builtin::types::Type::NULL_OPTION); } error_handling::handle_general_error("Unreachable"); exit(1); // unreachable } +nodes::TypeCheckResult type_check_literal(const nodes::Literal &literal, + SourcesManager &sources_manager, + nodes::MaybeTypeProxy expected_type) { + auto const type = get_literal_type(literal, sources_manager); + if (expected_type.has_value() && type != expected_type.value() { + return nodes::TypeCheckResult::construct_invalid_result(); + // nodes::TypeCheckResult::fail_with(type, expected_type, literal); // TODO: create error ?? + } + return nodes::TypeCheckResult(type); +} + } // namespace type_check diff --git a/src/builders/expression_builders.cpp b/src/builders/expression_builders.cpp index 7b37920..b1d2e8e 100644 --- a/src/builders/expression_builders.cpp +++ b/src/builders/expression_builders.cpp @@ -543,7 +543,7 @@ build_name_expression(parser::ParseTree::Node parser_node, build_node(parser_node), build_identifier(name_node), std::move(arguments), prefix_node.has_value() ? build_type(prefix_node.value(), type_storage) - : std::optional(), + : nodes::MaybeTypeProxy(), is_point_call, false); } diff --git a/src/builders/statement_builders.cpp b/src/builders/statement_builders.cpp index b6a5178..da98fa5 100644 --- a/src/builders/statement_builders.cpp +++ b/src/builders/statement_builders.cpp @@ -252,9 +252,9 @@ nodes::TypeDefinition build_type_definition(parser::ParseTree::Node parser_node, } } - std::optional type = + nodes::MaybeTypeProxy type = type_node.has_value() ? build_type(type_node.value(), type_storage) - : std::optional(); + : nodes::MaybeTypeProxy(); std::unordered_set annotations; diff --git a/src/expression_type_check.cpp b/src/expression_type_check.cpp index 87691ce..ef76fcf 100644 --- a/src/expression_type_check.cpp +++ b/src/expression_type_check.cpp @@ -14,56 +14,58 @@ namespace type_check { nodes::TypeCheckResult type_check_expression(const nodes::Expression &expression, - SourcesManager &sources_manager, State &state) { + SourcesManager &sources_manager, State &state, + const Arguments &arguments) { switch (expression.get_any()->index()) { // --- flow control case 0: // Match return type_check_match(*expression.get().value(), - sources_manager, state); + sources_manager, state, arguments); case 1: // Condition return type_check_condition(*expression.get().value(), - sources_manager, state); + sources_manager, state, arguments); case 2: // Loop return type_check_loop(*expression.get().value(), - sources_manager, state); + sources_manager, state, arguments); // --- containers case 3: // Container return type_check_container(*expression.get().value(), - sources_manager, state); + sources_manager, state, arguments); // --- modifiers case 4: // Return return type_check_return(*expression.get().value(), - sources_manager, state); + sources_manager, state, arguments); case 5: // NameDefinition return type_check_name_definition( *expression.get().value(), sources_manager, state); case 6: // Access return type_check_access(*expression.get().value(), - sources_manager, state); + sources_manager, state, arguments); case 7: // LoopControl return type_check_loop_control( - *expression.get().value(), sources_manager, state); + *expression.get().value(), sources_manager, state, + arguments); case 8: // ModifierExpression return type_check_modifier_expression( *expression.get().value(), sources_manager, - state); + state, arguments); // --- other case 9: // NameExpression return type_check_name_expression( *expression.get().value(), sources_manager, - state); + state, arguments); case 10: // Constructor return type_check_constructor(*expression.get().value(), - sources_manager, state); + sources_manager, state, arguments); case 11: // Lambda return type_check_lambda(*expression.get().value(), - sources_manager, state); + sources_manager, state, arguments); // --- literal case 12: // Literal // TODO return type_check_literal(*expression.get().value(), - sources_manager); + sources_manager, arguments.expected_type); // --- empty lines case 13: // Extra return nodes::TypeCheckResult( @@ -81,16 +83,21 @@ type_check_expression(const nodes::Expression &expression, // TODO nodes::TypeCheckResult type_check_match(const nodes::Match &expression, SourcesManager &sources_manager, - State &state) {} // IN PROGRESS + State &state, + const Arguments &arguments) { +} // IN PROGRESS // TODO nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression, SourcesManager &sources_manager, - State &state) {} // IN PROGRESS + State &state, + const Arguments &arguments) { +} // IN PROGRESS nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, SourcesManager &sources_manager, - State &state) { + State &state, + const Arguments &arguments) { // TODO: ranges ?? std::optional condition_result; @@ -176,7 +183,8 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, nodes::TypeCheckResult type_check_array(const nodes::Container &expression, SourcesManager &sources_manager, - State &state) { + State &state, + const Arguments &arguments) { std::optional last_expression_result; for (size_t i = 0; i < expression.expressions_size(); ++i) { @@ -214,11 +222,14 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression, // TODO nodes::TypeCheckResult type_check_block(const nodes::Container &expression, SourcesManager &sources_manager, - State &state) {} // IN PROGRESS + State &state, + const Arguments &arguments) { +} // IN PROGRESS nodes::TypeCheckResult type_check_container(const nodes::Container &expression, SourcesManager &sources_manager, - State &state) { + State &state, + const Arguments &arguments) { switch (expression.get_type()) { case nodes::Container::ARRAY: return type_check_array(expression, sources_manager, state); @@ -233,7 +244,8 @@ nodes::TypeCheckResult type_check_container(const nodes::Container &expression, nodes::TypeCheckResult type_check_return(const nodes::Return &expression, SourcesManager &sources_manager, - State &state) { + State &state, + const Arguments &arguments) { auto returned_result = type_check_expression(*expression.get_expression(), sources_manager, state); @@ -243,30 +255,23 @@ nodes::TypeCheckResult type_check_return(const nodes::Return &expression, switch (expression.get_type()) { case nodes::Return::BRING: - if (state.brought_type.has_value()) { - if (*state.brought_type.value().get() != *returned_result.get().get()) { - sources_manager.get_error_log()->add_error( - error_handling::ErrorLog::ErrorMessage( - expression, "Different brought type to current one", - error_handling::ErrorType::TYPE_CHECK)); - return nodes::TypeCheckResult::construct_invalid_result(); - } - } else { - state.brought_type = returned_result.get(); + if (state.bring_type(returned_result.get())) { + sources_manager.get_error_log()->add_error( + error_handling::ErrorLog::ErrorMessage( + expression, "Different brought type to current one", + error_handling::ErrorType::TYPE_CHECK)); + return nodes::TypeCheckResult::construct_invalid_result(); } break; case nodes::Return::RETURN: - if (state.returned_type.has_value()) { - if (*state.returned_type.value().get() != *returned_result.get().get()) { - sources_manager.get_error_log()->add_error( - error_handling::ErrorLog::ErrorMessage( - expression, "Different returned type to current one", - error_handling::ErrorType::TYPE_CHECK)); - return nodes::TypeCheckResult::construct_invalid_result(); - } - } else { - state.returned_type = returned_result.get(); + if (!state.return_type(returned_result.get())) { + sources_manager.get_error_log()->add_error( + error_handling::ErrorLog::ErrorMessage( + expression, "Different returned type to current one", + error_handling::ErrorType::TYPE_CHECK)); + return nodes::TypeCheckResult::construct_invalid_result(); } + break; } return nodes::TypeCheckResult( @@ -277,12 +282,13 @@ nodes::TypeCheckResult type_check_return(const nodes::Return &expression, // TODO nodes::TypeCheckResult type_check_name_definition(const nodes::NameDefinition &expression, - SourcesManager &sources_manager, State &state) { -} // IN PROGRESS + SourcesManager &sources_manager, State &state, + const Arguments &arguments) {} // IN PROGRESS nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression, SourcesManager &sources_manager, - State &state) { + State &state, + const Arguments &arguments) { auto index_result = type_check_expression(*expression.get_index(), sources_manager, state); @@ -322,7 +328,8 @@ nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression, nodes::TypeCheckResult type_check_tuple_access(const nodes::Access &expression, SourcesManager &sources_manager, - State &state) { + State &state, + const Arguments &arguments) { auto value_result = type_check_expression(*expression.get_value(), sources_manager, state); @@ -352,7 +359,8 @@ nodes::TypeCheckResult type_check_tuple_access(const nodes::Access &expression, nodes::TypeCheckResult type_check_access(const nodes::Access &expression, SourcesManager &sources_manager, - State &state) { + State &state, + const Arguments &arguments) { switch (expression.get_type()) { case nodes::Access::ARRAY: return type_check_array_access(expression, sources_manager, state); @@ -363,7 +371,8 @@ nodes::TypeCheckResult type_check_access(const nodes::Access &expression, nodes::TypeCheckResult type_check_loop_control(const nodes::LoopControl &, SourcesManager &sources_manager, - State &) { + State &, + const Arguments &arguments) { return nodes::TypeCheckResult( sources_manager.get_type_storage()->primitive_type( builtin::types::Type::UNIT)); @@ -371,7 +380,8 @@ nodes::TypeCheckResult type_check_loop_control(const nodes::LoopControl &, nodes::TypeCheckResult type_check_modifier_expression(const nodes::ModifierExpression &expression, - SourcesManager &sources_manager, State &state) { + SourcesManager &sources_manager, State &state, + const Arguments &arguments) { auto modified_result = type_check_expression(*expression.get_expression(), sources_manager, state); @@ -409,18 +419,20 @@ type_check_modifier_expression(const nodes::ModifierExpression &expression, // TODO nodes::TypeCheckResult type_check_name_expression(const nodes::NameExpression &expression, - SourcesManager &sources_manager, State &state) { -} // IN PROGRESS + SourcesManager &sources_manager, State &state, + const Arguments &arguments) {} // IN PROGRESS // TODO nodes::TypeCheckResult type_check_constructor(const nodes::Constructor &expression, - SourcesManager &sources_manager, State &state) { -} // IN PROGRESS + SourcesManager &sources_manager, State &state, + const Arguments &arguments) {} // IN PROGRESS // TODO nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression, SourcesManager &sources_manager, - State &state) {} // IN PROGRESS + State &state, + const Arguments &arguments) { +} // IN PROGRESS } // namespace type_check diff --git a/src/nodes/type_nodes.cpp b/src/nodes/type_nodes.cpp index 2e5e2f6..99c503a 100644 --- a/src/nodes/type_nodes.cpp +++ b/src/nodes/type_nodes.cpp @@ -6,4 +6,8 @@ Type *TypeProxy::get() { return type_storage_->get_type(id_); } const Type *TypeProxy::get() const { return type_storage_->get_type(id_); } +bool TypeProxy::operator==(const TypeProxy& other) const { + return *get() == *other.get(); +} + }; // namespace nodes