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

@ -13,8 +13,11 @@ include_directories(include
add_executable(lang src/main.cpp add_executable(lang src/main.cpp
src/name_tree.cpp
src/type_nodes.cpp src/type_nodes.cpp
src/expression_nodes.cpp src/expression_nodes.cpp
src/statement_nodes.cpp
src/basic_builders.cpp src/basic_builders.cpp
src/type_builders.cpp src/type_builders.cpp

View file

@ -22,9 +22,11 @@ public:
std::pair<size_t, size_t> end_position) std::pair<size_t, size_t> end_position)
: start_position_(start_position), end_position_(end_position) {} : start_position_(start_position), end_position_(end_position) {}
std::pair<size_t, size_t> get_start_position() { return start_position_; } std::pair<size_t, size_t> get_start_position() const {
return start_position_;
}
std::pair<size_t, size_t> get_end_position() { return end_position_; } std::pair<size_t, size_t> get_end_position() const { return end_position_; }
protected: protected:
std::pair<size_t, size_t> start_position_; std::pair<size_t, size_t> start_position_;

View file

@ -17,14 +17,13 @@ inline void print_position(std::ostream &out,
} }
inline void inline void
handle_internal_error(const std::string &message, const std::string &place, handle_internal_error(const std::string &message,
std::optional<nodes::Node> node = std::nullopt) { std::optional<const nodes::Node *> node = std::nullopt) {
std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at " std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message;
<< place;
if (node.has_value()) { if (node.has_value()) {
std::cerr << ", at "; std::cerr << " at ";
print_position(std::cerr, node.value().get_start_position(), print_position(std::cerr, node.value()->get_start_position(),
node.value().get_end_position()); node.value()->get_end_position());
} }
std::cerr << ".\n"; std::cerr << ".\n";
exit(1); exit(1);

View file

@ -1,7 +1,11 @@
#pragma once #pragma once
#include "statement_nodes.hpp"
#include "tree_sitter_wrapper.hpp" #include "tree_sitter_wrapper.hpp"
#include <cstddef>
#include <optional>
#include <unordered_map>
#include <vector> #include <vector>
namespace names { namespace names {
@ -9,72 +13,85 @@ namespace names {
// IN PROGRESS // IN PROGRESS
class NameTree { class NameTree {
public: public:
struct Node {}; NameTree() {
nodes_.emplace_back(); // root
}
NameTree() {} bool insert(const std::string &path, nodes::Statement &&statement);
bool insert_path(const std::vector<std::string> &path, Node node) {} std::optional<nodes::Statement *> find(const std::string &path);
std::optional<const nodes::Statement *> find(const std::string &path) const;
private: private:
}; struct Node {
class NameStorage;
class NameProxy {
friend NameStorage;
public: public:
NameProxy(NameStorage *name_storage, size_t id) std::optional<nodes::Statement *> get_statement() {
: name_storage_(name_storage), id_(id) {} if (statement_.has_value()) {
return &statement_.value();
std::string *get(); }
return std::nullopt;
const std::string *get() const;
bool operator==(const NameProxy &other) const {
return name_storage_ == other.name_storage_ && id_ == other.id_;
} }
bool operator<(const NameProxy &other) const { std::optional<const nodes::Statement *> get_statement() const {
return name_storage_ < other.name_storage_ || if (statement_.has_value()) {
(name_storage_ == other.name_storage_ && id_ < other.id_); return &statement_.value();
}
return std::nullopt;
}
bool set_statement(nodes::Statement &&statement) {
if (statement_.has_value()) {
return false;
}
statement_ = std::move(statement);
return true;
}
std::optional<size_t> find(size_t name_id) const {
auto name_iter = children_.find(name_id);
if (name_iter == children_.end()) {
return std::nullopt;
}
return name_iter->second;
}
bool insert(size_t name_id, size_t node_id) {
if (children_.count(name_id) != 0) {
return false;
}
children_[name_id] = node_id;
return true;
} }
private: private:
NameStorage *name_storage_; std::unordered_map<size_t, size_t> children_;
size_t id_; std::optional<nodes::Statement> statement_;
}; };
class NameStorage { size_t get_root() const { return 0; }
friend NameProxy;
public: size_t add_node(size_t current_node, const std::vector<size_t> &name_ids,
NameProxy add_expression(const std::string &name) { size_t current_name = 0);
storage_.push_back(name);
return NameProxy(this, storage_.size() - 1);
}
NameProxy add_expression(std::string &&name) { std::optional<size_t> find_node(size_t current_node,
storage_.push_back(std::move(name)); const std::vector<size_t> &name_ids,
return NameProxy(this, storage_.size() - 1); size_t current_name = 0) const;
}
std::vector<size_t> slice_path_to_name_ids(const std::string &path);
std::optional<std::vector<size_t>>
slice_path_to_existing_name_ids(const std::string &path) const;
size_t add_name_id(const std::string &name);
std::optional<size_t> find_name_id(const std::string &name) const;
private: private:
std::string *get_expression(size_t id) { return &storage_.at(id); } std::unordered_map<std::string, size_t> name_to_id_;
std::vector<Node> nodes_;
const std::string *get_expression(size_t id) const {
return &storage_.at(id);
}
private:
std::vector<std::string> storage_;
}; };
std::vector<std::string> string_to_path(const std::string &str) {
std::vector<std::string> path;
for (;;) {
}
return path;
} // IN PROGRESS
} // namespace names } // namespace names

View file

@ -11,6 +11,19 @@
namespace nodes { namespace nodes {
enum class CombineResult {
DIFFERENT_NAME_ERROR,
DIFFERNENT_MODIFIER_ERROR,
MORE_THEN_ONE_DOCS_ERROR,
MORE_THEN_ONE_CONSTRAINTS_ERROR,
MORE_THEN_ONE_DEFINITION_BODY_ERROR,
ARGUMENTS_ERROR,
DIFFERENT_STATEMENT_TYPES,
STATEMENTS_CANT_BE_COMBINED_ERROR,
GENERIC_ERROR,
OK,
};
// IN PROGRESS: add another constructors ?? // IN PROGRESS: add another constructors ??
class Import : public Node { class Import : public Node {
public: public:
@ -88,8 +101,42 @@ public:
// //
// add type with same annotation and same before_modifier
bool update_type_from(const Argument &other_argument) {
if (type_.has_value() || !other_argument.type_.has_value()) {
return false;
}
if (annotation_.has_value() &&
(!other_argument.annotation_.has_value() ||
annotation_.value() != other_argument.annotation_.value())) {
return false;
}
if (before_modifier_ != other_argument.before_modifier_) {
return false;
}
if (after_modifier_ != other_argument.after_modifier_) {
return false;
}
annotation_ = other_argument.annotation_;
type_ = other_argument.type_;
before_modifier_ = other_argument.before_modifier_;
after_modifier_ = other_argument.after_modifier_;
return true;
}
// check, that argument modifiers are none or same to different from type
// modifiers
bool add_type(const std::optional<std::string> &annotation, TypeProxy type, bool add_type(const std::optional<std::string> &annotation, TypeProxy type,
nodes::Modifier before_modifier = Modifier::NONE) { nodes::Modifier before_modifier = Modifier::NONE) {
if (type_.has_value()) {
return false;
}
if (annotation_.has_value() && if (annotation_.has_value() &&
(!annotation.has_value() || (!annotation.has_value() ||
annotation_.value() != annotation.value())) { annotation_.value() != annotation.value())) {
@ -258,7 +305,9 @@ public:
// //
bool combine(FunctionDefinition &&other_function_definition); bool is_same_to(const FunctionDefinition &other_function_definition) const;
CombineResult combine(FunctionDefinition &&other_function_definition);
private: private:
SymbolDocs docs_; SymbolDocs docs_;
@ -278,7 +327,11 @@ public:
std::vector<FunctionDefinition> &&methods) std::vector<FunctionDefinition> &&methods)
: Node(node), docs_(std::move(docs)), is_on_heap_(is_on_heap), : Node(node), docs_(std::move(docs)), is_on_heap_(is_on_heap),
name_(name), arguments_(std::move(arguments)), type_(std::move(type)), name_(name), arguments_(std::move(arguments)), type_(std::move(type)),
methods_(std::move(methods)) {} methods_(std::move(methods)) {
for (size_t i = 0; i < methods.size(); ++i) {
methods_by_name_[*methods_[i].get_name()->get()] = i;
}
}
// //
@ -332,7 +385,9 @@ public:
// //
bool combine(TypeDefinition &&other_type_definition); bool is_same_to(const TypeDefinition &other_type_definition) const;
CombineResult combine(TypeDefinition &&other_type_definition);
private: private:
SymbolDocs docs_; SymbolDocs docs_;
@ -340,6 +395,8 @@ private:
Identifier name_; Identifier name_;
std::vector<Identifier> arguments_; std::vector<Identifier> arguments_;
std::optional<VariantType> type_; // TupleType is VariantType with one variant std::optional<VariantType> type_; // TupleType is VariantType with one variant
std::unordered_map<std::string, size_t>
methods_by_name_; // methods can't be overloaded ??
std::vector<FunctionDefinition> methods_; std::vector<FunctionDefinition> methods_;
}; };
@ -350,7 +407,11 @@ public:
std::vector<FunctionDefinition> &&methods) std::vector<FunctionDefinition> &&methods)
: Node(node), docs_(std::move(docs)), name_(name), : Node(node), docs_(std::move(docs)), name_(name),
base_typeclasses_(std::move(base_typeclasses)), base_typeclasses_(std::move(base_typeclasses)),
methods_(std::move(methods)) {} methods_(std::move(methods)) {
for (size_t i = 0; i < methods.size(); ++i) {
methods_by_name_[*methods_[i].get_name()->get()] = i;
}
}
// //
@ -388,12 +449,16 @@ public:
// //
bool combine(TypeclassDefinition &&other_typeclass_definition); bool is_same_to(const TypeclassDefinition &other_typeclass_definition) const;
CombineResult combine(TypeclassDefinition &&other_typeclass_definition);
private: private:
SymbolDocs docs_; SymbolDocs docs_;
Identifier name_; Identifier name_;
std::vector<Identifier> base_typeclasses_; std::vector<Identifier> base_typeclasses_;
std::unordered_map<std::string, size_t>
methods_by_name_; // methods can't be overloaded ??
std::vector<FunctionDefinition> methods_; std::vector<FunctionDefinition> methods_;
}; };
@ -420,6 +485,10 @@ public:
auto get_any() const { return &expression_; } auto get_any() const { return &expression_; }
bool is_same_to(const Statement &other_statement) const;
CombineResult combine(Statement &&other_statement);
private: private:
std::variant<Import, TypeDefinition, FunctionDefinition, TypeclassDefinition, std::variant<Import, TypeDefinition, FunctionDefinition, TypeclassDefinition,
EmptyLines> EmptyLines>

179
src/name_tree.cpp Normal file
View file

@ -0,0 +1,179 @@
#include "name_tree.hpp"
namespace names {
// --- public
bool NameTree::insert(const std::string &path, nodes::Statement &&statement) {
auto name_ids = slice_path_to_name_ids(path);
size_t node_id = add_node(get_root(), name_ids);
if (nodes_[node_id].get_statement().has_value()) {
return false;
}
nodes_[node_id].set_statement(std::move(statement));
return true;
}
std::optional<nodes::Statement *> NameTree::find(const std::string &path) {
auto name_ids = slice_path_to_existing_name_ids(path);
if (!name_ids.has_value()) {
return std::nullopt;
}
auto node_id = find_node(get_root(), name_ids.value());
if (node_id.has_value()) {
return nodes_[node_id.value()].get_statement();
}
return std::nullopt;
}
std::optional<const nodes::Statement *>
NameTree::find(const std::string &path) const {
auto name_ids = slice_path_to_existing_name_ids(path);
if (!name_ids.has_value()) {
return std::nullopt;
}
auto node_id = find_node(get_root(), name_ids.value());
if (node_id.has_value()) {
return nodes_[node_id.value()].get_statement();
}
return std::nullopt;
}
// --- private
size_t NameTree::add_node(size_t current_node,
const std::vector<size_t> &name_ids,
size_t current_name) {
if (current_name >= name_ids.size()) {
return current_node;
}
auto next_node = nodes_[current_node].find(name_ids[current_name]);
if (!next_node.has_value()) {
next_node = nodes_.size();
nodes_[current_node].insert(name_ids[current_name], next_node.value());
nodes_.emplace_back();
}
return add_node(next_node.value(), name_ids, current_name + 1);
}
std::optional<size_t> NameTree::find_node(size_t current_node,
const std::vector<size_t> &name_ids,
size_t current_name) const {
if (current_name >= name_ids.size()) {
return current_node;
}
auto next_node = nodes_[current_node].find(name_ids[current_name]);
if (!next_node.has_value()) {
return std::nullopt;
}
return find_node(next_node.value(), name_ids, current_name + 1);
}
std::vector<size_t> NameTree::slice_path_to_name_ids(const std::string &path) {
// check that path is / is not points only operator
bool points_only = true;
for (size_t i = 0; i < path.size(); ++i) {
if (path[i] != '.') {
points_only = true;
break;
}
}
if (points_only) {
return {add_name_id(path)};
}
std::vector<size_t> name_ids;
size_t last_name_start = 0;
for (size_t i = 0; i < path.size() + 1; ++i) {
if (path[i] == '.' || i == path.size()) { // name separator
name_ids.push_back(
add_name_id(path.substr(last_name_start, i - last_name_start)));
last_name_start = i + 1;
}
}
return name_ids;
}
std::optional<std::vector<size_t>>
NameTree::slice_path_to_existing_name_ids(const std::string &path) const {
// check that path is / is not points only operator
bool points_only = true;
for (size_t i = 0; i < path.size(); ++i) {
if (path[i] != '.') {
points_only = true;
break;
}
}
if (points_only) {
auto maybe_id = find_name_id(path);
if (maybe_id.has_value()) {
return std::vector<size_t>{maybe_id.value()};
} else {
return std::nullopt;
}
}
std::vector<size_t> name_ids;
size_t last_name_start = 0;
for (size_t i = 0; i < path.size() + 1; ++i) {
if (path[i] == '.' || i == path.size()) { // name separator
auto maybe_id =
find_name_id(path.substr(last_name_start, i - last_name_start));
if (!maybe_id.has_value()) {
return std::nullopt;
}
name_ids.push_back(maybe_id.value());
last_name_start = i + 1;
}
}
return name_ids;
}
size_t NameTree::add_name_id(const std::string &name) {
auto name_iter = name_to_id_.find(name);
if (name_iter == name_to_id_.end()) {
size_t name_id = name_to_id_.size();
return name_to_id_[name] = name_id;
}
return name_iter->second;
}
std::optional<size_t> NameTree::find_name_id(const std::string &name) const {
auto name_iter = name_to_id_.find(name);
if (name_iter == name_to_id_.end()) {
return std::nullopt;
}
return name_iter->second;
}
} // namespace names

View file

@ -1,42 +1,55 @@
#include "statement_nodes.hpp" #include "statement_nodes.hpp"
#include "error_handling.hpp"
#include "utils.hpp"
#include <algorithm>
namespace nodes { namespace nodes {
// TODO: return error type instead of bool ?? // TODO: function overloading, etc. ??
bool FunctionDefinition::combine( bool FunctionDefinition::is_same_to(
FunctionDefinition &&other_function_definition) { const FunctionDefinition &other_function_definition) const {
// should be same in all definitions of one function
if (*name_.get() != *other_function_definition.name_.get()) { if (*name_.get() != *other_function_definition.name_.get()) {
return false; 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_) { if (modifier_ != other_function_definition.modifier_) {
return false; return CombineResult::DIFFERNENT_MODIFIER_ERROR;
} }
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 false; return CombineResult::ARGUMENTS_ERROR;
} }
// only one definition should have constraints // only one definition should have constraints
if (!constraints_.empty() && if (!constraints_.empty() &&
!other_function_definition.constraints_.empty()) { !other_function_definition.constraints_.empty()) {
return false; return CombineResult::MORE_THEN_ONE_CONSTRAINTS_ERROR;
} }
// only one definition should have expression // only one definition should have expression
if (expression_.has_value() && if (expression_.has_value() &&
other_function_definition.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 // only one definition should have documentation
if (docs_.get_description().has_value() && if (docs_.get_description().has_value() &&
other_function_definition.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 && if (docs_.get_annotations_info_size() > 0 &&
other_function_definition.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 // TODO: think about required checks
@ -60,7 +73,7 @@ bool FunctionDefinition::combine(
*other_function_definition.arguments_[i] *other_function_definition.arguments_[i]
.get_annotation() .get_annotation()
.value())) { .value())) {
return false; return CombineResult::ARGUMENTS_ERROR;
} }
// check that all argument names are the same // check that all argument names are the same
@ -73,14 +86,14 @@ bool FunctionDefinition::combine(
.get_name() .get_name()
.value() .value()
->get())) { ->get())) {
return false; return CombineResult::ARGUMENTS_ERROR;
} }
// check that types are are in zero or one set of arguments (TODO: can be // check that types are are in zero or one set of arguments (TODO: can be
// same and in two sets ??) // 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()) {
return false; return CombineResult::ARGUMENTS_ERROR;
} }
// argument modifiers should be same // argument modifiers should be same
@ -88,21 +101,18 @@ bool FunctionDefinition::combine(
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() !=
other_function_definition.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()) { } else if (i < arguments_.size()) {
// last arguments shouldn't be annotated (because they are not annotated // last arguments shouldn't be annotated (because they are not annotated
// in other function definition statement) // in other function definition statement)
if (arguments_[i].get_annotation().has_value()) { if (arguments_[i].get_annotation().has_value()) {
return false; return CombineResult::ARGUMENTS_ERROR;
} }
// last arguments can only be unnamed arguments (returned values) // last arguments can only be unnamed arguments (returned values)
if (arguments_[i].get_name().has_value()) { if (arguments_[i].get_name().has_value()) {
return false; 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 // last arguments shouldn't be annotated (because they are not annotated
@ -110,12 +120,12 @@ bool FunctionDefinition::combine(
if (other_function_definition.arguments_[i] if (other_function_definition.arguments_[i]
.get_annotation() .get_annotation()
.has_value()) { .has_value()) {
return false; return CombineResult::ARGUMENTS_ERROR;
} }
// last arguments can only be unnamed arguments (returned values) // last arguments can only be unnamed arguments (returned values)
if (other_function_definition.arguments_[i].get_name().has_value()) { 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) { other_function_definition.docs_.get_annotations_info_size() > 0) {
if (docs_.get_annotations_info_size() > 0 || if (docs_.get_annotations_info_size() > 0 ||
docs_.get_description().has_value()) { docs_.get_description().has_value()) {
return false; return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
} }
docs_ = std::move(other_function_definition.docs_); docs_ = std::move(other_function_definition.docs_);
@ -140,28 +150,50 @@ bool FunctionDefinition::combine(
expression_ = other_function_definition.expression_; 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()) {
return true; 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]));
}
} }
bool TypeDefinition::combine(TypeDefinition &&other_type_definition) { return CombineResult::OK;
// 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()) { if (*name_.get() != *other_type_definition.name_.get()) {
return false; 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_) { if (is_on_heap_ != other_type_definition.is_on_heap_) {
return false; return CombineResult::DIFFERNENT_MODIFIER_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()) {
return false; return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
} }
if (docs_.get_annotations_info_size() > 0 && if (docs_.get_annotations_info_size() > 0 &&
other_type_definition.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 // 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() || if ((other_type_definition.type_.has_value() ||
!other_type_definition.arguments_.empty()) && !other_type_definition.arguments_.empty()) &&
(type_.has_value() || !arguments_.empty())) { (type_.has_value() || !arguments_.empty())) {
return false; return CombineResult::ARGUMENTS_ERROR;
} }
// combine docs // combine docs
@ -178,7 +210,7 @@ bool TypeDefinition::combine(TypeDefinition &&other_type_definition) {
other_type_definition.docs_.get_annotations_info_size() > 0) { other_type_definition.docs_.get_annotations_info_size() > 0) {
if (docs_.get_annotations_info_size() > 0 || if (docs_.get_annotations_info_size() > 0 ||
docs_.get_description().has_value()) { docs_.get_description().has_value()) {
return false; return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
} }
docs_ = std::move(other_type_definition.docs_); 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_); 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()); methods_.reserve(methods_.size() + other_type_definition.methods_.size());
for (size_t i = 0; i < other_type_definition.methods_.size(); ++i) { for (size_t i = 0; i < other_type_definition.methods_.size(); ++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])); 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; return true;
} }
bool TypeclassDefinition::combine( CombineResult
TypeclassDefinition &&other_typeclass_definition) { TypeclassDefinition::combine(TypeclassDefinition &&other_typeclass_definition) {
// should be same in all definitions of one typeclass // should be same in all definitions of one typeclass
if (*name_.get() != *other_typeclass_definition.name_.get()) { if (*name_.get() != *other_typeclass_definition.name_.get()) {
return false; return CombineResult::DIFFERENT_NAME_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_typeclass_definition.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 && if (docs_.get_annotations_info_size() > 0 &&
other_typeclass_definition.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 // only one definition should define base typeclasses
if (!base_typeclasses_.empty() && if (!base_typeclasses_.empty() &&
!other_typeclass_definition.base_typeclasses_.empty()) { !other_typeclass_definition.base_typeclasses_.empty()) {
return false; return CombineResult::MORE_THEN_ONE_DEFINITION_BODY_ERROR;
} }
// combine docs // combine docs
@ -232,7 +284,7 @@ bool TypeclassDefinition::combine(
other_typeclass_definition.docs_.get_annotations_info_size() > 0) { other_typeclass_definition.docs_.get_annotations_info_size() > 0) {
if (docs_.get_annotations_info_size() > 0 || if (docs_.get_annotations_info_size() > 0 ||
docs_.get_description().has_value()) { docs_.get_description().has_value()) {
return false; return CombineResult::MORE_THEN_ONE_DOCS_ERROR;
} }
docs_ = std::move(other_typeclass_definition.docs_); docs_ = std::move(other_typeclass_definition.docs_);
@ -242,15 +294,89 @@ bool TypeclassDefinition::combine(
base_typeclasses_ = std::move(other_typeclass_definition.base_typeclasses_); 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() + methods_.reserve(methods_.size() +
other_typeclass_definition.methods_.size()); other_typeclass_definition.methods_.size());
for (size_t i = 0; i < other_typeclass_definition.methods_.size(); ++i) { for (size_t i = 0; i < other_typeclass_definition.methods_.size(); ++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])); 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 } // namespace nodes