mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-06 06:58:46 +00:00
256 lines
8.1 KiB
C++
256 lines
8.1 KiB
C++
#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
|