mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-05 22:48:43 +00:00
TypeStorage extensions: generic types, local types
This commit is contained in:
parent
fa01d36a84
commit
17b409fe51
2 changed files with 173 additions and 24 deletions
|
|
@ -231,6 +231,8 @@ public:
|
|||
// ANNOTATION, used as std::string
|
||||
OPERATOR,
|
||||
PLACEHOLDER,
|
||||
//
|
||||
GENERIC_TYPE,
|
||||
};
|
||||
|
||||
Identifier(Node node, IdentifierType type, std::string &&value)
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -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<nodes::TypeProxy> parameters;
|
||||
parameters.push_back(type);
|
||||
|
||||
|
|
@ -230,6 +227,15 @@ public:
|
|||
nodes::TypeProxy add_container_of(std::vector<TypeProxy> &¶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<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:
|
||||
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<std::string, size_t> named_local_types_;
|
||||
// check is builtin type instaniated
|
||||
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_;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue