TypeStorage extensions: generic types, local types

This commit is contained in:
ProgramSnail 2023-08-14 21:30:06 +03:00
parent fa01d36a84
commit 17b409fe51
2 changed files with 173 additions and 24 deletions

View file

@ -231,6 +231,8 @@ public:
// ANNOTATION, used as std::string // ANNOTATION, used as std::string
OPERATOR, OPERATOR,
PLACEHOLDER, PLACEHOLDER,
//
GENERIC_TYPE,
}; };
Identifier(Node node, IdentifierType type, std::string &&value) Identifier(Node node, IdentifierType type, std::string &&value)

View file

@ -7,9 +7,9 @@
#include <iterator> #include <iterator>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <set>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <variant> #include <variant>
#include <vector> #include <vector>
@ -35,19 +35,6 @@ private:
size_t id_; 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 { class Type {
public: public:
Type(Identifier &&identifier, Modifier modifier = nodes::Modifier::CONST, 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 { bool operator==(const Type &other) const {
if (name_ != other.name_ || modifier_ != other.modifier_ || if (name_ != other.name_ || modifier_ != other.modifier_ ||
parameters_.size() != other.parameters_.size()) { parameters_.size() != other.parameters_.size()) {
@ -219,6 +210,12 @@ public:
} }
TypeProxy add_array_of(TypeProxy type, Node node = Node()) { 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<nodes::TypeProxy> parameters; std::vector<nodes::TypeProxy> parameters;
parameters.push_back(type); parameters.push_back(type);
@ -230,6 +227,15 @@ public:
nodes::TypeProxy add_container_of(std::vector<TypeProxy> &&parameters, nodes::TypeProxy add_container_of(std::vector<TypeProxy> &&parameters,
builtin::types::Type container, builtin::types::Type container,
Node node = Node()) { Node node = Node()) {
for (auto &parameter : 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( return add_type(
nodes::Type(nodes::Identifier(node, nodes::Identifier::SIMPLE_TYPE, nodes::Type(nodes::Identifier(node, nodes::Identifier::SIMPLE_TYPE,
builtin::types::to_string(container)), builtin::types::to_string(container)),
@ -237,6 +243,12 @@ public:
} }
nodes::TypeProxy add_modification_of(TypeProxy type, Modifier modifier) { 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 type_copy = *type.get();
type_copy.set_modifier(modifier); type_copy.set_modifier(modifier);
@ -253,24 +265,159 @@ public:
return TypeProxy(*this, storage_.size() - 1); return TypeProxy(*this, storage_.size() - 1);
} }
// TODO: // -- deal with generic types (variable types in this case)
// bool try_resolve_all_generic_names
// bool add_generic_type bool resolve_all_generic_types() {
// bool add_local_type bool are_all_resolved = true;
// // add local type requirement
// // deduce generic type bool new_types_resolved = true;
// void clear_local_types
// ... 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<std::set<Identifier> *>
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<const std::set<Identifier> *>
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: private:
Type *get_type(size_t id) { return &storage_.at(id); } Type *get_type(size_t id) { return &storage_.at(id); }
const Type *get_type(size_t id) const { 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: private:
// TODO // check is builtin type instaniated
// std::unordered_map<std::string, size_t> named_local_types_;
std::unordered_map<builtin::types::Type, size_t> primitive_type_ids_; std::unordered_map<builtin::types::Type, size_t> primitive_type_ids_;
// deal with generic types and generic names
std::unordered_map<std::string, size_t> resolved_generic_names_;
size_t last_generic_type_id_ = 0;
// deal with local types
std::unordered_map<std::string, size_t> local_name_ids_;
std::vector<std::set<Identifier>> local_name_typeclasses_;
// storage for all types
std::vector<Type> storage_; std::vector<Type> storage_;
}; };