combine functions for statements partially implemented

This commit is contained in:
ProgramSnail 2023-07-26 23:17:14 +03:00
parent 6b74398f8c
commit 437c9692ec
3 changed files with 269 additions and 1 deletions

@ -1 +1 @@
Subproject commit 1c19b471990acb91cc0ccc9426d988debab8cb27
Subproject commit a75ea8012d6b104fb26efcd17e5ebc02ab49f7af

View file

@ -256,6 +256,10 @@ public:
return are_annotations_same_to_names_;
}
//
bool combine(FunctionDefinition &&other_function_definition);
private:
SymbolDocs docs_;
std::vector<Constraint> constraints_;
@ -326,6 +330,10 @@ public:
return &methods_.at(id);
}
//
bool combine(TypeDefinition &&other_type_definition);
private:
SymbolDocs docs_;
bool is_on_heap_;
@ -378,6 +386,10 @@ public:
return &methods_.at(id);
}
//
bool combine(TypeclassDefinition &&other_typeclass_definition);
private:
SymbolDocs docs_;
Identifier name_;

256
src/statement_nodes.cpp Normal file
View file

@ -0,0 +1,256 @@
#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