diff --git a/include/expression_type_check.hpp b/include/expression_type_check.hpp index 875ea29..5c3f266 100644 --- a/include/expression_type_check.hpp +++ b/include/expression_type_check.hpp @@ -11,8 +11,8 @@ namespace type_check { struct State { - std::optional brought_type; - std::optional returned_type; + std::optional brought_type; + std::optional returned_type; }; nodes::TypeCheckResult diff --git a/include/nodes/basic_nodes.hpp b/include/nodes/basic_nodes.hpp index 6392a26..8e65fef 100644 --- a/include/nodes/basic_nodes.hpp +++ b/include/nodes/basic_nodes.hpp @@ -8,11 +8,10 @@ namespace nodes { -// replace enum with structure ?? enum class Modifier { IN, // <- x REF, // <> x - CONST, // -- x (or nothing sometimes) + CONST, // -- x (or x sometimes) OUT, // -> x // IN_OR_REF, // <-|<> x @@ -37,9 +36,114 @@ enum class Modifier { namespace utils { -inline bool is_suffix_modifier(nodes::Modifier modifier) { - return modifier == nodes::Modifier::OPTIONAL || - modifier == nodes::Modifier::RESULT; +inline bool is_suffix_modifier(Modifier modifier) { + return modifier == Modifier::OPTIONAL || modifier == Modifier::RESULT; +} + +inline bool modifier_contains_IN(Modifier modifier) { + return modifier == Modifier::IN || // + modifier == Modifier::IN_OR_REF || // + modifier == Modifier::IN_OR_CONST || // + modifier == Modifier::IN_OR_OUT || // + modifier == Modifier::IN_OR_REF_OR_OUT || // + modifier == Modifier::IN_OR_CONST_OR_OUT || // + modifier == Modifier::IN_OR_REF_OR_CONST || // + modifier == Modifier::IN_OR_REF_OR_CONST_OR_OUT; // +} + +inline bool modifier_contains_REF(Modifier modifier) { + return modifier == Modifier::REF || // + modifier == Modifier::IN_OR_REF || // + modifier == Modifier::REF_OR_OUT || // + modifier == Modifier::REF_OR_CONST || // + modifier == Modifier::IN_OR_REF_OR_OUT || // + modifier == Modifier::IN_OR_REF_OR_CONST || // + modifier == Modifier::REF_OR_CONST_OR_OUT || // + modifier == Modifier::IN_OR_REF_OR_CONST_OR_OUT; // +} + +inline bool modifier_contains_CONST(Modifier modifier) { + return modifier == Modifier::CONST || // + modifier == Modifier::IN_OR_CONST || // + modifier == Modifier::CONST_OR_OUT || // + modifier == Modifier::REF_OR_CONST || // + modifier == Modifier::IN_OR_CONST_OR_OUT || // + modifier == Modifier::IN_OR_REF_OR_CONST || // + modifier == Modifier::REF_OR_CONST_OR_OUT || // + modifier == Modifier::IN_OR_REF_OR_CONST_OR_OUT; // +} + +inline bool modifier_contains_OUT(Modifier modifier) { + return modifier == Modifier::OUT || // + modifier == Modifier::REF_OR_OUT || // + modifier == Modifier::CONST_OR_OUT || // + modifier == Modifier::IN_OR_OUT || // + modifier == Modifier::IN_OR_REF_OR_OUT || // + modifier == Modifier::IN_OR_CONST_OR_OUT || // + modifier == Modifier::REF_OR_CONST_OR_OUT || // + modifier == Modifier::IN_OR_REF_OR_CONST_OR_OUT; // +} + +// possible casts: +// <> => -> +// <> => <- +// <> => -- +inline bool can_cast_modifier(Modifier from, Modifier to) { + if (is_suffix_modifier(from) || is_suffix_modifier(to) || + from == Modifier::NONE || to == Modifier::NONE) { + return false; + } + + switch (from) { + case Modifier::IN: // // <- x + return modifier_contains_IN(to); // + case Modifier::REF: // // <> x + return true; // + case Modifier::CONST: // // -- x (or x sometimes) + return modifier_contains_CONST(to); // + case Modifier::OUT: // // -> x + return modifier_contains_OUT(to); // + // + case Modifier::IN_OR_REF: // // <-|<> x + return modifier_contains_IN(to); // + case Modifier::IN_OR_CONST: // // <-|-- x + return modifier_contains_IN(to) && // + modifier_contains_CONST(to); // + case Modifier::REF_OR_OUT: // // <>|-> x + return modifier_contains_OUT(to); // + case Modifier::CONST_OR_OUT: // // --|-> x + return modifier_contains_CONST(to) && // + modifier_contains_OUT(to); // + case Modifier::REF_OR_CONST: // // <>|-- x + return modifier_contains_CONST(to); // + case Modifier::IN_OR_OUT: // // <-|-> x + return modifier_contains_IN(to) && // + modifier_contains_OUT(to); // + // + case Modifier::IN_OR_REF_OR_OUT: // // <-|<>|-> x + return modifier_contains_IN(to) && // + modifier_contains_OUT(to); // + case Modifier::IN_OR_CONST_OR_OUT: // // <-|--|-> x + return modifier_contains_IN(to) && // + modifier_contains_CONST(to) && // + modifier_contains_OUT(to); // + case Modifier::IN_OR_REF_OR_CONST: // // <-|<>|-- x + return modifier_contains_IN(to) && // + modifier_contains_CONST(to); // + case Modifier::REF_OR_CONST_OR_OUT: // // <>|--|-> x + return modifier_contains_CONST(to) && // + modifier_contains_OUT(to); // + // + case Modifier::IN_OR_REF_OR_CONST_OR_OUT: // // <-|<>|--|-> x + return modifier_contains_IN(to) && // + modifier_contains_CONST(to) && // + modifier_contains_OUT(to); // + default: + break; + } + + error_handling::handle_general_error("Unreachable"); + exit(1); // unreachable } } // namespace utils diff --git a/include/nodes/type_nodes.hpp b/include/nodes/type_nodes.hpp index 55832db..26b46fd 100644 --- a/include/nodes/type_nodes.hpp +++ b/include/nodes/type_nodes.hpp @@ -49,26 +49,26 @@ private: class Type { public: - Type(Identifier &&identifier, bool is_on_heap = false, + Type(Identifier &&identifier, Modifier modifier = nodes::Modifier::CONST, const std::optional &annotation = std::nullopt) - : name_(std::move(identifier)), is_on_heap_(is_on_heap), + : name_(std::move(identifier)), modifier_(modifier), annotation_(annotation) {} - Type(const Identifier &identifier, bool is_on_heap = false, + Type(const Identifier &identifier, Modifier modifier = nodes::Modifier::CONST, const std::optional &annotation = std::nullopt) - : name_(identifier), is_on_heap_(is_on_heap), annotation_(annotation) {} + : name_(identifier), modifier_(modifier), annotation_(annotation) {} Type(Identifier &&identifier, std::vector &¶meters, - bool is_on_heap = false, + Modifier modifier = nodes::Modifier::CONST, const std::optional &annotation = std::nullopt) : name_(std::move(identifier)), parameters_(std::move(parameters)), - is_on_heap_(is_on_heap), annotation_(annotation) {} + modifier_(modifier), annotation_(annotation) {} Type(const Identifier &identifier, std::vector &¶meters, - bool is_on_heap = false, + Modifier modifier = nodes::Modifier::CONST, const std::optional &annotation = std::nullopt) : name_(identifier), parameters_(std::move(parameters)), - is_on_heap_(is_on_heap), annotation_(annotation) {} + modifier_(modifier), annotation_(annotation) {} // @@ -90,9 +90,9 @@ public: // - bool is_on_heap() const { return is_on_heap_; } + Modifier get_modifier() const { return modifier_; } - void set_is_on_heap(bool is_on_heap) { is_on_heap_ = is_on_heap; } + void set_modifier(Modifier modifier) { modifier_ = modifier; } // @@ -133,7 +133,7 @@ public: // bool operator==(const Type &other) const { - if (name_ != other.name_ || is_on_heap_ != other.is_on_heap_ || + if (name_ != other.name_ || modifier_ != other.modifier_ || parameters_.size() != other.parameters_.size()) { return false; } @@ -156,8 +156,8 @@ public: return *name_.get() < *other.name_.get(); } - if (is_on_heap_ != other.is_on_heap_) { - return is_on_heap_ < other.is_on_heap_; + if (modifier_ != other.modifier_) { + return modifier_ < other.modifier_; } if (parameters_.size() != other.parameters_.size()) { @@ -198,8 +198,7 @@ public: private: Identifier name_; std::vector parameters_; - // or use allocator ?? - bool is_on_heap_ = false; + Modifier modifier_ = Modifier::NONE; std::optional annotation_; }; @@ -207,12 +206,12 @@ class TypeStorage { friend TypeProxy; public: - TypeProxy primitive_type(builtin::types::Type type, Node node = Node()) { + TypeProxy primitive_type(builtin::types::Type type) { if (unit_type_id.has_value()) { return TypeProxy(*this, unit_type_id.value()); } else { unit_type_id = storage_.size(); - return add_type(Type(Identifier(node, Identifier::SIMPLE_TYPE, + return add_type(Type(Identifier(Node(), Identifier::SIMPLE_TYPE, builtin::types::to_string(type)))); } } @@ -235,6 +234,13 @@ public: std::move(parameters))); } + nodes::TypeProxy add_modification_of(TypeProxy type, Modifier modifier) { + Type type_copy = *type.get(); + type_copy.set_modifier(modifier); + + return add_type(std::move(type_copy)); + } + TypeProxy add_type(const Type &type) { storage_.push_back(type); return TypeProxy(*this, storage_.size() - 1); @@ -256,57 +262,60 @@ private: std::vector storage_; }; -class ModifiedTypeProxy { -public: - ModifiedTypeProxy(nodes::TypeProxy type, - nodes::Modifier modifier = nodes::Modifier::NONE) - : type_(type), modifier_(modifier) {} - - // - - nodes::Modifier get_modifier() const { return modifier_; } - - void set_modifier(nodes::Modifier modifier) { modifier_ = modifier; } - - // - - nodes::Type *get_type() { return type_.get(); } - - const nodes::Type *get_type() const { return type_.get(); } - - const nodes::TypeProxy get_type_proxy() const { return type_; } - - // - - bool operator==(const ModifiedTypeProxy &other) const { - return *type_.get() == *other.type_.get() && modifier_ == other.modifier_; - } - - bool operator!=(const ModifiedTypeProxy &other) const { - return !(*this == other); - } - - // - - bool operator<(const ModifiedTypeProxy &other) const { - return *type_.get() < *other.type_.get() || - (*type_.get() == *other.type_.get() && modifier_ < other.modifier_); - } - - bool operator>(const ModifiedTypeProxy &other) const { return other < *this; } - - bool operator<=(const ModifiedTypeProxy &other) const { - return !operator>(other); - } - - bool operator>=(const ModifiedTypeProxy &other) const { - return !operator<(other); - } - -private: - nodes::TypeProxy type_; - nodes::Modifier modifier_; -}; +// class ModifiedTypeProxy { +// public: +// ModifiedTypeProxy(nodes::TypeProxy type, +// nodes::Modifier modifier = nodes::Modifier::NONE) +// : type_(type), modifier_(modifier) {} +// +// // +// +// nodes::Modifier get_modifier() const { return modifier_; } +// +// void set_modifier(nodes::Modifier modifier) { modifier_ = modifier; } +// +// // +// +// nodes::Type *get_type() { return type_.get(); } +// +// const nodes::Type *get_type() const { return type_.get(); } +// +// const nodes::TypeProxy get_type_proxy() const { return type_; } +// +// // +// +// bool operator==(const ModifiedTypeProxy &other) const { +// return *type_.get() == *other.type_.get() && modifier_ == +// other.modifier_; +// } +// +// bool operator!=(const ModifiedTypeProxy &other) const { +// return !(*this == other); +// } +// +// // +// +// bool operator<(const ModifiedTypeProxy &other) const { +// return *type_.get() < *other.type_.get() || +// (*type_.get() == *other.type_.get() && modifier_ < +// other.modifier_); +// } +// +// bool operator>(const ModifiedTypeProxy &other) const { return other < +// *this; } +// +// bool operator<=(const ModifiedTypeProxy &other) const { +// return !operator>(other); +// } +// +// bool operator>=(const ModifiedTypeProxy &other) const { +// return !operator<(other); +// } +// +// private: +// nodes::TypeProxy type_; +// nodes::Modifier modifier_; +// }; class TypeCheckResult { public: @@ -315,12 +324,11 @@ public: return TypeCheckResult(); } - explicit TypeCheckResult(std::optional type) - : type_(type) {} + explicit TypeCheckResult(std::optional type) : type_(type) {} // - ModifiedTypeProxy &get() { + TypeProxy &get() { if (!type_.has_value()) { error_handling::handle_general_error( "Access to invalid type in TypeCheckResult"); @@ -329,7 +337,7 @@ public: return type_.value(); } - const ModifiedTypeProxy &get() const { + const TypeProxy &get() const { if (!type_.has_value()) { error_handling::handle_general_error( "Access to invalid type in TypeCheckResult"); @@ -338,7 +346,7 @@ public: return type_.value(); } - void set(ModifiedTypeProxy type) { type_ = type; } + void set(TypeProxy type) { type_ = type; } // @@ -348,7 +356,7 @@ private: TypeCheckResult() = default; private: - std::optional type_; + std::optional type_; }; } // namespace nodes diff --git a/src/basic_type_check.cpp b/src/basic_type_check.cpp index 49de748..84687c9 100644 --- a/src/basic_type_check.cpp +++ b/src/basic_type_check.cpp @@ -59,6 +59,6 @@ nodes::TypeCheckResult type_check_literal(const nodes::Literal &literal, error_handling::handle_general_error("Unreachable"); exit(1); // unreachable -} // IN PROGRESS: modifiers ?? +} } // namespace type_check diff --git a/src/builders/type_builders.cpp b/src/builders/type_builders.cpp index 7c236c0..6f3f5fa 100644 --- a/src/builders/type_builders.cpp +++ b/src/builders/type_builders.cpp @@ -87,12 +87,13 @@ nodes::TypeProxy build_array_type(parser::ParseTree::Node parser_node, build_node(parser_node)); } +// TODO: add different reference types // '^' type nodes::TypeProxy build_reference_type(parser::ParseTree::Node parser_node, nodes::TypeStorage &type_storage) { nodes::TypeProxy type = build_type(parser_node.nth_named_child(0), type_storage); - type.get()->set_is_on_heap(true); + type.get()->set_modifier(nodes::Modifier::REF); return type; } @@ -124,7 +125,7 @@ nodes::TypeProxy build_modified_type(parser::ParseTree::Node parser_node, return type_storage.add_type( nodes::Type(nodes::Identifier(build_node(parser_node), nodes::Identifier::SIMPLE_TYPE, identifier), - std::move(parameters), false)); + std::move(parameters))); } // type_identifier ('[' type+ ']')? @@ -141,7 +142,7 @@ nodes::TypeProxy build_simple_type(parser::ParseTree::Node parser_node, } return type_storage.add_type( - nodes::Type(build_identifier(name_node), std::move(parameters), false)); + nodes::Type(build_identifier(name_node), std::move(parameters))); } } // namespace builders diff --git a/src/expression_type_check.cpp b/src/expression_type_check.cpp index decf34a..87691ce 100644 --- a/src/expression_type_check.cpp +++ b/src/expression_type_check.cpp @@ -63,7 +63,7 @@ type_check_expression(const nodes::Expression &expression, case 12: // Literal // TODO return type_check_literal(*expression.get().value(), - sources_manager, state); + sources_manager); // --- empty lines case 13: // Extra return nodes::TypeCheckResult( @@ -113,7 +113,7 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, return condition_result.value(); } - if (condition_result.value().get().get_type()->to_builtin() != + if (condition_result.value().get().get()->to_builtin() != builtin::types::Type::BOOL) { sources_manager.get_error_log()->add_error( error_handling::ErrorLog::ErrorMessage( @@ -149,7 +149,7 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, // } // TODO: ranges ?? - if (condition_result.value().get().get_type()->to_builtin() != + if (condition_result.value().get().get()->to_builtin() != builtin::types::Type::ARRAY) { sources_manager.get_error_log()->add_error( error_handling::ErrorLog::ErrorMessage( @@ -165,12 +165,11 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, return expression_result; } - // TODO: modifier checks ?? + // TODO: modifier checks ??, modifiers ?? return nodes::TypeCheckResult( - nodes::ModifiedTypeProxy(sources_manager.get_type_storage()->add_array_of( - expression_result.get().get_type_proxy()), - expression_result.get().get_modifier())); + sources_manager.get_type_storage()->add_array_of( + expression_result.get())); } // IN PROGRESS // --- containers @@ -187,7 +186,8 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression, if (!last_expression_result.has_value()) { last_expression_result = expression_result; } else { - if (last_expression_result.value().get() != expression_result.get()) { + if (*last_expression_result.value().get().get() != + *expression_result.get().get()) { sources_manager.get_error_log()->add_error( error_handling::ErrorLog::ErrorMessage( *expression.get_expression(i), @@ -206,10 +206,9 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression, return nodes::TypeCheckResult::construct_invalid_result(); } - return nodes::TypeCheckResult(nodes::ModifiedTypeProxy( + return nodes::TypeCheckResult( sources_manager.get_type_storage()->add_array_of( - last_expression_result.value().get().get_type_proxy()), - last_expression_result.value().get().get_modifier())); + last_expression_result.value().get())); } // IN PROGRESS // TODO @@ -245,8 +244,7 @@ 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_type() != - *returned_result.get().get_type()) { + 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", @@ -259,8 +257,7 @@ nodes::TypeCheckResult type_check_return(const nodes::Return &expression, break; case nodes::Return::RETURN: if (state.returned_type.has_value()) { - if (*state.returned_type.value().get_type() != - *returned_result.get().get_type()) { + 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", @@ -301,8 +298,7 @@ nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression, return value_result; } - if (index_result.get().get_type()->to_builtin() != - builtin::types::Type::INDEX) { + if (index_result.get().get()->to_builtin() != builtin::types::Type::INDEX) { sources_manager.get_error_log()->add_error( error_handling::ErrorLog::ErrorMessage( expression, "Can access only by Index", @@ -310,8 +306,7 @@ nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression, return nodes::TypeCheckResult::construct_invalid_result(); } - if (value_result.get().get_type()->to_builtin() != - builtin::types::Type::ARRAY) { + if (value_result.get().get()->to_builtin() != builtin::types::Type::ARRAY) { sources_manager.get_error_log()->add_error( error_handling::ErrorLog::ErrorMessage( expression, "Can apply array access only to Array", @@ -322,7 +317,7 @@ nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression, // TODO: modifier checks ?? return nodes::TypeCheckResult( - value_result.get().get_type()->get_parameter_proxy(0)); + value_result.get().get()->get_parameter_proxy(0)); } nodes::TypeCheckResult type_check_tuple_access(const nodes::Access &expression, @@ -341,8 +336,7 @@ nodes::TypeCheckResult type_check_tuple_access(const nodes::Access &expression, ->get() // Index type .value(); - if (value_result.get().get_type()->to_builtin() != - builtin::types::Type::TUPLE) { + if (value_result.get().get()->to_builtin() != builtin::types::Type::TUPLE) { sources_manager.get_error_log()->add_error( error_handling::ErrorLog::ErrorMessage( expression, "Can apply tuple access only to Tuple", @@ -353,7 +347,7 @@ nodes::TypeCheckResult type_check_tuple_access(const nodes::Access &expression, // TODO: modifier checks ?? return nodes::TypeCheckResult( - value_result.get().get_type()->get_parameter_proxy(index)); + value_result.get().get()->get_parameter_proxy(index)); } nodes::TypeCheckResult type_check_access(const nodes::Access &expression, @@ -388,12 +382,11 @@ type_check_modifier_expression(const nodes::ModifierExpression &expression, // '!' - open optional / result -> value / panic - switch (modified_result.get().get_type()->to_builtin()) { + switch (modified_result.get().get()->to_builtin()) { case builtin::types::Type::OPTIONAL: case builtin::types::Type::RESULT: - modified_result.set(nodes::ModifiedTypeProxy( - modified_result.get().get_type()->get_parameter_proxy(0), - modified_result.get().get_modifier())); + // TODO: how to unwrap external modifier ?? + modified_result.set(modified_result.get().get()->get_parameter_proxy(0)); break; default: sources_manager.get_error_log()->add_error( @@ -404,7 +397,8 @@ type_check_modifier_expression(const nodes::ModifierExpression &expression, } } else { // TODO: check that modifier can be applied - modified_result.get().set_modifier(expression.get_modifier()); + modified_result.set(sources_manager.get_type_storage()->add_modification_of( + modified_result.get(), expression.get_modifier())); } return modified_result; diff --git a/src/printers/type_printers.cpp b/src/printers/type_printers.cpp index 419dd0d..ca4644b 100644 --- a/src/printers/type_printers.cpp +++ b/src/printers/type_printers.cpp @@ -7,7 +7,8 @@ namespace printers { // TODO: better printing format for builtin types void print_type(const nodes::Type &type, printers::Printer &printer) { - if (type.is_on_heap()) { + // TODO: more modifier types + if (type.get_modifier() == nodes::Modifier::REF) { printer.print("^"); }