type node refactoring

This commit is contained in:
ProgramSnail 2024-09-15 17:24:15 +03:00
parent 361a267054
commit 662a846d2d
11 changed files with 564 additions and 415 deletions

View file

@ -246,7 +246,7 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
std::unordered_set<std::string> annotations;
if (type.has_value()) {
type.value().get()->collect_annotations_recursively(
type.value().get().CollectAnnotationsRecursively(
std::insert_iterator<std::unordered_set<std::string>>(
annotations, annotations.begin()));
}

View file

@ -61,7 +61,7 @@ std::vector<nodes::Type> collect_parameters(parser::ParseTree::Node first_node,
parameters.push_back(
BuilderTask<nodes::Type>{executor}(current_node, {}));
if (current_annotation.has_value()) {
parameters.back().get()->set_annotation(current_annotation.value());
parameters.back().get().annotation = current_annotation.value();
}
}
current_node = current_node.next_named_sibling();
@ -77,7 +77,7 @@ nodes::Type build_container_type(parser::ParseTree::Node parser_node,
std::vector<nodes::Type> parameters =
collect_parameters(parser_node.nth_named_child(0), executor);
return executor.state<Types>().add_container_of(std::move(parameters),
return executor.state<Types>().AddContainerOf(std::move(parameters),
container);
}
@ -103,7 +103,7 @@ nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::REFERENCE_TYPE>>::operator()(
Log::Context logc(executor.log(), Log::Area::kParse);
nodes::Type type = Run<nodes::Type>(parser_node.nth_named_child(0));
type.get()->set_modifier(RunOther<nodes::Modifier>(parser_node.nth_child(0)));
type.get().modifier = RunOther<nodes::Modifier>(parser_node.nth_child(0));
return type;
}
@ -112,8 +112,8 @@ nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::MODIFIED_TYPE>>::operator()(
const ParserNode &parser_node, const Args &) {
Log::Context logc(executor.log(), Log::Area::kParse);
std::vector<nodes::Type> parameters;
parameters.push_back(Run<nodes::Type>(parser_node.nth_named_child(0)));
std::vector<nodes::Type> params;
params.push_back(Run<nodes::Type>(parser_node.nth_named_child(0)));
nodes::Modifier modifier = RunOther<nodes::Modifier>(
parser_node.nth_child(parser_node.child_count() - 1));
@ -133,10 +133,11 @@ nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::MODIFIED_TYPE>>::operator()(
break;
}
return executor.state<Types>().add_type(
nodes::TypeData(nodes::Identifier{.kind = nodes::Identifier::kSimpleType,
return executor.state<Types>().AddType(nodes::TypeData{
.name = nodes::Identifier{.kind = nodes::Identifier::kSimpleType,
.value = identifier},
std::move(parameters)));
.params = std::move(params),
});
}
// type_identifier ('[' (annotation? type)+ ']')?
@ -146,11 +147,13 @@ nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::SIMPLE_TYPE>>::operator()(
auto name_node = parser_node.child_by_field_name("name");
std::vector<nodes::Type> parameters =
std::vector<nodes::Type> params =
collect_parameters(name_node.next_named_sibling(), executor);
return executor.state<Types>().add_type(nodes::TypeData(
RunOther<nodes::Identifier>(name_node), std::move(parameters)));
return executor.state<Types>().AddType(nodes::TypeData{
.name = RunOther<nodes::Identifier>(name_node),
.params = std::move(params),
});
}
} // namespace builders

View file

@ -55,8 +55,8 @@ struct FunctionDefinition {
Argument(const std::optional<std::string> &annotation, Type type,
Modifier before_modifier = Modifier::NONE)
: annotation(annotation), type(type), before_modifier(before_modifier),
after_modifier(
builtin::types::get_modifier(type.get()->to_builtin())) {}
after_modifier(builtin::types::get_modifier(type.get().ToBuiltin())) {
}
//
@ -109,7 +109,7 @@ struct FunctionDefinition {
}
auto type_after_modifier =
builtin::types::get_modifier(new_type.get()->to_builtin());
builtin::types::get_modifier(new_type.get().ToBuiltin());
if (after_modifier != Modifier::NONE &&
after_modifier != type_after_modifier) {

View file

@ -23,13 +23,16 @@ class Type {
friend TypeStorage;
public:
TypeData *get();
TypeData &get();
const TypeData *get() const;
const TypeData &get() const;
bool operator==(const Type &other) const;
std::strong_ordering operator<=>(const Type &other) const;
bool operator!=(const Type &) const = default;
// TODO: FIXME: should be automatic
bool operator==(const Type &other) const {
return (*this <=> other) == std::strong_ordering::equal;
}
private:
Type(TypeStorage &type_storage, size_t id)
@ -45,297 +48,193 @@ using Types = std::vector<Type>;
class TypeData {
public:
TypeData(Identifier &&identifier, Modifier modifier = nodes::Modifier::CONST,
const std::optional<std::string> &annotation = std::nullopt)
: name_(std::move(identifier)), modifier_(modifier),
annotation_(annotation) {}
TypeData(const Identifier &identifier,
Modifier modifier = nodes::Modifier::CONST,
const std::optional<std::string> &annotation = std::nullopt)
: name_(identifier), modifier_(modifier), annotation_(annotation) {}
TypeData(Identifier &&identifier, std::vector<Type> &&parameters,
Modifier modifier = nodes::Modifier::CONST,
const std::optional<std::string> &annotation = std::nullopt)
: name_(std::move(identifier)), parameters_(std::move(parameters)),
modifier_(modifier), annotation_(annotation) {}
TypeData(const Identifier &identifier, std::vector<Type> &&parameters,
Modifier modifier = nodes::Modifier::CONST,
const std::optional<std::string> &annotation = std::nullopt)
: name_(identifier), parameters_(std::move(parameters)),
modifier_(modifier), annotation_(annotation) {}
//
Identifier *get_name() { return &name_; }
const Identifier *get_name() const { return &name_; }
//
size_t parameters_size() const { return parameters_.size(); }
Type get_parameter_proxy(size_t id) const { return parameters_.at(id); }
TypeData *get_parameter(size_t id) { return get_parameter_proxy(id).get(); }
const TypeData *get_parameter(size_t id) const {
return get_parameter_proxy(id).get();
}
// TODO: cache with map ??
std::optional<Type>
get_parameter_proxy_by_name(const std::string &name) const {
std::optional<Type> ParamByName(const std::string &name) const {
const auto it = std::find_if(
parameters_.begin(), parameters_.end(), [&name](const auto &parameter) {
return parameter.get()->has_annotation() &&
*parameter.get()->get_annotation().value() == name;
params.begin(), params.end(), [&name](const auto &parameter) {
return parameter.get().HasAnnotation() &&
parameter.get().annotation.value() == name;
});
if (it != parameters_.end()) {
if (it != params.end()) {
return *it;
}
return std::nullopt;
}
std::optional<const TypeData *>
get_parameter_by_name(const std::string &name) const {
const auto proxy = get_parameter_proxy_by_name(name);
return proxy.has_value() ? proxy.value().get()
: std::optional<const TypeData *>{};
}
//
std::optional<TypeData *> get_parameter_by_name(const std::string &name) {
auto proxy = get_parameter_proxy_by_name(name);
return proxy.has_value() ? proxy.value().get()
: std::optional<TypeData *>{};
bool IsModifier(Modifier other_modifier) const {
return modifier == other_modifier;
}
//
Modifier get_modifier() const { return modifier_; }
bool HasAnnotation() const { return annotation.has_value(); }
void set_modifier(Modifier modifier) { modifier_ = modifier; }
bool is_modifier(Modifier modifier) const { return modifier_ == modifier; }
//
bool has_annotation() const { return annotation_.has_value(); }
std::optional<std::string *> get_annotation() {
if (annotation_.has_value()) {
return &annotation_.value();
}
return std::nullopt;
}
std::optional<const std::string *> get_annotation() const {
if (annotation_.has_value()) {
return &annotation_.value();
}
return std::nullopt;
}
bool is_no_annotation() const { return !annotation_.has_value(); }
bool is_annotation(const std::string &annotation) const {
return annotation_.has_value() && annotation_.value() == annotation;
}
void set_annotation(std::string &&annotation) {
annotation_ = std::move(annotation);
}
void set_annotation(const std::string &annotation) {
annotation_ = annotation;
bool IsAnnotation(const std::string &other_annotation) const {
return annotation.has_value() and annotation.value() == other_annotation;
}
template <typename T>
void collect_annotations_recursively(
std::insert_iterator<T> insert_iterator) const {
if (annotation_.has_value()) {
insert_iterator = annotation_.value();
void
CollectAnnotationsRecursively(std::insert_iterator<T> insert_iterator) const {
if (annotation.has_value()) {
insert_iterator = annotation.value();
}
for (auto &parameter : parameters_) {
parameter.get()->collect_annotations_recursively(insert_iterator);
for (auto &parameter : params) {
parameter.get().CollectAnnotationsRecursively(insert_iterator);
}
}
//
bool is_generic() { return name_.kind == Identifier::kGenericType; }
bool IsGeneric() const { return name.kind == Identifier::kGenericType; }
//
bool operator==(const TypeData &other) const {
if (name_ != other.name_ || modifier_ != other.modifier_ ||
parameters_.size() != other.parameters_.size()) {
return false;
std::strong_ordering operator<=>(const TypeData &other) const {
if (name != other.name) {
return name.value <=> other.name.value;
}
for (size_t i = 0; i < parameters_.size(); ++i) {
if (parameters_[i] != other.parameters_[i]) {
return false;
if (modifier != other.modifier) {
return modifier <=> other.modifier;
}
if (params.size() != other.params.size()) {
return params.size() <=> other.params.size();
}
for (size_t i = 0; i < params.size(); ++i) {
if ((params[i].get() <=> other.params[i].get()) !=
std::strong_ordering::equal) {
return params[i].get() <=> other.params[i].get();
}
}
return true;
return std::strong_ordering::equal;
}
bool operator!=(const TypeData &other) const { return !(*this == other); }
//
bool operator<(const TypeData &other) const {
if (name_ != other.name_) {
return name_.value < other.name_.value;
}
if (modifier_ != other.modifier_) {
return modifier_ < other.modifier_;
}
if (parameters_.size() != other.parameters_.size()) {
return parameters_.size() < other.parameters_.size();
}
for (size_t i = 0; i < parameters_.size(); ++i) {
if (parameters_[i] != other.parameters_[i]) {
return false;
}
}
return true;
}
bool operator>(const TypeData &other) const { return other < *this; }
bool operator<=(const TypeData &other) const { return !operator>(other); }
bool operator>=(const TypeData &other) const { return !operator<(other); }
// is parameters count check necessary ??
builtin::Type to_builtin() const {
auto builtin_type = builtin::types::to_type(name_.value);
builtin::Type ToBuiltin() const {
auto builtin_type = builtin::types::to_type(name.value);
auto builtin_type_parameters_count =
builtin::types::get_parameters_count(builtin_type);
// for fixed parameter counts
if (builtin_type_parameters_count.has_value() &&
builtin_type_parameters_count.value() != parameters_.size()) {
builtin_type_parameters_count.value() != params.size()) {
return builtin::Type::NONE;
}
return builtin_type;
}
bool is_builtin(builtin::Type type) const { return to_builtin() == type; }
bool IsBuiltin(builtin::Type type) const { return ToBuiltin() == type; }
private:
Identifier name_;
std::vector<Type> parameters_;
Modifier modifier_ = Modifier::NONE;
std::optional<std::string> annotation_;
public:
Identifier name;
std::vector<Type> params = {};
Modifier modifier = Modifier::NONE;
std::optional<std::string> annotation = {};
};
class TypeStorage {
friend Type;
public:
Type primitive(builtin::Type type);
Type Primitive(builtin::Type type);
Type add_array_of(Type type);
Type AddArrayOf(Type type);
Type add_error_of(Type type);
Type AddErrorOf(Type type);
nodes::Type add_container_of(std::vector<Type> &&parameters,
nodes::Type AddContainerOf(std::vector<Type> &&parameters,
builtin::Type container);
nodes::Type add_modification_of(Type type, Modifier modifier);
nodes::Type AddModificationOf(Type type, Modifier modifier);
Type add_type(const TypeData &type) {
storage_.push_back(type);
return Type(*this, storage_.size() - 1);
}
Type add_type(TypeData &&type) {
Type AddType(TypeData type) {
storage_.push_back(std::move(type));
return Type(*this, storage_.size() - 1);
}
// -- deal with generic types (variable types in this case)
bool resolve_all_generic_types();
Type add_generic_type() {
return add_type(TypeData(generate_generic_type_identifier()));
Type AddGenericType() {
return AddType(TypeData{.name = GenerateGenericTypeId()});
}
bool resolve_generic_name(const std::string &name, const Type &actulal_type);
void clear_resolved_generic_names() { resolved_generic_names_.clear(); }
// -- deal with local types // not needed ??
bool add_local_type(const std::string &name);
bool add_local_type_requirement(const std::string &name,
const Identifier &typeclass);
bool add_local_type_requirement(const std::string &name,
Identifier &&typeclass);
std::optional<std::set<Identifier> *>
get_local_type_requirements(const std::string &name);
std::optional<const std::set<Identifier> *>
get_local_type_requirements(const std::string &name) const;
void clear_local_name_typeclasses() {
local_name_ids_.clear();
local_name_typeclasses_.clear();
}
//
enum class UnifyModePolicy { // TODO: proper modes for modifier
Ignore, // all mode differences ignored
ApplyStrongest, // unique > shared, modes changed
CheckLeftIsSubmode, // only check is performed
kIgnore, // all mode differences ignored
kApplyStrongest, // unique > shared, modes changed
kCheckLeftIsSubmode, // only check is performed
};
// TODO: next iteration of type check
bool unify(Type left_proxy, Type right_proxy, UnifyModePolicy policy);
bool Unify(Type left, Type right, UnifyModePolicy policy);
bool resolve(Type generic,
bool Resolve(Type generic,
const TypeData &replacement /* TODO , Mode mode = {}*/);
// TODO: needed ??
// bool resolve_all_generic_types();
// bool resolve_generic_name(const std::string &name, const Type
// &actulal_type);
// void clear_resolved_generic_names() { resolved_generic_names_.clear(); }
// -- deal with local types // not needed ??
// bool add_local_type(const std::string &name);
// bool add_local_type_requirement(const std::string &name,
// const Identifier &typeclass);
// bool add_local_type_requirement(const std::string &name,
// Identifier &&typeclass);
// std::optional<std::set<Identifier> *>
// get_local_type_requirements(const std::string &name);
// std::optional<const std::set<Identifier> *>
// get_local_type_requirements(const std::string &name) const;
// void clear_local_name_typeclasses() {
// local_name_ids_.clear();
// local_name_typeclasses_.clear();
// }
private:
TypeData *get_type(size_t id) { return &storage_.at(id); }
TypeData &operator[](size_t id) { return storage_.at(id); }
const TypeData *get_type(size_t id) const { return &storage_.at(id); }
const TypeData &operator[](size_t id) const { return storage_.at(id); }
Identifier generate_generic_type_identifier();
Identifier GenerateGenericTypeId();
private:
// check is builtin type instaniated
std::unordered_map<builtin::Type, size_t> primitive_type_ids_;
// deal with generic types and generic names
std::unordered_map<std::string, size_t> resolved_generic_names_;
// std::unordered_map<std::string, size_t> resolved_generic_names_; // TODO:
// needed ??
size_t last_generic_type_id_ = 0;
// TODO: needed ??
// deal with local types
std::unordered_map<std::string, size_t> local_name_ids_;
std::vector<std::set<Identifier>> local_name_typeclasses_;
// std::unordered_map<std::string, size_t> local_name_ids_;
// std::vector<std::set<Identifier>> local_name_typeclasses_;
// storage for all types
std::vector<TypeData> storage_;
std::vector<TypeData> storage_; // TODO: map ??
};
} // namespace nodes

View file

@ -4,69 +4,76 @@
namespace nodes {
TypeData *Type::get() { return type_storage_->get_type(id_); }
TypeData &Type::get() { return (*type_storage_)[id_]; }
const TypeData *Type::get() const { return type_storage_->get_type(id_); }
const TypeData &Type::get() const { return (*type_storage_)[id_]; }
bool Type::operator==(const Type &other) const {
return *get() == *other.get();
std::strong_ordering Type::operator<=>(const Type &other) const {
return get() <=> other.get();
}
//
Type TypeStorage::primitive(builtin::Type type) {
Type TypeStorage::Primitive(builtin::Type type) {
auto iter = primitive_type_ids_.find(type);
if (iter != primitive_type_ids_.end()) {
return Type(*this, iter->second);
} else {
primitive_type_ids_[type] = storage_.size();
return add_type(TypeData(Identifier{
return AddType(TypeData{
.name =
Identifier{
.kind = Identifier::kSimpleType,
.value = builtin::types::to_string(type),
}));
},
});
}
}
Type TypeStorage::add_array_of(Type type) {
Type TypeStorage::AddArrayOf(Type type) {
if (type.type_storage_ != this) {
error_handling::handle_general_error(
"TypeStorage: Can't add array of type from another type "
"storage");
}
std::vector<nodes::Type> parameters;
parameters.push_back(type);
std::vector<nodes::Type> params;
params.push_back(type);
return add_type(TypeData(
return AddType(TypeData{
.name =
Identifier{
.kind = Identifier::kSimpleType,
.value = builtin::types::ARRAY_IDENTIFIER,
},
std::move(parameters)));
.params = std::move(params),
});
}
Type TypeStorage::add_error_of(Type type) {
Type TypeStorage::AddErrorOf(Type type) {
if (type.type_storage_ != this) {
error_handling::handle_general_error(
"TypeStorage: Can't add error of type from another type "
"storage");
}
std::vector<nodes::Type> parameters;
parameters.push_back(type);
std::vector<nodes::Type> params;
params.push_back(type);
return add_type(TypeData(
return AddType(TypeData{
.name =
Identifier{
.kind = Identifier::kSimpleType,
.value = builtin::types::ERROR_IDENTIFIER,
},
std::move(parameters)));
.params = std::move(params),
});
}
nodes::Type TypeStorage::add_container_of(std::vector<Type> &&parameters,
nodes::Type TypeStorage::AddContainerOf(std::vector<Type> &&params,
builtin::Type container) {
for (auto &parameter : parameters) {
if (parameter.type_storage_ != this) {
for (auto &param : params) {
if (param.type_storage_ != this) {
error_handling::handle_general_error(
"TypeStorage: Can't add container with parameter of type from "
"another type "
@ -74,146 +81,148 @@ nodes::Type TypeStorage::add_container_of(std::vector<Type> &&parameters,
}
}
return add_type(nodes::TypeData(
return AddType(nodes::TypeData{
.name =
nodes::Identifier{
.kind = nodes::Identifier::kSimpleType,
.value = builtin::types::to_string(container),
},
std::move(parameters)));
.params = std::move(params),
});
}
nodes::Type TypeStorage::add_modification_of(Type type, Modifier modifier) {
nodes::Type TypeStorage::AddModificationOf(Type type, Modifier modifier) {
if (type.type_storage_ != this) {
error_handling::handle_general_error(
"TypeStorage: Can't add modification of type from another type "
"storage");
}
TypeData type_copy = *type.get();
type_copy.set_modifier(modifier);
TypeData type_copy = type.get();
type_copy.modifier = modifier;
return add_type(std::move(type_copy));
return AddType(std::move(type_copy));
}
// -- deal with generic types (variable types in this case)
bool TypeStorage::resolve_all_generic_types() {
bool are_all_resolved = true;
// bool TypeStorage::ResolveAllGenericTypes() {
// bool are_all_resolved = true;
bool new_types_resolved = true;
// bool new_types_resolved = true;
while (new_types_resolved) {
new_types_resolved = false;
// 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()->value);
// for (auto &type : storage_) {
// if (type.is_generic()) {
// auto iter = resolved_generic_names_.find(type.get_name()->value);
// because of undefined order some 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;
}
}
}
}
// // because of undefined order some 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;
}
}
// // this check is not required ??
// for (auto &type : storage_) {
// if (!type.is_generic()) {
// are_all_resolved = false;
// break;
// }
// }
return are_all_resolved;
}
// return are_all_resolved;
// }
bool TypeStorage::resolve_generic_name(const std::string &name,
const Type &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");
}
// bool TypeStorage::ResolveGenericName(const std::string &name,
// const Type &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;
}
// if (resolved_generic_names_.count(name) != 0) {
// return false;
// }
resolved_generic_names_[name] = actulal_type.id_;
// resolved_generic_names_[name] = actulal_type.id_;
return true;
}
// return true;
// }
// -- deal with local types
bool TypeStorage::add_local_type(const std::string &name) {
if (local_name_ids_.count(name) != 0) {
return false;
}
// bool TypeStorage::AddLocalType(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();
// local_name_ids_[name] = local_name_typeclasses_.size();
// local_name_typeclasses_.emplace_back();
return true;
}
// return true;
// }
bool TypeStorage::add_local_type_requirement(const std::string &name,
const Identifier &typeclass) {
auto iter = local_name_ids_.find(name);
// bool TypeStorage::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;
}
// if (iter == local_name_ids_.end()) {
// return false;
// }
local_name_typeclasses_[iter->second].insert(typeclass);
// local_name_typeclasses_[iter->second].insert(typeclass);
return true;
}
// return true;
// }
bool TypeStorage::add_local_type_requirement(const std::string &name,
Identifier &&typeclass) {
auto iter = local_name_ids_.find(name);
// bool TypeStorage::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;
}
// if (iter == local_name_ids_.end()) {
// return false;
// }
local_name_typeclasses_[iter->second].insert(std::move(typeclass));
// local_name_typeclasses_[iter->second].insert(std::move(typeclass));
return true;
}
// return true;
// }
std::optional<std::set<Identifier> *>
TypeStorage::get_local_type_requirements(const std::string &name) {
auto iter = local_name_ids_.find(name);
// std::optional<std::set<Identifier> *>
// TypeStorage::get_local_type_requirements(const std::string &name) {
// auto iter = local_name_ids_.find(name);
if (iter == local_name_ids_.end()) {
return std::nullopt;
}
// if (iter == local_name_ids_.end()) {
// return std::nullopt;
// }
return &local_name_typeclasses_[iter->second];
}
// return &local_name_typeclasses_[iter->second];
// }
std::optional<const std::set<Identifier> *>
TypeStorage::get_local_type_requirements(const std::string &name) const {
auto iter = local_name_ids_.find(name);
// std::optional<const std::set<Identifier> *>
// TypeStorage::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;
}
// if (iter == local_name_ids_.end()) {
// return std::nullopt;
// }
return &local_name_typeclasses_[iter->second];
}
// return &local_name_typeclasses_[iter->second];
// }
// TODO
bool TypeStorage::unify(Type /*left_proxy*/, Type /*right_proxy*/,
bool TypeStorage::Unify(Type /*left*/, Type /*right*/,
UnifyModePolicy /*policy*/) {
// Type &left = left_id.get();
// Type &right = right_id.get();
@ -275,12 +284,12 @@ bool TypeStorage::unify(Type /*left_proxy*/, Type /*right_proxy*/,
throw std::exception();
}
bool TypeStorage::resolve(
bool TypeStorage::Resolve(
Type generic, const TypeData &replacement /* TODO , Mode mode = {}*/) {
error_handling::ensure(generic.get()->is_generic(), "Type should be generic");
error_handling::ensure(generic.get()->is_generic(), "Type should be generic");
error_handling::ensure(generic.get().IsGeneric(), "Type should be generic");
error_handling::ensure(generic.get().IsGeneric(), "Type should be generic");
for (auto &type : storage_) {
if (type.is_generic() && type.get_name() == generic.get()->get_name()) {
if (type.IsGeneric() && type.name == generic.get().name) {
type = replacement;
// type.mode = mode;
}
@ -291,7 +300,7 @@ bool TypeStorage::resolve(
//
Identifier TypeStorage::generate_generic_type_identifier() {
Identifier TypeStorage::GenerateGenericTypeId() {
Identifier identifier = Identifier{
.kind = Identifier::kGenericType,
.value = "G_" + std::to_string(last_generic_type_id_),

View file

@ -7,27 +7,27 @@ namespace printers {
Result PrintTask<nodes::Type>::operator()(const nodes::Type &type,
const Args &args) {
return Run(*type.get(), args);
return Run(type.get(), args);
}
// TODO: better printing format for builtin types
Result PrintTask<nodes::TypeData>::operator()(const nodes::TypeData &type,
const Args &) {
if (type.has_annotation()) {
Run(nodes::Annotation{.value = *type.get_annotation().value()});
if (type.HasAnnotation()) {
Run(nodes::Annotation{.value = type.annotation.value()});
Space();
}
if (type.get_modifier() != nodes::Modifier::CONST) {
Run(type.get_modifier());
if (type.modifier != nodes::Modifier::CONST) {
Run(type.modifier);
}
Run(*type.get_name());
Run(type.name);
if (type.parameters_size() > 0) {
if (type.params.size() > 0) {
Print("[");
for (size_t i = 0; i < type.parameters_size(); ++i) {
Run(*type.get_parameter(i));
if (i + 1 < type.parameters_size()) {
for (size_t i = 0; i < type.params.size(); ++i) {
Run(type.params.at(i));
if (i + 1 < type.params.size()) {
Space();
}
}

View file

@ -189,13 +189,13 @@ public:
Args ExpectBuiltin(builtin::Type type, Executor &executor) const {
Args copy(*this);
copy.expected_types_ = {executor.state<Types>().primitive(type)};
copy.expected_types_ = {executor.state<Types>().Primitive(type)};
return copy;
}
Args PassBuiltin(builtin::Type type, Executor &executor) const {
Args copy(*this);
copy.passed_type_ = executor.state<Types>().primitive(type);
copy.passed_type_ = executor.state<Types>().Primitive(type);
return copy;
}

View file

@ -8,31 +8,31 @@ nodes::Type get_literal_type(const nodes::Literal &literal,
switch (literal.value.index()) {
case 0: // float
return executor.state<Types>().primitive(builtin::Type::FLOAT);
return executor.state<Types>().Primitive(builtin::Type::FLOAT);
case 1: // double
return executor.state<Types>().primitive(builtin::Type::DOUBLE);
return executor.state<Types>().Primitive(builtin::Type::DOUBLE);
case 2: // int32_t
return executor.state<Types>().primitive(builtin::Type::INT);
return executor.state<Types>().Primitive(builtin::Type::INT);
case 3: // int64_t
return executor.state<Types>().primitive(builtin::Type::LONG);
return executor.state<Types>().Primitive(builtin::Type::LONG);
case 4: // size_t
return executor.state<Types>().primitive(builtin::Type::INDEX);
return executor.state<Types>().Primitive(builtin::Type::INDEX);
case 5: // std::string
return executor.state<Types>().add_array_of(
executor.state<Types>().primitive(builtin::Type::CHAR));
return executor.state<Types>().AddArrayOf(
executor.state<Types>().Primitive(builtin::Type::CHAR));
case 6: // unicode_string
return executor.state<Types>().add_array_of(
executor.state<Types>().primitive(builtin::Type::UNICODE));
return executor.state<Types>().AddArrayOf(
executor.state<Types>().Primitive(builtin::Type::UNICODE));
case 7: // char
return executor.state<Types>().primitive(builtin::Type::CHAR);
return executor.state<Types>().Primitive(builtin::Type::CHAR);
case 8: // unicode
return executor.state<Types>().primitive(builtin::Type::UNICODE);
return executor.state<Types>().Primitive(builtin::Type::UNICODE);
case 9: // bool
return executor.state<Types>().primitive(builtin::Type::BOOL);
return executor.state<Types>().Primitive(builtin::Type::BOOL);
case 10: // unit
return executor.state<Types>().primitive(builtin::Type::UNIT);
return executor.state<Types>().Primitive(builtin::Type::UNIT);
case 11: // null
return executor.state<Types>().primitive(builtin::Type::NULL_OPTION);
return executor.state<Types>().Primitive(builtin::Type::NULL_OPTION);
}
utils::Assert(true, "Unreachable");

View file

@ -2,4 +2,245 @@
#include "expression_type_check.hpp"
namespace type_check {} // namespace type_check
namespace type_check {
// <------ NOTE: CHECK ENDED THERE
// TODO: add constraints evaluation
Result CheckTask<nodes::Constructor>::operator()(const nodes::Constructor &expr,
const Args &args) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
const auto current_pos = PosOf(args.current_id);
// TODO: constraints ??
// TODO: use pass type
const auto maybe_type_definition =
FindTypeDefinition(expr.type.get().name.value, current_pos, executor);
if (!maybe_type_definition.has_value()) {
return Result::invalid();
}
const nodes::TypeDefinition *type_definition = maybe_type_definition.value();
if (!type_definition->type.has_value()) {
TypeCheckError(
"Type defenition for constructor type not found (declaration only)",
current_pos);
return Result::invalid();
}
// TODO: deal with anniotations, recursive annotations
// TODO: check that is not typeclass ??
nodes::Type type = type_definition->type.value();
// TODO: work with different parametric types: tuple, variant, ...
if (expr.args.size() == 0) {
TypeCheckError("Number of type constructor arguments should be > 0",
current_pos);
return Result::invalid();
// TODO: try return correct type (constructor's type), when possible (not
// generic)
}
// TODO: work with generics (type_definition->args, ...)
const auto builtin_type = type.get().ToBuiltin();
{ // check args size, ets.
switch (builtin_type) {
case builtin::Type::TUPLE:
if (expr.args.size() != type.get().params.size()) {
TypeCheckError(
"Number of type constructor arguments is different from expected "
"(" +
std::to_string(expr.args.size()) + " instead of " +
std::to_string(type.get().params.size()) + ")",
current_pos);
return Result::invalid();
// TODO: try return correct type (constructor's type), when possible
// (not generic)
}
break;
case builtin::Type::VARIANT:
case builtin::Type::OPTIONAL:
case builtin::Type::RESULT:
case builtin::Type::ERROR:
case builtin::Type::FUNCTION:
case builtin::Type::NONE:
if (expr.args.size() != 1) { // TODO: better to_string
TypeCheckError(std::format("Number of type constructor arguments "
"should be = 1 (builtin type {})",
uint(builtin_type)),
current_pos);
return Result::invalid();
// TODO: try return correct type (constructor's type), when possible
// (not generic)
}
break;
default: // array, basic types
break;
}
if (builtin::types::get_parameters_count(builtin_type).has_value() &&
type.get().params.size() !=
builtin::types::get_parameters_count(builtin_type).value()) {
TypeCheckError("Wrong amount of parametars for builtin type",
current_pos);
return Result::invalid();
// TODO: try return correct type (constructor's type), when possible (not
// generic)
}
}
std::optional<size_t> chosen_variant_option; // for VARIANT
{ // check annotations
const auto check_same_annotation =
[&expr, this](size_t i,
std::optional<const std::string_view> expected_annotation,
bool log_errors) {
bool is_same = true;
const auto annotation = expr.args.at(i).first;
if (annotation.has_value() != expected_annotation.has_value()) {
if (log_errors) {
TypeCheckError(
"Wrong type constructor argument annotation: should be " +
std::string{expected_annotation.has_value()
? expected_annotation.value()
: "[none]"},
PosOf(expr.args.at(i).second));
}
is_same = false;
}
if (annotation.has_value() &&
annotation.value() != expected_annotation.value()) {
if (log_errors) {
TypeCheckError("Wrong function argument type annotation: " +
annotation.value() + " instead of " +
std::string{expected_annotation.value()},
PosOf(expr.args.at(i).second));
}
is_same = false;
}
return is_same;
};
const auto check_no_annotation = [&expr, this](size_t i, bool log_errors) {
if (expr.args.at(i).first.has_value()) {
if (log_errors) {
TypeCheckError(
"Type constructor argument annotation not expected there",
PosOf(expr.args.at(i).second));
}
return false;
}
return true;
};
switch (builtin_type) {
case builtin::Type::TUPLE:
for (size_t i = 0; i < expr.args.size(); ++i) {
check_same_annotation(i, type.get().params.at(i).get().annotation,
true /*log errors*/);
}
break;
case builtin::Type::VARIANT:
// more then one same annotation ??
for (size_t i = 0; i < type.get().params.size(); ++i) {
if (check_same_annotation(0, type.get().params.at(i).get().annotation,
false /*do not log errors*/)) {
chosen_variant_option = i;
break;
}
}
if (!chosen_variant_option.has_value() &&
!check_no_annotation(0, false /*do not log errors*/)) {
TypeCheckError("Wrong type constructor argument annotation in "
"constructor of variant type",
PosOf(expr.args.front().second));
}
break;
case builtin::Type::ERROR: // no anotations ??
check_same_annotation(0, type.get().params.front().get().annotation,
true /*log errors*/);
break;
case builtin::Type::OPTIONAL:
case builtin::Type::RESULT:
case builtin::Type::FUNCTION:
case builtin::Type::NONE:
check_no_annotation(0, true /*log errors*/);
break;
default: // array, basic types
break;
}
}
{ // type check args
switch (builtin_type) {
case builtin::Type::TUPLE:
for (size_t i = 0; i < expr.args.size(); ++i) {
Run(expr.args.at(i).second,
Args{expr.args.at(i).second}.Expect(type.get().params.at(i)));
}
break;
case builtin::Type::VARIANT:
if (chosen_variant_option.has_value()) {
Run(expr.args.front().second,
Args{expr.args.front().second}.Expect(
type.get().params.at(chosen_variant_option.value())));
} else { // TODO: error, if there is more then one possible variant in
// answer
nodes::Types possible_options = type.get().params;
Run(expr.args.front().second,
Args{expr.args.front().second}.Expect(possible_options));
}
break;
case builtin::Type::OPTIONAL:
// first parameter or NULL
Run(expr.args.front().second,
Args{expr.args.front().second}.Expect(
{type.get().params.front(),
state<Types>().Primitive(builtin::Type::NULL_OPTION)}));
break;
case builtin::Type::RESULT:
// first parameter or ERROR[second parameter]
Run(expr.args.front().second,
Args{expr.args.front().second}.Expect(
{type.get().params.front(),
state<Types>().AddErrorOf(type.get().params.at(1))}));
break;
case builtin::Type::ERROR:
// first parameter
Run(expr.args.front().second,
Args{expr.args.front().second}.Expect(type.get().params.front()));
break;
case builtin::Type::FUNCTION:
case builtin::Type::NONE:
// type itself
Run(expr.args.front().second,
Args{expr.args.front().second}.Expect(type));
break;
default: // array, basic types
TypeCheckError("Type can't be constructed", current_pos);
break;
}
}
// TODO: deduce generic parts in type
return TypeCheckFromArgs(expr.type, args, current_pos);
// TODO: add <- modifiier to type ??
} // IN PROGRESS
} // namespace type_check

View file

@ -105,7 +105,7 @@ Result CheckTask<nodes::Match>::operator()(const nodes::Match &expr,
}
if (not expr_result.has_value()) {
expr_result = Result{state<Types>().primitive(builtin::Type::UNIT)};
expr_result = Result{state<Types>().Primitive(builtin::Type::UNIT)};
}
return TypeCheckFromArgs(expr_result.value().Get(), args, current_pos);
@ -179,7 +179,7 @@ Result CheckTask<nodes::Loop>::operator()(const nodes::Loop &expr,
}
const auto range_elem_type =
interval_result.value().Get().get()->get_parameter_proxy(0);
interval_result.value().Get().get().params.at(0);
variable_result = Run(expr.variable.value(),
Args{expr.variable.value()}.Expect(
@ -192,7 +192,7 @@ Result CheckTask<nodes::Loop>::operator()(const nodes::Loop &expr,
return Result::invalid();
}
return TypeCheckFromArgs(state<Types>().add_array_of(expression_result.Get()),
return TypeCheckFromArgs(state<Types>().AddArrayOf(expression_result.Get()),
args, current_pos);
}
@ -233,7 +233,7 @@ Result CheckTask<nodes::Container>::CheckArray(const nodes::Container &expr,
}
return TypeCheckFromArgs(
state<Types>().add_array_of(last_expr_result.value().Get()), args,
state<Types>().AddArrayOf(last_expr_result.value().Get()), args,
current_pos);
}
@ -260,7 +260,7 @@ Result CheckTask<nodes::Container>::CheckBlock(const nodes::Container &expr,
Result block_brought_type =
context_exit_type.has_value()
? Result(context_exit_type.value())
: Result(state<Types>().primitive(builtin::Type::UNIT));
: Result(state<Types>().Primitive(builtin::Type::UNIT));
return TypeCheckFromArgs(block_brought_type.Get(), args, current_pos);
}
@ -305,7 +305,7 @@ Result CheckTask<nodes::Return>::operator()(const nodes::Return &expr,
break;
}
return TypeCheckFromArgs(state<Types>().primitive(builtin::Type::UNIT), args,
return TypeCheckFromArgs(state<Types>().Primitive(builtin::Type::UNIT), args,
current_pos);
}
@ -324,15 +324,14 @@ CheckTask<nodes::NameDefinition>::operator()(const nodes::NameDefinition &expr,
// assigned type shold be one of <-, <>, -- (can't be ->)
const auto variable_type = args.passed().value();
if (nodes::utils::modifier_contains_OUT(
variable_type.get()->get_modifier())) {
if (nodes::utils::modifier_contains_OUT(variable_type.get().modifier)) {
// TODO: modifiers are nto fully implemented yet
TypeCheckError("Variable can't be assigned from out (->) value",
current_pos);
}
// variable is accessible by reference by default
state<Types>().add_modification_of(variable_type, nodes::Modifier::REF);
state<Types>().AddModificationOf(variable_type, nodes::Modifier::REF);
// TODO: warning if name is same to package prefix, function prefix, etc. ??
if (not state<State>().InsertVariable(expr.name.value, variable_type,
@ -341,7 +340,7 @@ CheckTask<nodes::NameDefinition>::operator()(const nodes::NameDefinition &expr,
}
// Return BOOL (as any := / =: expression) == true
return TypeCheckFromArgs(state<Types>().primitive(builtin::Type::BOOL), args,
return TypeCheckFromArgs(state<Types>().Primitive(builtin::Type::BOOL), args,
current_pos);
}
@ -370,8 +369,8 @@ Result CheckTask<nodes::Access>::CheckArrayAccess(const nodes::Access &expr,
}
// NOTE: 0 - type of array
return TypeCheckFromArgs(value_result.Get().get()->get_parameter_proxy(0),
args, current_pos);
return TypeCheckFromArgs(value_result.Get().get().params.front(), args,
current_pos);
}
Result CheckTask<nodes::Access>::CheckTupleAccess(const nodes::Access &expr,
@ -395,8 +394,8 @@ Result CheckTask<nodes::Access>::CheckTupleAccess(const nodes::Access &expr,
.get<size_t>() // Index type
.value();
return TypeCheckFromArgs(value_result.Get().get()->get_parameter_proxy(index),
args, current_pos);
return TypeCheckFromArgs(value_result.Get().get().params.at(index), args,
current_pos);
}
Result CheckTask<nodes::Access>::operator()(const nodes::Access &expr,
@ -418,7 +417,7 @@ Result CheckTask<nodes::LoopControl>::operator()(const nodes::LoopControl &expr,
//
return TypeCheckFromArgs(state<Types>().primitive(builtin::Type::UNIT), args,
return TypeCheckFromArgs(state<Types>().Primitive(builtin::Type::UNIT), args,
current_pos);
}
@ -432,8 +431,8 @@ Result CheckTask<nodes::ModifierExpression>::operator()(
// TODO: check expect for parametrized type without parameters
auto given_args = nodes::utils::is_suffix_modifier(expr.modifier)
? Args{expr.expr}.Expect({
state<Types>().primitive(builtin::Type::OPTIONAL),
state<Types>().primitive(builtin::Type::RESULT),
state<Types>().Primitive(builtin::Type::OPTIONAL),
state<Types>().Primitive(builtin::Type::RESULT),
})
: Args{expr.expr};
@ -444,14 +443,13 @@ Result CheckTask<nodes::ModifierExpression>::operator()(
}
if (nodes::utils::is_suffix_modifier(expr.modifier)) { // optional, result
switch (modified_result.Get().get()->to_builtin()) {
switch (modified_result.Get().get().ToBuiltin()) {
case builtin::Type::OPTIONAL: { // '?' - open optional / result in ->
// (execute
// or not execute pattern matching expression)
// / (value / return)
const auto underlying_type =
modified_result.Get().get()->get_parameter_proxy(0);
const auto underlying_type = modified_result.Get().get().params.front();
// TODO: alternative for bring in future
if (not state<State>().ReturnType(underlying_type)) {
@ -463,8 +461,7 @@ Result CheckTask<nodes::ModifierExpression>::operator()(
}
case builtin::Type::RESULT: { // '!' - open optional / result -> value /
// panic
const auto underlying_type =
modified_result.Get().get()->get_parameter_proxy(0);
const auto underlying_type = modified_result.Get().get().params.front();
modified_result.Set(underlying_type);
break;
@ -477,8 +474,8 @@ Result CheckTask<nodes::ModifierExpression>::operator()(
// NOTE: other modifiers applied instead of current one
// TODO: check that modification is possible (not all casts are possible)
modified_result.Set(state<Types>().add_modification_of(
modified_result.Get(), expr.modifier));
modified_result.Set(
state<Types>().AddModificationOf(modified_result.Get(), expr.modifier));
}
return TypeCheckFromArgs(modified_result.Get(), args, current_pos);
@ -510,7 +507,7 @@ Result CheckTask<nodes::Lambda>::operator()(const nodes::Lambda &expr,
}
const auto expected_type = args.expected().front();
if (!expected_type.get()->is_builtin(builtin::Type::FUNCTION)) {
if (!expected_type.get().IsBuiltin(builtin::Type::FUNCTION)) {
TypeCheckError("Type of lambda function should be function", current_pos);
}
@ -539,7 +536,7 @@ Result CheckTask<nodes::Lambda>::operator()(const nodes::Lambda &expr,
for (size_t i = 0; i < expr.args.size(); ++i) {
if (not state<State>().InsertVariable(expr.args.at(i).value,
state<Types>().add_generic_type(),
state<Types>().AddGenericType(),
nodes::NameDefinition::Kind::LET)) {
// TODO: choose LET / CONST
TypeCheckError("Variable is already defined in this context",
@ -580,7 +577,7 @@ Result CheckTask<nodes::Extra>::operator()(const nodes::Extra &, const Args &) {
//
return Result(state<Types>().primitive(builtin::Type::UNIT));
return Result(state<Types>().Primitive(builtin::Type::UNIT));
}
// NOTE: CHECKED
@ -590,7 +587,7 @@ Result CheckTask<nodes::EmptyLines>::operator()(const nodes::EmptyLines &,
//
return Result(state<Types>().primitive(builtin::Type::UNIT));
return Result(state<Types>().Primitive(builtin::Type::UNIT));
}
} // namespace type_check

View file

@ -20,7 +20,7 @@ nodes::Type CheckSameToPassTypeInArgs(nodes::Type type, const Args &args,
logc.Error<Log::kProc>({{message}} /* TODO: node */);
}
return executor.state<Types>().primitive(builtin::Type::BOOL);
return executor.state<Types>().Primitive(builtin::Type::BOOL);
}
Result CheckTypeSameToExpected(nodes::Type type, const Args &args,
@ -99,8 +99,8 @@ std::optional<nodes::Type> UnfoldUserDefinedType(nodes::Type type,
bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
const auto maybe_type_definition = FindTypeDefinition(
type.get()->get_name()->value, pos, executor, handle_errors);
const auto maybe_type_definition =
FindTypeDefinition(type.get().name.value, pos, executor, handle_errors);
if (!maybe_type_definition.has_value()) {
return std::nullopt;
@ -110,13 +110,13 @@ std::optional<nodes::Type> UnfoldUserDefinedType(nodes::Type type,
if (handle_errors) {
logc.Error<Log::kProc>({{std::format(
"Only type declaration found for type {} (type is not defined)",
type.get()->get_name()->value)}} /* TODO: node*/);
type.get().name.value)}} /* TODO: node*/);
}
return std::nullopt;
}
// TODO: perform type args substitution
logc.Require<Log::kProc>(type.get()->parameters_size() == 0,
logc.Require<Log::kProc>(type.get().params.size() == 0,
{{"Unfold of generic type is not supported (yet)"}});
//
return maybe_type_definition.value()->type.value();
@ -127,10 +127,10 @@ FieldTypeByName(nodes::Type type, const std::string &field,
const utils::Pos &pos, Executor &executor, bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
switch (type.get()->to_builtin()) {
switch (type.get().ToBuiltin()) {
case builtin::Type::TUPLE: { // access field
const auto maybe_field = type.get()->get_parameter_proxy_by_name(field);
const auto maybe_field = type.get().ParamByName(field);
if (not maybe_field.has_value() and handle_errors) {
// TODO: pass unfolded type name to log it ??
@ -159,7 +159,7 @@ FieldTypeByName(nodes::Type type, const std::string &field,
logc.Error<Log::kProc>(
{{std::format("Type {} has no accessible fields by definition",
builtin::types::to_string(
type.get()->to_builtin()))}} /* TODO: node */);
type.get().ToBuiltin()))}} /* TODO: node */);
}
return std::nullopt;
}