diff --git a/include/basic_nodes.hpp b/include/basic_nodes.hpp index ee444d2..801a412 100644 --- a/include/basic_nodes.hpp +++ b/include/basic_nodes.hpp @@ -115,6 +115,16 @@ public: value_ += name; } + // + + bool operator==(const Identifier &other_identifier) const { + return type_ == other_identifier.type_ && value_ == other_identifier.value_; + } + + bool operator!=(const Identifier &other_identifier) const { + return !(*this == other_identifier); + } + private: IdentifierType type_; std::string value_; diff --git a/include/statement_nodes.hpp b/include/statement_nodes.hpp index c1572ca..a422bb0 100644 --- a/include/statement_nodes.hpp +++ b/include/statement_nodes.hpp @@ -17,6 +17,7 @@ enum class CombineResult { MORE_THEN_ONE_DOCS_ERROR, MORE_THEN_ONE_CONSTRAINTS_ERROR, MORE_THEN_ONE_DEFINITION_BODY_ERROR, + TYPECLASSES_ERROR, ARGUMENTS_ERROR, DIFFERENT_STATEMENT_TYPES, STATEMENTS_CANT_BE_COMBINED_ERROR, diff --git a/include/type_nodes.hpp b/include/type_nodes.hpp index 97fc055..8638553 100644 --- a/include/type_nodes.hpp +++ b/include/type_nodes.hpp @@ -56,10 +56,14 @@ public: : Node(node), name_(identifier), parameters_(std::move(parameters)), is_on_heap_(is_on_heap), modifier_(modifier) {} + // + Identifier *get_name() { return &name_; } const Identifier *get_name() const { return &name_; } + // + size_t get_parametrs_size() const { return parameters_.size(); } Type *get_parameter(size_t id) { return parameters_.at(id).get(); } @@ -68,10 +72,34 @@ public: return parameters_.at(id).get(); } + // + bool is_on_heap() const { return is_on_heap_; } Modifier get_modifier() const { return modifier_; } + // + + bool operator==(const Type &other_type) const { + if (name_ != other_type.name_ || is_on_heap_ != other_type.is_on_heap_ || + modifier_ != other_type.modifier_ || + parameters_.size() != other_type.parameters_.size()) { + return false; + } + + for (size_t i = 0; i < parameters_.size(); ++i) { + if (*parameters_[i].get() != *other_type.parameters_[i].get()) { + return false; + } + } + + return true; + } + + bool operator!=(const Type &other_type) const { + return !(*this == other_type); + } + private: Identifier name_; std::vector parameters_; diff --git a/src/statement_builders.cpp b/src/statement_builders.cpp index 8a7fe14..33cdde1 100644 --- a/src/statement_builders.cpp +++ b/src/statement_builders.cpp @@ -166,8 +166,8 @@ parser::ParseTree::Node collect_symbol_doc_nodes( return current_node; } -// definition_info? annotation_info* '^'? simple_type (argument_type* '=' -// variant_type)? ('{' function_definition* '}' | ';') +// definition_info? annotation_info* '^'? (simple_type | typeclass) +// (argument_type* '=' variant_type)? ';' nodes::TypeDefinition build_type_definition(parser::ParseTree::Node parser_node, nodes::TypeStorage &type_storage) { bool is_on_heap = parser_node.nth_child(0).get_value() == "^"; @@ -262,7 +262,7 @@ nodes::TypeDefinition build_type_definition(parser::ParseTree::Node parser_node, std::move(type)); } -// definition_info? annotation_info* (constraint ';')* _var_let_? (simple_name +// definition_info? annotation_info* (constraint ';')* '.'? (simple_name // | '(' operator ')') (annotation? _reference_? argument_name '?'?)* (: // (annotation? _reference_ type)+)? // ('=' (block | expression ';') | ';') @@ -410,6 +410,13 @@ nodes::FunctionDefinition build_function_definition( "Less types then arguments in function definition", parser_node); } + if (current_type_id == 0 && !expression_node.has_value()) { + error_handling::handle_parsing_error( + "Can't declare function without types (types or function body should " + "be added)", + parser_node); + } + // automatic annotations bool are_annotations_same_to_names = (!at_least_one_argument_annotation_found && current_type_id == 0); diff --git a/src/statement_nodes.cpp b/src/statement_nodes.cpp index 1fb7318..b92b1bb 100644 --- a/src/statement_nodes.cpp +++ b/src/statement_nodes.cpp @@ -6,29 +6,34 @@ namespace nodes { -// TODO: function overloading, etc. ?? bool FunctionDefinition::is_same_to( const FunctionDefinition &other_function_definition) const { - if (*name_.get() != *other_function_definition.name_.get()) { + if (name_ != other_function_definition.name_) { return false; } return true; } -// TODO: function overloading, etc. ?? +// TODO +// possible configurations: +// name 'arg1 'arg2 'arg3 : Type1 Type2 Type3 -> Type4; // function declaration +// name 'arg1 'arg2 'arg3 : Type1 Type2 Type3 -> Type4 = ... // function +// definition (with types) +// name 'arg1 'arg2 -> 'arg3 = ... // function definition (without types) CombineResult FunctionDefinition::combine(FunctionDefinition &&other_function_definition) { - // should be same in all definitions of one function - if (*name_.get() != *other_function_definition.name_.get()) { + // names should be the same + if (name_ != other_function_definition.name_) { return CombineResult::DIFFERENT_NAME_ERROR; } + + // modifiers should be the same if (return_modifier_ != other_function_definition.return_modifier_) { return CombineResult::DIFFERNENT_MODIFIER_ERROR; } if (is_method_ != other_function_definition.is_method_) { return CombineResult::DIFFERNENT_MODIFIER_ERROR; // other error type ?? } - if (are_annotations_same_to_names_ != other_function_definition.are_annotations_same_to_names_) { return CombineResult::ARGUMENTS_ERROR; @@ -40,7 +45,7 @@ FunctionDefinition::combine(FunctionDefinition &&other_function_definition) { return CombineResult::MORE_THEN_ONE_CONSTRAINTS_ERROR; } - // only one definition should have expression + // only one definition should have expression (body) if (expression_.has_value() && other_function_definition.expression_.has_value()) { return CombineResult::MORE_THEN_ONE_DEFINITION_BODY_ERROR; @@ -56,15 +61,14 @@ FunctionDefinition::combine(FunctionDefinition &&other_function_definition) { return CombineResult::MORE_THEN_ONE_DOCS_ERROR; } - // TODO: think about required checks - // check, that function definitions have same named arguments count + // check, that function definitions have same named arguments for (size_t i = 0; i < std::max(arguments_.size(), other_function_definition.arguments_.size()); ++i) { if (i < arguments_.size() && i < other_function_definition.arguments_.size()) { - // check that all argument annotations are the same + // annotations should be the same if ((!arguments_[i].get_annotation().has_value() && !other_function_definition.arguments_[i] .get_annotation() @@ -80,27 +84,25 @@ FunctionDefinition::combine(FunctionDefinition &&other_function_definition) { return CombineResult::ARGUMENTS_ERROR; } - // check that all argument names are the same + // argument names should be the same if ((!arguments_[i].get_name().has_value() && !other_function_definition.arguments_[i].get_name().has_value()) || (arguments_[i].get_name().has_value() && other_function_definition.arguments_[i].get_name().has_value() && - *arguments_[i].get_name().value()->get() != - *other_function_definition.arguments_[i] - .get_name() - .value() - ->get())) { + arguments_[i].get_name().value() != + other_function_definition.arguments_[i].get_name().value())) { return CombineResult::ARGUMENTS_ERROR; } - // check that types are are in zero or one set of arguments (TODO: can be - // same and in two sets ??) + // types should be the same (if present in both definitions) if (arguments_[i].get_type().has_value() && - other_function_definition.arguments_[i].get_type().has_value()) { + other_function_definition.arguments_[i].get_type().has_value() && + *arguments_[i].get_type().value() != + *other_function_definition.arguments_[i].get_type().value()) { return CombineResult::ARGUMENTS_ERROR; } - // argument modifiers should be same + // argument modifiers should be the same if (arguments_[i].get_before_modifier() != other_function_definition.arguments_[i].get_before_modifier() || arguments_[i].get_after_modifier() != @@ -108,26 +110,24 @@ FunctionDefinition::combine(FunctionDefinition &&other_function_definition) { return CombineResult::ARGUMENTS_ERROR; } } else if (i < arguments_.size()) { - // last arguments shouldn't be annotated (because they are not annotated - // in other function definition statement) + // annotations should be the same if (arguments_[i].get_annotation().has_value()) { return CombineResult::ARGUMENTS_ERROR; } - // last arguments can only be unnamed arguments (returned values) + // names should be the same if (arguments_[i].get_name().has_value()) { return CombineResult::ARGUMENTS_ERROR; } } else { // i < other_function_definition.size() - // last arguments shouldn't be annotated (because they are not annotated - // in other function definition statement) + // annotations should be the same if (other_function_definition.arguments_[i] .get_annotation() .has_value()) { return CombineResult::ARGUMENTS_ERROR; } - // last arguments can only be unnamed arguments (returned values) + // names should be the same if (other_function_definition.arguments_[i].get_name().has_value()) { return CombineResult::ARGUMENTS_ERROR; } @@ -175,21 +175,47 @@ FunctionDefinition::combine(FunctionDefinition &&other_function_definition) { bool TypeDefinition::is_same_to( const TypeDefinition &other_type_definition) const { - if (*name_.get() != *other_type_definition.name_.get()) { + if (name_ != other_type_definition.name_) { return false; } return true; } +// possible configurations: +// Type[...] 'A 'B 'C; // declare type / define typeclass (statement without +// args in this case) +// Type[...] 'A 'B 'C = ... // define type CombineResult TypeDefinition::combine(TypeDefinition &&other_type_definition) { - // should be same in all definitions of one type - if (*name_.get() != *other_type_definition.name_.get()) { + // name should be same + if (name_ != other_type_definition.name_) { return CombineResult::DIFFERENT_NAME_ERROR; } + + // modifier should be the same if (is_on_heap_ != other_type_definition.is_on_heap_) { return CombineResult::DIFFERNENT_MODIFIER_ERROR; } + // typeclasses should be the same + if (typeclasses_.size() != other_type_definition.typeclasses_.size()) { + return CombineResult::ARGUMENTS_ERROR; + } + for (size_t i = 0; i < typeclasses_.size(); ++i) { + if (typeclasses_[i] != other_type_definition.typeclasses_[i]) { + return CombineResult::ARGUMENTS_ERROR; + } + } + + // arguments should be the same + if (arguments_.size() != other_type_definition.arguments_.size()) { + return CombineResult::ARGUMENTS_ERROR; + } + for (size_t i = 0; i < arguments_.size(); ++i) { + if (arguments_[i] != other_type_definition.arguments_[i]) { + return CombineResult::ARGUMENTS_ERROR; + } + } + // only one definition should have documentation if (docs_.get_description().has_value() && other_type_definition.docs_.get_description().has_value()) { @@ -200,12 +226,9 @@ CombineResult TypeDefinition::combine(TypeDefinition &&other_type_definition) { return CombineResult::MORE_THEN_ONE_DOCS_ERROR; } - // only one definition should define type and arguments (they should be - // defined in one place) - if ((other_type_definition.type_.has_value() || - !other_type_definition.arguments_.empty()) && - (type_.has_value() || !arguments_.empty())) { - return CombineResult::ARGUMENTS_ERROR; + // only one type should define type / body + if (type_.has_value() && other_type_definition.type_.has_value()) { + return CombineResult::MORE_THEN_ONE_DEFINITION_BODY_ERROR; } // combine docs @@ -220,10 +243,6 @@ CombineResult TypeDefinition::combine(TypeDefinition &&other_type_definition) { docs_ = std::move(other_type_definition.docs_); } - if (!other_type_definition.arguments_.empty()) { - arguments_ = std::move(other_type_definition.arguments_); - } - if (other_type_definition.type_.has_value()) { type_ = std::move(other_type_definition.type_); } @@ -247,9 +266,13 @@ bool Statement::is_same_to(const Statement &other_statement) const { return std::get(expression_) .is_same_to(std::move( std::get(other_statement.expression_))); - case 3: // EmptyLines + case 3: // Extra + return false; + case 4: // EmptyLines return false; default: + error_handling::handle_general_error( + "Unexpected statement type in is_same_to"); break; } @@ -273,9 +296,13 @@ CombineResult Statement::combine(Statement &&other_statement) { return std::get(expression_) .combine(std::move( std::get(other_statement.expression_))); - case 3: // EmptyLines + case 3: // Extra + return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR; + case 4: // EmptyLines return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR; default: + error_handling::handle_general_error( + "Unexpected statement type in combine"); break; }