mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-06 06:58:46 +00:00
combine functions fixes
This commit is contained in:
parent
5e70f0015f
commit
4714a05467
5 changed files with 117 additions and 44 deletions
|
|
@ -115,6 +115,16 @@ public:
|
||||||
value_ += name;
|
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:
|
private:
|
||||||
IdentifierType type_;
|
IdentifierType type_;
|
||||||
std::string value_;
|
std::string value_;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ enum class CombineResult {
|
||||||
MORE_THEN_ONE_DOCS_ERROR,
|
MORE_THEN_ONE_DOCS_ERROR,
|
||||||
MORE_THEN_ONE_CONSTRAINTS_ERROR,
|
MORE_THEN_ONE_CONSTRAINTS_ERROR,
|
||||||
MORE_THEN_ONE_DEFINITION_BODY_ERROR,
|
MORE_THEN_ONE_DEFINITION_BODY_ERROR,
|
||||||
|
TYPECLASSES_ERROR,
|
||||||
ARGUMENTS_ERROR,
|
ARGUMENTS_ERROR,
|
||||||
DIFFERENT_STATEMENT_TYPES,
|
DIFFERENT_STATEMENT_TYPES,
|
||||||
STATEMENTS_CANT_BE_COMBINED_ERROR,
|
STATEMENTS_CANT_BE_COMBINED_ERROR,
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,14 @@ public:
|
||||||
: Node(node), name_(identifier), parameters_(std::move(parameters)),
|
: Node(node), name_(identifier), parameters_(std::move(parameters)),
|
||||||
is_on_heap_(is_on_heap), modifier_(modifier) {}
|
is_on_heap_(is_on_heap), modifier_(modifier) {}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
Identifier *get_name() { return &name_; }
|
Identifier *get_name() { return &name_; }
|
||||||
|
|
||||||
const Identifier *get_name() const { return &name_; }
|
const Identifier *get_name() const { return &name_; }
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
size_t get_parametrs_size() const { return parameters_.size(); }
|
size_t get_parametrs_size() const { return parameters_.size(); }
|
||||||
|
|
||||||
Type *get_parameter(size_t id) { return parameters_.at(id).get(); }
|
Type *get_parameter(size_t id) { return parameters_.at(id).get(); }
|
||||||
|
|
@ -68,10 +72,34 @@ public:
|
||||||
return parameters_.at(id).get();
|
return parameters_.at(id).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
bool is_on_heap() const { return is_on_heap_; }
|
bool is_on_heap() const { return is_on_heap_; }
|
||||||
|
|
||||||
Modifier get_modifier() const { return modifier_; }
|
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:
|
private:
|
||||||
Identifier name_;
|
Identifier name_;
|
||||||
std::vector<TypeProxy> parameters_;
|
std::vector<TypeProxy> parameters_;
|
||||||
|
|
|
||||||
|
|
@ -166,8 +166,8 @@ parser::ParseTree::Node collect_symbol_doc_nodes(
|
||||||
return current_node;
|
return current_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// definition_info? annotation_info* '^'? simple_type (argument_type* '='
|
// definition_info? annotation_info* '^'? (simple_type | typeclass)
|
||||||
// variant_type)? ('{' function_definition* '}' | ';')
|
// (argument_type* '=' variant_type)? ';'
|
||||||
nodes::TypeDefinition build_type_definition(parser::ParseTree::Node parser_node,
|
nodes::TypeDefinition build_type_definition(parser::ParseTree::Node parser_node,
|
||||||
nodes::TypeStorage &type_storage) {
|
nodes::TypeStorage &type_storage) {
|
||||||
bool is_on_heap = parser_node.nth_child(0).get_value() == "^";
|
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));
|
std::move(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
// definition_info? annotation_info* (constraint ';')* _var_let_? (simple_name
|
// definition_info? annotation_info* (constraint ';')* '.'? (simple_name
|
||||||
// | '(' operator ')') (annotation? _reference_? argument_name '?'?)* (:
|
// | '(' operator ')') (annotation? _reference_? argument_name '?'?)* (:
|
||||||
// (annotation? _reference_ type)+)?
|
// (annotation? _reference_ type)+)?
|
||||||
// ('=' (block | expression ';') | ';')
|
// ('=' (block | expression ';') | ';')
|
||||||
|
|
@ -410,6 +410,13 @@ nodes::FunctionDefinition build_function_definition(
|
||||||
"Less types then arguments in function definition", parser_node);
|
"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
|
// automatic annotations
|
||||||
bool are_annotations_same_to_names =
|
bool are_annotations_same_to_names =
|
||||||
(!at_least_one_argument_annotation_found && current_type_id == 0);
|
(!at_least_one_argument_annotation_found && current_type_id == 0);
|
||||||
|
|
|
||||||
|
|
@ -6,29 +6,34 @@
|
||||||
|
|
||||||
namespace nodes {
|
namespace nodes {
|
||||||
|
|
||||||
// TODO: function overloading, etc. ??
|
|
||||||
bool FunctionDefinition::is_same_to(
|
bool FunctionDefinition::is_same_to(
|
||||||
const FunctionDefinition &other_function_definition) const {
|
const FunctionDefinition &other_function_definition) const {
|
||||||
if (*name_.get() != *other_function_definition.name_.get()) {
|
if (name_ != other_function_definition.name_) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
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
|
CombineResult
|
||||||
FunctionDefinition::combine(FunctionDefinition &&other_function_definition) {
|
FunctionDefinition::combine(FunctionDefinition &&other_function_definition) {
|
||||||
// should be same in all definitions of one function
|
// names should be the same
|
||||||
if (*name_.get() != *other_function_definition.name_.get()) {
|
if (name_ != other_function_definition.name_) {
|
||||||
return CombineResult::DIFFERENT_NAME_ERROR;
|
return CombineResult::DIFFERENT_NAME_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// modifiers should be the same
|
||||||
if (return_modifier_ != other_function_definition.return_modifier_) {
|
if (return_modifier_ != other_function_definition.return_modifier_) {
|
||||||
return CombineResult::DIFFERNENT_MODIFIER_ERROR;
|
return CombineResult::DIFFERNENT_MODIFIER_ERROR;
|
||||||
}
|
}
|
||||||
if (is_method_ != other_function_definition.is_method_) {
|
if (is_method_ != other_function_definition.is_method_) {
|
||||||
return CombineResult::DIFFERNENT_MODIFIER_ERROR; // other error type ??
|
return CombineResult::DIFFERNENT_MODIFIER_ERROR; // other error type ??
|
||||||
}
|
}
|
||||||
|
|
||||||
if (are_annotations_same_to_names_ !=
|
if (are_annotations_same_to_names_ !=
|
||||||
other_function_definition.are_annotations_same_to_names_) {
|
other_function_definition.are_annotations_same_to_names_) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
|
|
@ -40,7 +45,7 @@ FunctionDefinition::combine(FunctionDefinition &&other_function_definition) {
|
||||||
return CombineResult::MORE_THEN_ONE_CONSTRAINTS_ERROR;
|
return CombineResult::MORE_THEN_ONE_CONSTRAINTS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only one definition should have expression
|
// only one definition should have expression (body)
|
||||||
if (expression_.has_value() &&
|
if (expression_.has_value() &&
|
||||||
other_function_definition.expression_.has_value()) {
|
other_function_definition.expression_.has_value()) {
|
||||||
return CombineResult::MORE_THEN_ONE_DEFINITION_BODY_ERROR;
|
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;
|
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: think about required checks
|
// check, that function definitions have same named arguments
|
||||||
// check, that function definitions have same named arguments count
|
|
||||||
for (size_t i = 0; i < std::max(arguments_.size(),
|
for (size_t i = 0; i < std::max(arguments_.size(),
|
||||||
other_function_definition.arguments_.size());
|
other_function_definition.arguments_.size());
|
||||||
++i) {
|
++i) {
|
||||||
if (i < arguments_.size() &&
|
if (i < arguments_.size() &&
|
||||||
i < other_function_definition.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() &&
|
if ((!arguments_[i].get_annotation().has_value() &&
|
||||||
!other_function_definition.arguments_[i]
|
!other_function_definition.arguments_[i]
|
||||||
.get_annotation()
|
.get_annotation()
|
||||||
|
|
@ -80,27 +84,25 @@ FunctionDefinition::combine(FunctionDefinition &&other_function_definition) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
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() &&
|
if ((!arguments_[i].get_name().has_value() &&
|
||||||
!other_function_definition.arguments_[i].get_name().has_value()) ||
|
!other_function_definition.arguments_[i].get_name().has_value()) ||
|
||||||
(arguments_[i].get_name().has_value() &&
|
(arguments_[i].get_name().has_value() &&
|
||||||
other_function_definition.arguments_[i].get_name().has_value() &&
|
other_function_definition.arguments_[i].get_name().has_value() &&
|
||||||
*arguments_[i].get_name().value()->get() !=
|
arguments_[i].get_name().value() !=
|
||||||
*other_function_definition.arguments_[i]
|
other_function_definition.arguments_[i].get_name().value())) {
|
||||||
.get_name()
|
|
||||||
.value()
|
|
||||||
->get())) {
|
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that types are are in zero or one set of arguments (TODO: can be
|
// types should be the same (if present in both definitions)
|
||||||
// same and in two sets ??)
|
|
||||||
if (arguments_[i].get_type().has_value() &&
|
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;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// argument modifiers should be same
|
// argument modifiers should be the same
|
||||||
if (arguments_[i].get_before_modifier() !=
|
if (arguments_[i].get_before_modifier() !=
|
||||||
other_function_definition.arguments_[i].get_before_modifier() ||
|
other_function_definition.arguments_[i].get_before_modifier() ||
|
||||||
arguments_[i].get_after_modifier() !=
|
arguments_[i].get_after_modifier() !=
|
||||||
|
|
@ -108,26 +110,24 @@ FunctionDefinition::combine(FunctionDefinition &&other_function_definition) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
} else if (i < arguments_.size()) {
|
} else if (i < arguments_.size()) {
|
||||||
// last arguments shouldn't be annotated (because they are not annotated
|
// annotations should be the same
|
||||||
// in other function definition statement)
|
|
||||||
if (arguments_[i].get_annotation().has_value()) {
|
if (arguments_[i].get_annotation().has_value()) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
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()) {
|
if (arguments_[i].get_name().has_value()) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
} else { // i < other_function_definition.size()
|
} else { // i < other_function_definition.size()
|
||||||
// last arguments shouldn't be annotated (because they are not annotated
|
// annotations should be the same
|
||||||
// in other function definition statement)
|
|
||||||
if (other_function_definition.arguments_[i]
|
if (other_function_definition.arguments_[i]
|
||||||
.get_annotation()
|
.get_annotation()
|
||||||
.has_value()) {
|
.has_value()) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
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()) {
|
if (other_function_definition.arguments_[i].get_name().has_value()) {
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
return CombineResult::ARGUMENTS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
@ -175,21 +175,47 @@ FunctionDefinition::combine(FunctionDefinition &&other_function_definition) {
|
||||||
|
|
||||||
bool TypeDefinition::is_same_to(
|
bool TypeDefinition::is_same_to(
|
||||||
const TypeDefinition &other_type_definition) const {
|
const TypeDefinition &other_type_definition) const {
|
||||||
if (*name_.get() != *other_type_definition.name_.get()) {
|
if (name_ != other_type_definition.name_) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
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) {
|
CombineResult TypeDefinition::combine(TypeDefinition &&other_type_definition) {
|
||||||
// should be same in all definitions of one type
|
// name should be same
|
||||||
if (*name_.get() != *other_type_definition.name_.get()) {
|
if (name_ != other_type_definition.name_) {
|
||||||
return CombineResult::DIFFERENT_NAME_ERROR;
|
return CombineResult::DIFFERENT_NAME_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// modifier should be the same
|
||||||
if (is_on_heap_ != other_type_definition.is_on_heap_) {
|
if (is_on_heap_ != other_type_definition.is_on_heap_) {
|
||||||
return CombineResult::DIFFERNENT_MODIFIER_ERROR;
|
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
|
// only one definition should have documentation
|
||||||
if (docs_.get_description().has_value() &&
|
if (docs_.get_description().has_value() &&
|
||||||
other_type_definition.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;
|
return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only one definition should define type and arguments (they should be
|
// only one type should define type / body
|
||||||
// defined in one place)
|
if (type_.has_value() && other_type_definition.type_.has_value()) {
|
||||||
if ((other_type_definition.type_.has_value() ||
|
return CombineResult::MORE_THEN_ONE_DEFINITION_BODY_ERROR;
|
||||||
!other_type_definition.arguments_.empty()) &&
|
|
||||||
(type_.has_value() || !arguments_.empty())) {
|
|
||||||
return CombineResult::ARGUMENTS_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// combine docs
|
// combine docs
|
||||||
|
|
@ -220,10 +243,6 @@ CombineResult TypeDefinition::combine(TypeDefinition &&other_type_definition) {
|
||||||
docs_ = std::move(other_type_definition.docs_);
|
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()) {
|
if (other_type_definition.type_.has_value()) {
|
||||||
type_ = std::move(other_type_definition.type_);
|
type_ = std::move(other_type_definition.type_);
|
||||||
}
|
}
|
||||||
|
|
@ -247,9 +266,13 @@ bool Statement::is_same_to(const Statement &other_statement) const {
|
||||||
return std::get<FunctionDefinition>(expression_)
|
return std::get<FunctionDefinition>(expression_)
|
||||||
.is_same_to(std::move(
|
.is_same_to(std::move(
|
||||||
std::get<FunctionDefinition>(other_statement.expression_)));
|
std::get<FunctionDefinition>(other_statement.expression_)));
|
||||||
case 3: // EmptyLines
|
case 3: // Extra
|
||||||
|
return false;
|
||||||
|
case 4: // EmptyLines
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
|
error_handling::handle_general_error(
|
||||||
|
"Unexpected statement type in is_same_to");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,9 +296,13 @@ CombineResult Statement::combine(Statement &&other_statement) {
|
||||||
return std::get<FunctionDefinition>(expression_)
|
return std::get<FunctionDefinition>(expression_)
|
||||||
.combine(std::move(
|
.combine(std::move(
|
||||||
std::get<FunctionDefinition>(other_statement.expression_)));
|
std::get<FunctionDefinition>(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;
|
return CombineResult::STATEMENTS_CANT_BE_COMBINED_ERROR;
|
||||||
default:
|
default:
|
||||||
|
error_handling::handle_general_error(
|
||||||
|
"Unexpected statement type in combine");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue