#include "statement_nodes.hpp" namespace nodes { // TODO: return error type instead of bool ?? bool FunctionDefinition::combine( FunctionDefinition &&other_function_definition) { // should be same in all definitions of one function if (*name_.get() != *other_function_definition.name_.get()) { return false; } if (modifier_ != other_function_definition.modifier_) { return false; } if (are_annotations_same_to_names_ != other_function_definition.are_annotations_same_to_names_) { return false; } // only one definition should have constraints if (!constraints_.empty() && !other_function_definition.constraints_.empty()) { return false; } // only one definition should have expression if (expression_.has_value() && other_function_definition.expression_.has_value()) { return false; } // only one definition should have documentation if (docs_.get_description().has_value() && other_function_definition.docs_.get_description().has_value()) { return false; } if (docs_.get_annotations_info_size() > 0 && other_function_definition.docs_.get_annotations_info_size() > 0) { return false; } // TODO: think about required checks // check, that function definitions have same named arguments count 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 if ((!arguments_[i].get_annotation().has_value() && !other_function_definition.arguments_[i] .get_annotation() .has_value()) || (arguments_[i].get_annotation().has_value() && other_function_definition.arguments_[i] .get_annotation() .has_value() && *arguments_[i].get_annotation().value() != *other_function_definition.arguments_[i] .get_annotation() .value())) { return false; } // check that all argument names are 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())) { return false; } // check that types are are in zero or one set of arguments (TODO: can be // same and in two sets ??) if (arguments_[i].get_type().has_value() && other_function_definition.arguments_[i].get_type().has_value()) { return false; } // argument modifiers should be same if (arguments_[i].get_before_modifier() != other_function_definition.arguments_[i].get_before_modifier() || arguments_[i].get_after_modifier() != other_function_definition.arguments_[i].get_after_modifier()) { return false; } // TODO: other checks (annotations, ...) } else if (i < arguments_.size()) { // last arguments shouldn't be annotated (because they are not annotated // in other function definition statement) if (arguments_[i].get_annotation().has_value()) { return false; } // last arguments can only be unnamed arguments (returned values) if (arguments_[i].get_name().has_value()) { return false; } } else { // i < other_function_definition.size() // last arguments shouldn't be annotated (because they are not annotated // in other function definition statement) if (other_function_definition.arguments_[i] .get_annotation() .has_value()) { return false; } // last arguments can only be unnamed arguments (returned values) if (other_function_definition.arguments_[i].get_name().has_value()) { return false; } } } // combine docs // all docs should be in one definition if (other_function_definition.docs_.get_description().has_value() || other_function_definition.docs_.get_annotations_info_size() > 0) { if (docs_.get_annotations_info_size() > 0 || docs_.get_description().has_value()) { return false; } docs_ = std::move(other_function_definition.docs_); } if (!other_function_definition.constraints_.empty()) { constraints_ = std::move(other_function_definition.constraints_); } if (other_function_definition.expression_.has_value()) { expression_ = other_function_definition.expression_; } // TODO: arguments: check and merge return true; } bool TypeDefinition::combine(TypeDefinition &&other_type_definition) { // should be same in all definitions of one type if (*name_.get() != *other_type_definition.name_.get()) { return false; } if (is_on_heap_ != other_type_definition.is_on_heap_) { return false; } // only one definition should have documentation if (docs_.get_description().has_value() && other_type_definition.docs_.get_description().has_value()) { return false; } if (docs_.get_annotations_info_size() > 0 && other_type_definition.docs_.get_annotations_info_size() > 0) { return false; } // 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 false; } // combine docs // all docs should be in one definition if (other_type_definition.docs_.get_description().has_value() || other_type_definition.docs_.get_annotations_info_size() > 0) { if (docs_.get_annotations_info_size() > 0 || docs_.get_description().has_value()) { return false; } 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_); } methods_.reserve(methods_.size() + other_type_definition.methods_.size()); for (size_t i = 0; i < other_type_definition.methods_.size(); ++i) { methods_.push_back(std::move(other_type_definition.methods_[i])); } // TODO: combine methods ?? return true; } bool TypeclassDefinition::combine( TypeclassDefinition &&other_typeclass_definition) { // should be same in all definitions of one typeclass if (*name_.get() != *other_typeclass_definition.name_.get()) { return false; } // only one definition should have documentation if (docs_.get_description().has_value() && other_typeclass_definition.docs_.get_description().has_value()) { return false; } if (docs_.get_annotations_info_size() > 0 && other_typeclass_definition.docs_.get_annotations_info_size() > 0) { return false; } // only one definition should define base typeclasses if (!base_typeclasses_.empty() && !other_typeclass_definition.base_typeclasses_.empty()) { return false; } // combine docs // all docs should be in one definition if (other_typeclass_definition.docs_.get_description().has_value() || other_typeclass_definition.docs_.get_annotations_info_size() > 0) { if (docs_.get_annotations_info_size() > 0 || docs_.get_description().has_value()) { return false; } docs_ = std::move(other_typeclass_definition.docs_); } if (!other_typeclass_definition.base_typeclasses_.empty()) { base_typeclasses_ = std::move(other_typeclass_definition.base_typeclasses_); } methods_.reserve(methods_.size() + other_typeclass_definition.methods_.size()); for (size_t i = 0; i < other_typeclass_definition.methods_.size(); ++i) { methods_.push_back(std::move(other_typeclass_definition.methods_[i])); } // TODO: combine methods ?? return true; } } // namespace nodes