combine functions for statements part done

This commit is contained in:
ProgramSnail 2023-07-28 17:58:45 +03:00
parent 437c9692ec
commit 263b58a17c
7 changed files with 515 additions and 120 deletions

View file

@ -1,42 +1,55 @@
#include "statement_nodes.hpp"
#include "error_handling.hpp"
#include "utils.hpp"
#include <algorithm>
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
// TODO: function overloading, etc. ??
bool FunctionDefinition::is_same_to(
const FunctionDefinition &other_function_definition) const {
if (*name_.get() != *other_function_definition.name_.get()) {
return false;
}
return true;
}
// TODO: function overloading, etc. ??
CombineResult
FunctionDefinition::combine(FunctionDefinition &&other_function_definition) {
// should be same in all definitions of one function
if (*name_.get() != *other_function_definition.name_.get()) {
return CombineResult::DIFFERENT_NAME_ERROR;
}
if (modifier_ != other_function_definition.modifier_) {
return false;
return CombineResult::DIFFERNENT_MODIFIER_ERROR;
}
if (are_annotations_same_to_names_ !=
other_function_definition.are_annotations_same_to_names_) {
return false;
return CombineResult::ARGUMENTS_ERROR;
}
// only one definition should have constraints
if (!constraints_.empty() &&
!other_function_definition.constraints_.empty()) {
return false;
return CombineResult::MORE_THEN_ONE_CONSTRAINTS_ERROR;
}
// only one definition should have expression
if (expression_.has_value() &&
other_function_definition.expression_.has_value()) {
return false;
return CombineResult::MORE_THEN_ONE_DEFINITION_BODY_ERROR;
}
// only one definition should have documentation
if (docs_.get_description().has_value() &&
other_function_definition.docs_.get_description().has_value()) {
return false;
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
if (docs_.get_annotations_info_size() > 0 &&
other_function_definition.docs_.get_annotations_info_size() > 0) {
return false;
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
// TODO: think about required checks
@ -60,7 +73,7 @@ bool FunctionDefinition::combine(
*other_function_definition.arguments_[i]
.get_annotation()
.value())) {
return false;
return CombineResult::ARGUMENTS_ERROR;
}
// check that all argument names are the same
@ -73,14 +86,14 @@ bool FunctionDefinition::combine(
.get_name()
.value()
->get())) {
return false;
return CombineResult::ARGUMENTS_ERROR;
}
// 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;
return CombineResult::ARGUMENTS_ERROR;
}
// argument modifiers should be same
@ -88,21 +101,18 @@ bool FunctionDefinition::combine(
other_function_definition.arguments_[i].get_before_modifier() ||
arguments_[i].get_after_modifier() !=
other_function_definition.arguments_[i].get_after_modifier()) {
return false;
return CombineResult::ARGUMENTS_ERROR;
}
// 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;
return CombineResult::ARGUMENTS_ERROR;
}
// last arguments can only be unnamed arguments (returned values)
if (arguments_[i].get_name().has_value()) {
return false;
return CombineResult::ARGUMENTS_ERROR;
}
} else { // i < other_function_definition.size()
// last arguments shouldn't be annotated (because they are not annotated
@ -110,12 +120,12 @@ bool FunctionDefinition::combine(
if (other_function_definition.arguments_[i]
.get_annotation()
.has_value()) {
return false;
return CombineResult::ARGUMENTS_ERROR;
}
// last arguments can only be unnamed arguments (returned values)
if (other_function_definition.arguments_[i].get_name().has_value()) {
return false;
return CombineResult::ARGUMENTS_ERROR;
}
}
}
@ -126,7 +136,7 @@ bool FunctionDefinition::combine(
other_function_definition.docs_.get_annotations_info_size() > 0) {
if (docs_.get_annotations_info_size() > 0 ||
docs_.get_description().has_value()) {
return false;
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
docs_ = std::move(other_function_definition.docs_);
@ -140,28 +150,50 @@ bool FunctionDefinition::combine(
expression_ = other_function_definition.expression_;
}
// TODO: arguments: check and merge
for (size_t i = 0; i < other_function_definition.arguments_.size(); ++i) {
if (i < arguments_.size()) {
if (other_function_definition.arguments_[i].get_type().has_value()) {
if (arguments_[i].update_type_from(
other_function_definition.arguments_[i])) {
error_handling::handle_internal_error(
"Function arguments are not properly checked before merging "
"during combination",
this);
}
}
} else {
arguments_.push_back(std::move(other_function_definition.arguments_[i]));
}
}
return true;
return CombineResult::OK;
}
bool TypeDefinition::combine(TypeDefinition &&other_type_definition) {
// should be same in all definitions of one type
bool TypeDefinition::is_same_to(
const TypeDefinition &other_type_definition) const {
if (*name_.get() != *other_type_definition.name_.get()) {
return false;
}
return true;
}
CombineResult TypeDefinition::combine(TypeDefinition &&other_type_definition) {
// should be same in all definitions of one type
if (*name_.get() != *other_type_definition.name_.get()) {
return CombineResult::DIFFERENT_NAME_ERROR;
}
if (is_on_heap_ != other_type_definition.is_on_heap_) {
return false;
return CombineResult::DIFFERNENT_MODIFIER_ERROR;
}
// only one definition should have documentation
if (docs_.get_description().has_value() &&
other_type_definition.docs_.get_description().has_value()) {
return false;
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
if (docs_.get_annotations_info_size() > 0 &&
other_type_definition.docs_.get_annotations_info_size() > 0) {
return false;
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
// only one definition should define type and arguments (they should be
@ -169,7 +201,7 @@ bool TypeDefinition::combine(TypeDefinition &&other_type_definition) {
if ((other_type_definition.type_.has_value() ||
!other_type_definition.arguments_.empty()) &&
(type_.has_value() || !arguments_.empty())) {
return false;
return CombineResult::ARGUMENTS_ERROR;
}
// combine docs
@ -178,7 +210,7 @@ bool TypeDefinition::combine(TypeDefinition &&other_type_definition) {
other_type_definition.docs_.get_annotations_info_size() > 0) {
if (docs_.get_annotations_info_size() > 0 ||
docs_.get_description().has_value()) {
return false;
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
docs_ = std::move(other_type_definition.docs_);
@ -192,38 +224,58 @@ bool TypeDefinition::combine(TypeDefinition &&other_type_definition) {
type_ = std::move(other_type_definition.type_);
}
// TODO: can be in incorrect state if error occure here
// combine methods ??
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]));
auto method_iter = methods_by_name_.find(
*other_type_definition.methods_[i].get_name()->get());
if (method_iter == methods_by_name_.end()) {
methods_by_name_[*other_type_definition.methods_[i].get_name()->get()] =
methods_.size();
methods_.push_back(std::move(other_type_definition.methods_[i]));
} else {
auto method_combine_result = methods_[method_iter->second].combine(
std::move(other_type_definition.methods_[i]));
if (method_combine_result != CombineResult::OK) {
return method_combine_result;
}
}
}
// TODO: combine methods ??
return CombineResult::OK;
}
bool TypeclassDefinition::is_same_to(
const TypeclassDefinition &other_typeclass_definition) const {
if (*name_.get() != *other_typeclass_definition.name_.get()) {
return false;
}
return true;
}
bool TypeclassDefinition::combine(
TypeclassDefinition &&other_typeclass_definition) {
CombineResult
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;
return CombineResult::DIFFERENT_NAME_ERROR;
}
// only one definition should have documentation
if (docs_.get_description().has_value() &&
other_typeclass_definition.docs_.get_description().has_value()) {
return false;
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
if (docs_.get_annotations_info_size() > 0 &&
other_typeclass_definition.docs_.get_annotations_info_size() > 0) {
return false;
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
// only one definition should define base typeclasses
if (!base_typeclasses_.empty() &&
!other_typeclass_definition.base_typeclasses_.empty()) {
return false;
return CombineResult::MORE_THEN_ONE_DEFINITION_BODY_ERROR;
}
// combine docs
@ -232,7 +284,7 @@ bool TypeclassDefinition::combine(
other_typeclass_definition.docs_.get_annotations_info_size() > 0) {
if (docs_.get_annotations_info_size() > 0 ||
docs_.get_description().has_value()) {
return false;
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
}
docs_ = std::move(other_typeclass_definition.docs_);
@ -242,15 +294,89 @@ bool TypeclassDefinition::combine(
base_typeclasses_ = std::move(other_typeclass_definition.base_typeclasses_);
}
// TODO: can be in incorrect state if error occure here
// combine methods ??
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]));
auto method_iter = methods_by_name_.find(
*other_typeclass_definition.methods_[i].get_name()->get());
if (method_iter == methods_by_name_.end()) {
methods_by_name_
[*other_typeclass_definition.methods_[i].get_name()->get()] =
methods_.size();
methods_.push_back(std::move(other_typeclass_definition.methods_[i]));
} else {
auto method_combine_result = methods_[method_iter->second].combine(
std::move(other_typeclass_definition.methods_[i]));
if (method_combine_result != CombineResult::OK) {
return method_combine_result;
}
}
}
// TODO: combine methods ??
return CombineResult::OK;
}
return true;
bool Statement::is_same_to(const Statement &other_statement) const {
if (expression_.index() != other_statement.expression_.index()) {
return false;
}
switch (expression_.index()) {
case 0: // Import
return false;
case 1: // TypeDefinition
return std::get<TypeDefinition>(expression_)
.is_same_to(
std::move(std::get<TypeDefinition>(other_statement.expression_)));
case 2: // FunctionDefinition
return std::get<FunctionDefinition>(expression_)
.is_same_to(std::move(
std::get<FunctionDefinition>(other_statement.expression_)));
case 3: // TypeclassDefinition
return std::get<TypeclassDefinition>(expression_)
.is_same_to(std::move(
std::get<TypeclassDefinition>(other_statement.expression_)));
case 4: // EmptyLines
return false;
default:
break;
}
error_handling::handle_general_error("Unreachable");
exit(1);
}
CombineResult Statement::combine(Statement &&other_statement) {
if (expression_.index() != other_statement.expression_.index()) {
return CombineResult::DIFFERENT_STATEMENT_TYPES;
}
switch (expression_.index()) {
case 0: // Import
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
case 1: // TypeDefinition
return std::get<TypeDefinition>(expression_)
.combine(
std::move(std::get<TypeDefinition>(other_statement.expression_)));
case 2: // FunctionDefinition
return std::get<FunctionDefinition>(expression_)
.combine(std::move(
std::get<FunctionDefinition>(other_statement.expression_)));
case 3: // TypeclassDefinition
return std::get<TypeclassDefinition>(expression_)
.combine(std::move(
std::get<TypeclassDefinition>(other_statement.expression_)));
case 4: // EmptyLines
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
default:
break;
}
error_handling::handle_general_error("Unreachable");
exit(1);
}
} // namespace nodes