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; std::unordered_set<std::string> annotations;
if (type.has_value()) { if (type.has_value()) {
type.value().get()->collect_annotations_recursively( type.value().get().CollectAnnotationsRecursively(
std::insert_iterator<std::unordered_set<std::string>>( std::insert_iterator<std::unordered_set<std::string>>(
annotations, annotations.begin())); annotations, annotations.begin()));
} }

View file

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

View file

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

View file

@ -23,13 +23,16 @@ class Type {
friend TypeStorage; friend TypeStorage;
public: 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: private:
Type(TypeStorage &type_storage, size_t id) Type(TypeStorage &type_storage, size_t id)
@ -45,297 +48,193 @@ using Types = std::vector<Type>;
class TypeData { class TypeData {
public: 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 ?? // TODO: cache with map ??
std::optional<Type> std::optional<Type> ParamByName(const std::string &name) const {
get_parameter_proxy_by_name(const std::string &name) const {
const auto it = std::find_if( const auto it = std::find_if(
parameters_.begin(), parameters_.end(), [&name](const auto &parameter) { params.begin(), params.end(), [&name](const auto &parameter) {
return parameter.get()->has_annotation() && return parameter.get().HasAnnotation() &&
*parameter.get()->get_annotation().value() == name; parameter.get().annotation.value() == name;
}); });
if (it != parameters_.end()) { if (it != params.end()) {
return *it; return *it;
} }
return std::nullopt; 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) { bool IsModifier(Modifier other_modifier) const {
auto proxy = get_parameter_proxy_by_name(name); return modifier == other_modifier;
return proxy.has_value() ? proxy.value().get()
: std::optional<TypeData *>{};
} }
// //
Modifier get_modifier() const { return modifier_; } bool HasAnnotation() const { return annotation.has_value(); }
void set_modifier(Modifier modifier) { modifier_ = modifier; } bool IsAnnotation(const std::string &other_annotation) const {
return annotation.has_value() and annotation.value() == other_annotation;
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;
} }
template <typename T> template <typename T>
void collect_annotations_recursively( void
std::insert_iterator<T> insert_iterator) const { CollectAnnotationsRecursively(std::insert_iterator<T> insert_iterator) const {
if (annotation_.has_value()) { if (annotation.has_value()) {
insert_iterator = annotation_.value(); insert_iterator = annotation.value();
} }
for (auto &parameter : parameters_) { for (auto &parameter : params) {
parameter.get()->collect_annotations_recursively(insert_iterator); 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 { std::strong_ordering operator<=>(const TypeData &other) const {
if (name_ != other.name_ || modifier_ != other.modifier_ || if (name != other.name) {
parameters_.size() != other.parameters_.size()) { return name.value <=> other.name.value;
return false;
} }
for (size_t i = 0; i < parameters_.size(); ++i) { if (modifier != other.modifier) {
if (parameters_[i] != other.parameters_[i]) { return modifier <=> other.modifier;
return false; }
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 ?? // is parameters count check necessary ??
builtin::Type to_builtin() const { builtin::Type ToBuiltin() const {
auto builtin_type = builtin::types::to_type(name_.value); auto builtin_type = builtin::types::to_type(name.value);
auto builtin_type_parameters_count = auto builtin_type_parameters_count =
builtin::types::get_parameters_count(builtin_type); builtin::types::get_parameters_count(builtin_type);
// for fixed parameter counts // for fixed parameter counts
if (builtin_type_parameters_count.has_value() && 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::NONE;
} }
return builtin_type; return builtin_type;
} }
bool is_builtin(builtin::Type type) const { return to_builtin() == type; } bool IsBuiltin(builtin::Type type) const { return ToBuiltin() == type; }
private: public:
Identifier name_; Identifier name;
std::vector<Type> parameters_; std::vector<Type> params = {};
Modifier modifier_ = Modifier::NONE; Modifier modifier = Modifier::NONE;
std::optional<std::string> annotation_; std::optional<std::string> annotation = {};
}; };
class TypeStorage { class TypeStorage {
friend Type; friend Type;
public: 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); 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) { Type AddType(TypeData type) {
storage_.push_back(type);
return Type(*this, storage_.size() - 1);
}
Type add_type(TypeData &&type) {
storage_.push_back(std::move(type)); storage_.push_back(std::move(type));
return Type(*this, storage_.size() - 1); return Type(*this, storage_.size() - 1);
} }
// -- deal with generic types (variable types in this case) // -- deal with generic types (variable types in this case)
bool resolve_all_generic_types(); Type AddGenericType() {
return AddType(TypeData{.name = GenerateGenericTypeId()});
Type add_generic_type() {
return add_type(TypeData(generate_generic_type_identifier()));
} }
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 enum class UnifyModePolicy { // TODO: proper modes for modifier
Ignore, // all mode differences ignored kIgnore, // all mode differences ignored
ApplyStrongest, // unique > shared, modes changed kApplyStrongest, // unique > shared, modes changed
CheckLeftIsSubmode, // only check is performed kCheckLeftIsSubmode, // only check is performed
}; };
// TODO: next iteration of type check // 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 = {}*/); 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: 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: private:
// check is builtin type instaniated // check is builtin type instaniated
std::unordered_map<builtin::Type, size_t> primitive_type_ids_; std::unordered_map<builtin::Type, size_t> primitive_type_ids_;
// deal with generic types and generic names // 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; size_t last_generic_type_id_ = 0;
// TODO: needed ??
// deal with local types // deal with local types
std::unordered_map<std::string, size_t> local_name_ids_; // std::unordered_map<std::string, size_t> local_name_ids_;
std::vector<std::set<Identifier>> local_name_typeclasses_; // std::vector<std::set<Identifier>> local_name_typeclasses_;
// storage for all types // storage for all types
std::vector<TypeData> storage_; std::vector<TypeData> storage_; // TODO: map ??
}; };
} // namespace nodes } // namespace nodes

View file

@ -4,69 +4,76 @@
namespace nodes { 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 { std::strong_ordering Type::operator<=>(const Type &other) const {
return *get() == *other.get(); return get() <=> other.get();
} }
// //
Type TypeStorage::primitive(builtin::Type type) { Type TypeStorage::Primitive(builtin::Type type) {
auto iter = primitive_type_ids_.find(type); auto iter = primitive_type_ids_.find(type);
if (iter != primitive_type_ids_.end()) { if (iter != primitive_type_ids_.end()) {
return Type(*this, iter->second); return Type(*this, iter->second);
} else { } else {
primitive_type_ids_[type] = storage_.size(); primitive_type_ids_[type] = storage_.size();
return add_type(TypeData(Identifier{ return AddType(TypeData{
.kind = Identifier::kSimpleType, .name =
.value = builtin::types::to_string(type), 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) { if (type.type_storage_ != this) {
error_handling::handle_general_error( error_handling::handle_general_error(
"TypeStorage: Can't add array of type from another type " "TypeStorage: Can't add array of type from another type "
"storage"); "storage");
} }
std::vector<nodes::Type> parameters; std::vector<nodes::Type> params;
parameters.push_back(type); params.push_back(type);
return add_type(TypeData( return AddType(TypeData{
Identifier{ .name =
.kind = Identifier::kSimpleType, Identifier{
.value = builtin::types::ARRAY_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) { if (type.type_storage_ != this) {
error_handling::handle_general_error( error_handling::handle_general_error(
"TypeStorage: Can't add error of type from another type " "TypeStorage: Can't add error of type from another type "
"storage"); "storage");
} }
std::vector<nodes::Type> parameters; std::vector<nodes::Type> params;
parameters.push_back(type); params.push_back(type);
return add_type(TypeData( return AddType(TypeData{
Identifier{ .name =
.kind = Identifier::kSimpleType, Identifier{
.value = builtin::types::ERROR_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) { builtin::Type container) {
for (auto &parameter : parameters) { for (auto &param : params) {
if (parameter.type_storage_ != this) { if (param.type_storage_ != this) {
error_handling::handle_general_error( error_handling::handle_general_error(
"TypeStorage: Can't add container with parameter of type from " "TypeStorage: Can't add container with parameter of type from "
"another type " "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{
nodes::Identifier{ .name =
.kind = nodes::Identifier::kSimpleType, nodes::Identifier{
.value = builtin::types::to_string(container), .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) { if (type.type_storage_ != this) {
error_handling::handle_general_error( error_handling::handle_general_error(
"TypeStorage: Can't add modification of type from another type " "TypeStorage: Can't add modification of type from another type "
"storage"); "storage");
} }
TypeData type_copy = *type.get(); TypeData type_copy = type.get();
type_copy.set_modifier(modifier); 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) // -- deal with generic types (variable types in this case)
bool TypeStorage::resolve_all_generic_types() { // bool TypeStorage::ResolveAllGenericTypes() {
bool are_all_resolved = true; // bool are_all_resolved = true;
bool new_types_resolved = true; // bool new_types_resolved = true;
while (new_types_resolved) { // while (new_types_resolved) {
new_types_resolved = false; // new_types_resolved = false;
for (auto &type : storage_) { // for (auto &type : storage_) {
if (type.is_generic()) { // if (type.is_generic()) {
auto iter = resolved_generic_names_.find(type.get_name()->value); // auto iter = resolved_generic_names_.find(type.get_name()->value);
// because of undefined order some types can became resolved earlir // // because of undefined order some types can became resolved earlir
// wirking correctly because each generic type has <= 1 successor, no // // wirking correctly because each generic type has <= 1 successor, no
// cyclic deps allowed (do check ??) // // cyclic deps allowed (do check ??)
if (iter != resolved_generic_names_.end()) { // if (iter != resolved_generic_names_.end()) {
new_types_resolved = true; // new_types_resolved = true;
type = storage_[iter->second]; // type = storage_[iter->second];
} else { // } else {
are_all_resolved = false; // are_all_resolved = false;
} // }
} // }
} // }
} // }
// this check is not required ?? // // this check is not required ??
for (auto &type : storage_) { // for (auto &type : storage_) {
if (!type.is_generic()) { // if (!type.is_generic()) {
are_all_resolved = false; // are_all_resolved = false;
break; // break;
} // }
} // }
return are_all_resolved; // return are_all_resolved;
} // }
bool TypeStorage::resolve_generic_name(const std::string &name, // bool TypeStorage::ResolveGenericName(const std::string &name,
const Type &actulal_type) { // const Type &actulal_type) {
if (actulal_type.type_storage_ != this) { // if (actulal_type.type_storage_ != this) {
error_handling::handle_general_error( // error_handling::handle_general_error(
"TypeStorage: Can't resolve generic type to type from another type " // "TypeStorage: Can't resolve generic type to type from another type "
"storage"); // "storage");
} // }
if (resolved_generic_names_.count(name) != 0) { // if (resolved_generic_names_.count(name) != 0) {
return false; // return false;
} // }
resolved_generic_names_[name] = actulal_type.id_; // resolved_generic_names_[name] = actulal_type.id_;
return true; // return true;
} // }
// -- deal with local types // -- deal with local types
bool TypeStorage::add_local_type(const std::string &name) { // bool TypeStorage::AddLocalType(const std::string &name) {
if (local_name_ids_.count(name) != 0) { // if (local_name_ids_.count(name) != 0) {
return false; // return false;
} // }
local_name_ids_[name] = local_name_typeclasses_.size(); // local_name_ids_[name] = local_name_typeclasses_.size();
local_name_typeclasses_.emplace_back(); // local_name_typeclasses_.emplace_back();
return true; // return true;
} // }
bool TypeStorage::add_local_type_requirement(const std::string &name, // bool TypeStorage::add_local_type_requirement(const std::string &name,
const Identifier &typeclass) { // const Identifier &typeclass) {
auto iter = local_name_ids_.find(name); // auto iter = local_name_ids_.find(name);
if (iter == local_name_ids_.end()) { // if (iter == local_name_ids_.end()) {
return false; // 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, // bool TypeStorage::add_local_type_requirement(const std::string &name,
Identifier &&typeclass) { // Identifier &&typeclass) {
auto iter = local_name_ids_.find(name); // auto iter = local_name_ids_.find(name);
if (iter == local_name_ids_.end()) { // if (iter == local_name_ids_.end()) {
return false; // 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> *> // std::optional<std::set<Identifier> *>
TypeStorage::get_local_type_requirements(const std::string &name) { // TypeStorage::get_local_type_requirements(const std::string &name) {
auto iter = local_name_ids_.find(name); // auto iter = local_name_ids_.find(name);
if (iter == local_name_ids_.end()) { // if (iter == local_name_ids_.end()) {
return std::nullopt; // return std::nullopt;
} // }
return &local_name_typeclasses_[iter->second]; // return &local_name_typeclasses_[iter->second];
} // }
std::optional<const std::set<Identifier> *> // std::optional<const std::set<Identifier> *>
TypeStorage::get_local_type_requirements(const std::string &name) const { // TypeStorage::get_local_type_requirements(const std::string &name) const {
auto iter = local_name_ids_.find(name); // auto iter = local_name_ids_.find(name);
if (iter == local_name_ids_.end()) { // if (iter == local_name_ids_.end()) {
return std::nullopt; // return std::nullopt;
} // }
return &local_name_typeclasses_[iter->second]; // return &local_name_typeclasses_[iter->second];
} // }
// TODO // TODO
bool TypeStorage::unify(Type /*left_proxy*/, Type /*right_proxy*/, bool TypeStorage::Unify(Type /*left*/, Type /*right*/,
UnifyModePolicy /*policy*/) { UnifyModePolicy /*policy*/) {
// Type &left = left_id.get(); // Type &left = left_id.get();
// Type &right = right_id.get(); // Type &right = right_id.get();
@ -275,12 +284,12 @@ bool TypeStorage::unify(Type /*left_proxy*/, Type /*right_proxy*/,
throw std::exception(); throw std::exception();
} }
bool TypeStorage::resolve( bool TypeStorage::Resolve(
Type generic, const TypeData &replacement /* TODO , Mode mode = {}*/) { Type generic, const TypeData &replacement /* TODO , Mode mode = {}*/) {
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()->is_generic(), "Type should be generic"); error_handling::ensure(generic.get().IsGeneric(), "Type should be generic");
for (auto &type : storage_) { 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 = replacement;
// type.mode = mode; // type.mode = mode;
} }
@ -291,7 +300,7 @@ bool TypeStorage::resolve(
// //
Identifier TypeStorage::generate_generic_type_identifier() { Identifier TypeStorage::GenerateGenericTypeId() {
Identifier identifier = Identifier{ Identifier identifier = Identifier{
.kind = Identifier::kGenericType, .kind = Identifier::kGenericType,
.value = "G_" + std::to_string(last_generic_type_id_), .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, Result PrintTask<nodes::Type>::operator()(const nodes::Type &type,
const Args &args) { const Args &args) {
return Run(*type.get(), args); return Run(type.get(), args);
} }
// TODO: better printing format for builtin types // TODO: better printing format for builtin types
Result PrintTask<nodes::TypeData>::operator()(const nodes::TypeData &type, Result PrintTask<nodes::TypeData>::operator()(const nodes::TypeData &type,
const Args &) { const Args &) {
if (type.has_annotation()) { if (type.HasAnnotation()) {
Run(nodes::Annotation{.value = *type.get_annotation().value()}); Run(nodes::Annotation{.value = type.annotation.value()});
Space(); Space();
} }
if (type.get_modifier() != nodes::Modifier::CONST) { if (type.modifier != nodes::Modifier::CONST) {
Run(type.get_modifier()); Run(type.modifier);
} }
Run(*type.get_name()); Run(type.name);
if (type.parameters_size() > 0) { if (type.params.size() > 0) {
Print("["); Print("[");
for (size_t i = 0; i < type.parameters_size(); ++i) { for (size_t i = 0; i < type.params.size(); ++i) {
Run(*type.get_parameter(i)); Run(type.params.at(i));
if (i + 1 < type.parameters_size()) { if (i + 1 < type.params.size()) {
Space(); Space();
} }
} }

View file

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

View file

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

View file

@ -2,4 +2,245 @@
#include "expression_type_check.hpp" #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()) { 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); 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 = 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(), variable_result = Run(expr.variable.value(),
Args{expr.variable.value()}.Expect( Args{expr.variable.value()}.Expect(
@ -192,7 +192,7 @@ Result CheckTask<nodes::Loop>::operator()(const nodes::Loop &expr,
return Result::invalid(); return Result::invalid();
} }
return TypeCheckFromArgs(state<Types>().add_array_of(expression_result.Get()), return TypeCheckFromArgs(state<Types>().AddArrayOf(expression_result.Get()),
args, current_pos); args, current_pos);
} }
@ -233,7 +233,7 @@ Result CheckTask<nodes::Container>::CheckArray(const nodes::Container &expr,
} }
return TypeCheckFromArgs( return TypeCheckFromArgs(
state<Types>().add_array_of(last_expr_result.value().Get()), args, state<Types>().AddArrayOf(last_expr_result.value().Get()), args,
current_pos); current_pos);
} }
@ -260,7 +260,7 @@ Result CheckTask<nodes::Container>::CheckBlock(const nodes::Container &expr,
Result block_brought_type = Result block_brought_type =
context_exit_type.has_value() context_exit_type.has_value()
? Result(context_exit_type.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); return TypeCheckFromArgs(block_brought_type.Get(), args, current_pos);
} }
@ -305,7 +305,7 @@ Result CheckTask<nodes::Return>::operator()(const nodes::Return &expr,
break; break;
} }
return TypeCheckFromArgs(state<Types>().primitive(builtin::Type::UNIT), args, return TypeCheckFromArgs(state<Types>().Primitive(builtin::Type::UNIT), args,
current_pos); current_pos);
} }
@ -324,15 +324,14 @@ CheckTask<nodes::NameDefinition>::operator()(const nodes::NameDefinition &expr,
// assigned type shold be one of <-, <>, -- (can't be ->) // assigned type shold be one of <-, <>, -- (can't be ->)
const auto variable_type = args.passed().value(); const auto variable_type = args.passed().value();
if (nodes::utils::modifier_contains_OUT( if (nodes::utils::modifier_contains_OUT(variable_type.get().modifier)) {
variable_type.get()->get_modifier())) {
// TODO: modifiers are nto fully implemented yet // TODO: modifiers are nto fully implemented yet
TypeCheckError("Variable can't be assigned from out (->) value", TypeCheckError("Variable can't be assigned from out (->) value",
current_pos); current_pos);
} }
// variable is accessible by reference by default // 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. ?? // TODO: warning if name is same to package prefix, function prefix, etc. ??
if (not state<State>().InsertVariable(expr.name.value, variable_type, 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 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); current_pos);
} }
@ -370,8 +369,8 @@ Result CheckTask<nodes::Access>::CheckArrayAccess(const nodes::Access &expr,
} }
// NOTE: 0 - type of array // NOTE: 0 - type of array
return TypeCheckFromArgs(value_result.Get().get()->get_parameter_proxy(0), return TypeCheckFromArgs(value_result.Get().get().params.front(), args,
args, current_pos); current_pos);
} }
Result CheckTask<nodes::Access>::CheckTupleAccess(const nodes::Access &expr, 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 .get<size_t>() // Index type
.value(); .value();
return TypeCheckFromArgs(value_result.Get().get()->get_parameter_proxy(index), return TypeCheckFromArgs(value_result.Get().get().params.at(index), args,
args, current_pos); current_pos);
} }
Result CheckTask<nodes::Access>::operator()(const nodes::Access &expr, 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); current_pos);
} }
@ -432,8 +431,8 @@ Result CheckTask<nodes::ModifierExpression>::operator()(
// TODO: check expect for parametrized type without parameters // TODO: check expect for parametrized type without parameters
auto given_args = nodes::utils::is_suffix_modifier(expr.modifier) auto given_args = nodes::utils::is_suffix_modifier(expr.modifier)
? Args{expr.expr}.Expect({ ? Args{expr.expr}.Expect({
state<Types>().primitive(builtin::Type::OPTIONAL), state<Types>().Primitive(builtin::Type::OPTIONAL),
state<Types>().primitive(builtin::Type::RESULT), state<Types>().Primitive(builtin::Type::RESULT),
}) })
: Args{expr.expr}; : Args{expr.expr};
@ -444,14 +443,13 @@ Result CheckTask<nodes::ModifierExpression>::operator()(
} }
if (nodes::utils::is_suffix_modifier(expr.modifier)) { // optional, result 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 -> case builtin::Type::OPTIONAL: { // '?' - open optional / result in ->
// (execute // (execute
// or not execute pattern matching expression) // or not execute pattern matching expression)
// / (value / return) // / (value / return)
const auto underlying_type = const auto underlying_type = modified_result.Get().get().params.front();
modified_result.Get().get()->get_parameter_proxy(0);
// TODO: alternative for bring in future // TODO: alternative for bring in future
if (not state<State>().ReturnType(underlying_type)) { if (not state<State>().ReturnType(underlying_type)) {
@ -463,8 +461,7 @@ Result CheckTask<nodes::ModifierExpression>::operator()(
} }
case builtin::Type::RESULT: { // '!' - open optional / result -> value / case builtin::Type::RESULT: { // '!' - open optional / result -> value /
// panic // panic
const auto underlying_type = const auto underlying_type = modified_result.Get().get().params.front();
modified_result.Get().get()->get_parameter_proxy(0);
modified_result.Set(underlying_type); modified_result.Set(underlying_type);
break; break;
@ -477,8 +474,8 @@ Result CheckTask<nodes::ModifierExpression>::operator()(
// NOTE: other modifiers applied instead of current one // NOTE: other modifiers applied instead of current one
// TODO: check that modification is possible (not all casts are possible) // TODO: check that modification is possible (not all casts are possible)
modified_result.Set(state<Types>().add_modification_of( modified_result.Set(
modified_result.Get(), expr.modifier)); state<Types>().AddModificationOf(modified_result.Get(), expr.modifier));
} }
return TypeCheckFromArgs(modified_result.Get(), args, current_pos); 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(); 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); 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) { for (size_t i = 0; i < expr.args.size(); ++i) {
if (not state<State>().InsertVariable(expr.args.at(i).value, if (not state<State>().InsertVariable(expr.args.at(i).value,
state<Types>().add_generic_type(), state<Types>().AddGenericType(),
nodes::NameDefinition::Kind::LET)) { nodes::NameDefinition::Kind::LET)) {
// TODO: choose LET / CONST // TODO: choose LET / CONST
TypeCheckError("Variable is already defined in this context", 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 // 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 } // 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 */); 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, Result CheckTypeSameToExpected(nodes::Type type, const Args &args,
@ -99,8 +99,8 @@ std::optional<nodes::Type> UnfoldUserDefinedType(nodes::Type type,
bool handle_errors) { bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck); Log::Context logc(executor.log(), Log::Area::kTypeCheck);
const auto maybe_type_definition = FindTypeDefinition( const auto maybe_type_definition =
type.get()->get_name()->value, pos, executor, handle_errors); FindTypeDefinition(type.get().name.value, pos, executor, handle_errors);
if (!maybe_type_definition.has_value()) { if (!maybe_type_definition.has_value()) {
return std::nullopt; return std::nullopt;
@ -110,13 +110,13 @@ std::optional<nodes::Type> UnfoldUserDefinedType(nodes::Type type,
if (handle_errors) { if (handle_errors) {
logc.Error<Log::kProc>({{std::format( logc.Error<Log::kProc>({{std::format(
"Only type declaration found for type {} (type is not defined)", "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; return std::nullopt;
} }
// TODO: perform type args substitution // 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)"}}); {{"Unfold of generic type is not supported (yet)"}});
// //
return maybe_type_definition.value()->type.value(); 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) { const utils::Pos &pos, Executor &executor, bool handle_errors) {
Log::Context logc(executor.log(), Log::Area::kTypeCheck); Log::Context logc(executor.log(), Log::Area::kTypeCheck);
switch (type.get()->to_builtin()) { switch (type.get().ToBuiltin()) {
case builtin::Type::TUPLE: { // access field 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) { if (not maybe_field.has_value() and handle_errors) {
// TODO: pass unfolded type name to log it ?? // TODO: pass unfolded type name to log it ??
@ -159,7 +159,7 @@ FieldTypeByName(nodes::Type type, const std::string &field,
logc.Error<Log::kProc>( logc.Error<Log::kProc>(
{{std::format("Type {} has no accessible fields by definition", {{std::format("Type {} has no accessible fields by definition",
builtin::types::to_string( builtin::types::to_string(
type.get()->to_builtin()))}} /* TODO: node */); type.get().ToBuiltin()))}} /* TODO: node */);
} }
return std::nullopt; return std::nullopt;
} }