diff --git a/include/nodes/basic_nodes.hpp b/include/nodes/basic_nodes.hpp index 8e65fef..107de2d 100644 --- a/include/nodes/basic_nodes.hpp +++ b/include/nodes/basic_nodes.hpp @@ -231,6 +231,8 @@ public: // ANNOTATION, used as std::string OPERATOR, PLACEHOLDER, + // + GENERIC_TYPE, }; Identifier(Node node, IdentifierType type, std::string &&value) diff --git a/include/nodes/type_nodes.hpp b/include/nodes/type_nodes.hpp index c661c87..e3cb225 100644 --- a/include/nodes/type_nodes.hpp +++ b/include/nodes/type_nodes.hpp @@ -7,9 +7,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -35,19 +35,6 @@ private: size_t id_; }; -// // not needed ?? -// class TypeNode : public Node { -// public: -// TypeNode(Node node, TypeProxy type) : Node(node), type_(type) {} -// -// Type *get() { return type_.get(); } -// -// const Type *get() const { return type_.get(); } -// -// private: -// TypeProxy type_; -// }; - class Type { public: Type(Identifier &&identifier, Modifier modifier = nodes::Modifier::CONST, @@ -133,6 +120,10 @@ public: // + bool is_generic() { return name_.get_type() == Identifier::GENERIC_TYPE; } + + // + bool operator==(const Type &other) const { if (name_ != other.name_ || modifier_ != other.modifier_ || parameters_.size() != other.parameters_.size()) { @@ -219,6 +210,12 @@ public: } TypeProxy add_array_of(TypeProxy type, Node node = Node()) { + if (type.type_storage_ != this) { + error_handling::handle_general_error( + "TypeStorage: Can't add array of type from another type " + "storage"); + } + std::vector parameters; parameters.push_back(type); @@ -230,6 +227,15 @@ public: nodes::TypeProxy add_container_of(std::vector &¶meters, builtin::types::Type container, Node node = Node()) { + for (auto ¶meter : parameters) { + if (parameter.type_storage_ != this) { + error_handling::handle_general_error( + "TypeStorage: Can't add container with parameter of type from " + "another type " + "storage"); + } + } + return add_type( nodes::Type(nodes::Identifier(node, nodes::Identifier::SIMPLE_TYPE, builtin::types::to_string(container)), @@ -237,6 +243,12 @@ public: } nodes::TypeProxy add_modification_of(TypeProxy type, Modifier modifier) { + if (type.type_storage_ != this) { + error_handling::handle_general_error( + "TypeStorage: Can't add modification of type from another type " + "storage"); + } + Type type_copy = *type.get(); type_copy.set_modifier(modifier); @@ -253,24 +265,159 @@ public: return TypeProxy(*this, storage_.size() - 1); } - // TODO: - // bool try_resolve_all_generic_names - // bool add_generic_type - // bool add_local_type - // // add local type requirement - // // deduce generic type - // void clear_local_types - // ... + // -- deal with generic types (variable types in this case) + + bool resolve_all_generic_types() { + bool are_all_resolved = true; + + bool new_types_resolved = true; + + while (new_types_resolved) { + new_types_resolved = false; + + for (auto &type : storage_) { + if (type.is_generic()) { + auto iter = resolved_generic_names_.find(*type.get_name()->get()); + + // because of undefined order sone types can became resolved earlir + // wirking correctly because each generic type has <= 1 successor, no + // cyclic deps allowed (do check ??) + if (iter != resolved_generic_names_.end()) { + new_types_resolved = true; + type = storage_[iter->second]; + } else { + are_all_resolved = false; + } + } + } + } + + // this check is not required ?? + for (auto &type : storage_) { + if (!type.is_generic()) { + are_all_resolved = false; + break; + } + } + + return are_all_resolved; + } + + TypeProxy add_generic_type() { + return add_type(Type(generate_generic_type_identifier())); + } + + bool resolve_generic_name(const std::string &name, + const TypeProxy &actulal_type) { + if (actulal_type.type_storage_ != this) { + error_handling::handle_general_error( + "TypeStorage: Can't resolve generic type to type from another type " + "storage"); + } + + if (resolved_generic_names_.count(name) != 0) { + return false; + } + + resolved_generic_names_[name] = actulal_type.id_; + + return true; + } + + void clear_resolved_generic_names() { resolved_generic_names_.clear(); } + + // -- deal with local types + + bool add_local_type(const std::string &name) { + if (local_name_ids_.count(name) != 0) { + return false; + } + + local_name_ids_[name] = local_name_typeclasses_.size(); + local_name_typeclasses_.emplace_back(); + + return true; + } + + bool add_local_type_requirement(const std::string &name, + const Identifier &typeclass) { + auto iter = local_name_ids_.find(name); + + if (iter == local_name_ids_.end()) { + return false; + } + + local_name_typeclasses_[iter->second].insert(typeclass); + + return true; + } + + bool add_local_type_requirement(const std::string &name, + Identifier &&typeclass) { + auto iter = local_name_ids_.find(name); + + if (iter == local_name_ids_.end()) { + return false; + } + + local_name_typeclasses_[iter->second].insert(std::move(typeclass)); + + return true; + } + + std::optional *> + get_local_type_requirements(const std::string &name) { + auto iter = local_name_ids_.find(name); + + if (iter == local_name_ids_.end()) { + return std::nullopt; + } + + return &local_name_typeclasses_[iter->second]; + } + + std::optional *> + get_local_type_requirements(const std::string &name) const { + auto iter = local_name_ids_.find(name); + + if (iter == local_name_ids_.end()) { + return std::nullopt; + } + + return &local_name_typeclasses_[iter->second]; + } + + void clear_local_name_typeclasses() { + local_name_ids_.clear(); + local_name_typeclasses_.clear(); + } private: Type *get_type(size_t id) { return &storage_.at(id); } const Type *get_type(size_t id) const { return &storage_.at(id); } + Identifier generate_generic_type_identifier() { + Identifier identifier = + Identifier(Node(), Identifier::GENERIC_TYPE, + "G_" + std::to_string(last_generic_type_id_)); + ++last_generic_type_id_; + return identifier; + } + private: - // TODO - // std::unordered_map named_local_types_; + // check is builtin type instaniated std::unordered_map primitive_type_ids_; + + // deal with generic types and generic names + std::unordered_map resolved_generic_names_; + size_t last_generic_type_id_ = 0; + + // deal with local types + std::unordered_map local_name_ids_; + std::vector> local_name_typeclasses_; + + // storage for all types std::vector storage_; };