diff --git a/lang/builders/src/statement_builders.cpp b/lang/builders/src/statement_builders.cpp index 9b2d626..38b1b8c 100644 --- a/lang/builders/src/statement_builders.cpp +++ b/lang/builders/src/statement_builders.cpp @@ -246,7 +246,7 @@ BuilderTask::operator()(const ParserNode &parser_node, std::unordered_set annotations; if (type.has_value()) { - type.value().get()->collect_annotations_recursively( + type.value().get().CollectAnnotationsRecursively( std::insert_iterator>( annotations, annotations.begin())); } diff --git a/lang/builders/src/type_builders.cpp b/lang/builders/src/type_builders.cpp index 7564201..c85e199 100644 --- a/lang/builders/src/type_builders.cpp +++ b/lang/builders/src/type_builders.cpp @@ -61,7 +61,7 @@ std::vector collect_parameters(parser::ParseTree::Node first_node, parameters.push_back( BuilderTask{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,8 +77,8 @@ nodes::Type build_container_type(parser::ParseTree::Node parser_node, std::vector parameters = collect_parameters(parser_node.nth_named_child(0), executor); - return executor.state().add_container_of(std::move(parameters), - container); + return executor.state().AddContainerOf(std::move(parameters), + container); } // '|'? annotation? type ('|' annotation? type)+ @@ -103,7 +103,7 @@ nodes::Type BuilderTask>::operator()( Log::Context logc(executor.log(), Log::Area::kParse); nodes::Type type = Run(parser_node.nth_named_child(0)); - type.get()->set_modifier(RunOther(parser_node.nth_child(0))); + type.get().modifier = RunOther(parser_node.nth_child(0)); return type; } @@ -112,8 +112,8 @@ nodes::Type BuilderTask>::operator()( const ParserNode &parser_node, const Args &) { Log::Context logc(executor.log(), Log::Area::kParse); - std::vector parameters; - parameters.push_back(Run(parser_node.nth_named_child(0))); + std::vector params; + params.push_back(Run(parser_node.nth_named_child(0))); nodes::Modifier modifier = RunOther( parser_node.nth_child(parser_node.child_count() - 1)); @@ -133,10 +133,11 @@ nodes::Type BuilderTask>::operator()( break; } - return executor.state().add_type( - nodes::TypeData(nodes::Identifier{.kind = nodes::Identifier::kSimpleType, - .value = identifier}, - std::move(parameters))); + return executor.state().AddType(nodes::TypeData{ + .name = nodes::Identifier{.kind = nodes::Identifier::kSimpleType, + .value = identifier}, + .params = std::move(params), + }); } // type_identifier ('[' (annotation? type)+ ']')? @@ -146,11 +147,13 @@ nodes::Type BuilderTask>::operator()( auto name_node = parser_node.child_by_field_name("name"); - std::vector parameters = + std::vector params = collect_parameters(name_node.next_named_sibling(), executor); - return executor.state().add_type(nodes::TypeData( - RunOther(name_node), std::move(parameters))); + return executor.state().AddType(nodes::TypeData{ + .name = RunOther(name_node), + .params = std::move(params), + }); } } // namespace builders diff --git a/lang/nodes/include/statement_nodes.hpp b/lang/nodes/include/statement_nodes.hpp index 2678e13..8ee3804 100644 --- a/lang/nodes/include/statement_nodes.hpp +++ b/lang/nodes/include/statement_nodes.hpp @@ -55,8 +55,8 @@ struct FunctionDefinition { Argument(const std::optional &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) { diff --git a/lang/nodes/include/type_nodes.hpp b/lang/nodes/include/type_nodes.hpp index 88d9f2e..9579c69 100644 --- a/lang/nodes/include/type_nodes.hpp +++ b/lang/nodes/include/type_nodes.hpp @@ -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; class TypeData { public: - TypeData(Identifier &&identifier, Modifier modifier = nodes::Modifier::CONST, - const std::optional &annotation = std::nullopt) - : name_(std::move(identifier)), modifier_(modifier), - annotation_(annotation) {} - - TypeData(const Identifier &identifier, - Modifier modifier = nodes::Modifier::CONST, - const std::optional &annotation = std::nullopt) - : name_(identifier), modifier_(modifier), annotation_(annotation) {} - - TypeData(Identifier &&identifier, std::vector &¶meters, - Modifier modifier = nodes::Modifier::CONST, - const std::optional &annotation = std::nullopt) - : name_(std::move(identifier)), parameters_(std::move(parameters)), - modifier_(modifier), annotation_(annotation) {} - - TypeData(const Identifier &identifier, std::vector &¶meters, - Modifier modifier = nodes::Modifier::CONST, - const std::optional &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 - get_parameter_proxy_by_name(const std::string &name) const { + std::optional ParamByName(const std::string &name) const { const auto it = std::find_if( - parameters_.begin(), parameters_.end(), [&name](const auto ¶meter) { - return parameter.get()->has_annotation() && - *parameter.get()->get_annotation().value() == name; + params.begin(), params.end(), [&name](const auto ¶meter) { + return parameter.get().HasAnnotation() && + parameter.get().annotation.value() == name; }); - if (it != parameters_.end()) { + if (it != params.end()) { return *it; } return std::nullopt; } - std::optional - 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{}; - } + // - std::optional 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{}; + 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 get_annotation() { - if (annotation_.has_value()) { - return &annotation_.value(); - } - return std::nullopt; - } - - std::optional 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 - void collect_annotations_recursively( - std::insert_iterator insert_iterator) const { - if (annotation_.has_value()) { - insert_iterator = annotation_.value(); + void + CollectAnnotationsRecursively(std::insert_iterator insert_iterator) const { + if (annotation.has_value()) { + insert_iterator = annotation.value(); } - for (auto ¶meter : parameters_) { - parameter.get()->collect_annotations_recursively(insert_iterator); + for (auto ¶meter : 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 parameters_; - Modifier modifier_ = Modifier::NONE; - std::optional annotation_; +public: + Identifier name; + std::vector params = {}; + Modifier modifier = Modifier::NONE; + std::optional 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 &¶meters, - builtin::Type container); + nodes::Type AddContainerOf(std::vector &¶meters, + 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 *> - get_local_type_requirements(const std::string &name); - - std::optional *> - 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 *> + // get_local_type_requirements(const std::string &name); + + // std::optional *> + // 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 primitive_type_ids_; // deal with generic types and generic names - std::unordered_map resolved_generic_names_; + // std::unordered_map resolved_generic_names_; // TODO: + // needed ?? size_t last_generic_type_id_ = 0; + // TODO: needed ?? // deal with local types - std::unordered_map local_name_ids_; - std::vector> local_name_typeclasses_; + // std::unordered_map local_name_ids_; + // std::vector> local_name_typeclasses_; // storage for all types - std::vector storage_; + std::vector storage_; // TODO: map ?? }; } // namespace nodes diff --git a/lang/nodes/src/type_nodes.cpp b/lang/nodes/src/type_nodes.cpp index 5a2dba8..bc89806 100644 --- a/lang/nodes/src/type_nodes.cpp +++ b/lang/nodes/src/type_nodes.cpp @@ -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{ - .kind = Identifier::kSimpleType, - .value = builtin::types::to_string(type), - })); + 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 parameters; - parameters.push_back(type); + std::vector params; + params.push_back(type); - return add_type(TypeData( - Identifier{ - .kind = Identifier::kSimpleType, - .value = builtin::types::ARRAY_IDENTIFIER, - }, - std::move(parameters))); + return AddType(TypeData{ + .name = + Identifier{ + .kind = Identifier::kSimpleType, + .value = builtin::types::ARRAY_IDENTIFIER, + }, + .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 parameters; - parameters.push_back(type); + std::vector params; + params.push_back(type); - return add_type(TypeData( - Identifier{ - .kind = Identifier::kSimpleType, - .value = builtin::types::ERROR_IDENTIFIER, - }, - std::move(parameters))); + return AddType(TypeData{ + .name = + Identifier{ + .kind = Identifier::kSimpleType, + .value = builtin::types::ERROR_IDENTIFIER, + }, + .params = std::move(params), + }); } -nodes::Type TypeStorage::add_container_of(std::vector &¶meters, - builtin::Type container) { - for (auto ¶meter : parameters) { - if (parameter.type_storage_ != this) { +nodes::Type TypeStorage::AddContainerOf(std::vector &¶ms, + builtin::Type container) { + for (auto ¶m : 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 &¶meters, } } - return add_type(nodes::TypeData( - nodes::Identifier{ - .kind = nodes::Identifier::kSimpleType, - .value = builtin::types::to_string(container), - }, - std::move(parameters))); + return AddType(nodes::TypeData{ + .name = + nodes::Identifier{ + .kind = nodes::Identifier::kSimpleType, + .value = builtin::types::to_string(container), + }, + .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 *> -TypeStorage::get_local_type_requirements(const std::string &name) { - auto iter = local_name_ids_.find(name); +// std::optional *> +// 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 *> -TypeStorage::get_local_type_requirements(const std::string &name) const { - auto iter = local_name_ids_.find(name); +// std::optional *> +// 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_), diff --git a/lang/printers/src/type_printers.cpp b/lang/printers/src/type_printers.cpp index cf57e3e..c756ec6 100644 --- a/lang/printers/src/type_printers.cpp +++ b/lang/printers/src/type_printers.cpp @@ -7,27 +7,27 @@ namespace printers { Result PrintTask::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::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(); } } diff --git a/lang/type_check/include/type_check_utils.hpp b/lang/type_check/include/type_check_utils.hpp index 6de7620..35a86bd 100644 --- a/lang/type_check/include/type_check_utils.hpp +++ b/lang/type_check/include/type_check_utils.hpp @@ -189,13 +189,13 @@ public: Args ExpectBuiltin(builtin::Type type, Executor &executor) const { Args copy(*this); - copy.expected_types_ = {executor.state().primitive(type)}; + copy.expected_types_ = {executor.state().Primitive(type)}; return copy; } Args PassBuiltin(builtin::Type type, Executor &executor) const { Args copy(*this); - copy.passed_type_ = executor.state().primitive(type); + copy.passed_type_ = executor.state().Primitive(type); return copy; } diff --git a/lang/type_check/src/basic_type_check.cpp b/lang/type_check/src/basic_type_check.cpp index 6a27d8c..f4130b5 100644 --- a/lang/type_check/src/basic_type_check.cpp +++ b/lang/type_check/src/basic_type_check.cpp @@ -8,31 +8,31 @@ nodes::Type get_literal_type(const nodes::Literal &literal, switch (literal.value.index()) { case 0: // float - return executor.state().primitive(builtin::Type::FLOAT); + return executor.state().Primitive(builtin::Type::FLOAT); case 1: // double - return executor.state().primitive(builtin::Type::DOUBLE); + return executor.state().Primitive(builtin::Type::DOUBLE); case 2: // int32_t - return executor.state().primitive(builtin::Type::INT); + return executor.state().Primitive(builtin::Type::INT); case 3: // int64_t - return executor.state().primitive(builtin::Type::LONG); + return executor.state().Primitive(builtin::Type::LONG); case 4: // size_t - return executor.state().primitive(builtin::Type::INDEX); + return executor.state().Primitive(builtin::Type::INDEX); case 5: // std::string - return executor.state().add_array_of( - executor.state().primitive(builtin::Type::CHAR)); + return executor.state().AddArrayOf( + executor.state().Primitive(builtin::Type::CHAR)); case 6: // unicode_string - return executor.state().add_array_of( - executor.state().primitive(builtin::Type::UNICODE)); + return executor.state().AddArrayOf( + executor.state().Primitive(builtin::Type::UNICODE)); case 7: // char - return executor.state().primitive(builtin::Type::CHAR); + return executor.state().Primitive(builtin::Type::CHAR); case 8: // unicode - return executor.state().primitive(builtin::Type::UNICODE); + return executor.state().Primitive(builtin::Type::UNICODE); case 9: // bool - return executor.state().primitive(builtin::Type::BOOL); + return executor.state().Primitive(builtin::Type::BOOL); case 10: // unit - return executor.state().primitive(builtin::Type::UNIT); + return executor.state().Primitive(builtin::Type::UNIT); case 11: // null - return executor.state().primitive(builtin::Type::NULL_OPTION); + return executor.state().Primitive(builtin::Type::NULL_OPTION); } utils::Assert(true, "Unreachable"); diff --git a/lang/type_check/src/constructor_expression_type_check.cpp b/lang/type_check/src/constructor_expression_type_check.cpp index ec6e42a..5aebf73 100644 --- a/lang/type_check/src/constructor_expression_type_check.cpp +++ b/lang/type_check/src/constructor_expression_type_check.cpp @@ -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::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 chosen_variant_option; // for VARIANT + + { // check annotations + const auto check_same_annotation = + [&expr, this](size_t i, + std::optional 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().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().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 diff --git a/lang/type_check/src/expression_type_check.cpp b/lang/type_check/src/expression_type_check.cpp index 7cfbc70..73b297d 100644 --- a/lang/type_check/src/expression_type_check.cpp +++ b/lang/type_check/src/expression_type_check.cpp @@ -105,7 +105,7 @@ Result CheckTask::operator()(const nodes::Match &expr, } if (not expr_result.has_value()) { - expr_result = Result{state().primitive(builtin::Type::UNIT)}; + expr_result = Result{state().Primitive(builtin::Type::UNIT)}; } return TypeCheckFromArgs(expr_result.value().Get(), args, current_pos); @@ -179,7 +179,7 @@ Result CheckTask::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::operator()(const nodes::Loop &expr, return Result::invalid(); } - return TypeCheckFromArgs(state().add_array_of(expression_result.Get()), + return TypeCheckFromArgs(state().AddArrayOf(expression_result.Get()), args, current_pos); } @@ -233,7 +233,7 @@ Result CheckTask::CheckArray(const nodes::Container &expr, } return TypeCheckFromArgs( - state().add_array_of(last_expr_result.value().Get()), args, + state().AddArrayOf(last_expr_result.value().Get()), args, current_pos); } @@ -260,7 +260,7 @@ Result CheckTask::CheckBlock(const nodes::Container &expr, Result block_brought_type = context_exit_type.has_value() ? Result(context_exit_type.value()) - : Result(state().primitive(builtin::Type::UNIT)); + : Result(state().Primitive(builtin::Type::UNIT)); return TypeCheckFromArgs(block_brought_type.Get(), args, current_pos); } @@ -305,7 +305,7 @@ Result CheckTask::operator()(const nodes::Return &expr, break; } - return TypeCheckFromArgs(state().primitive(builtin::Type::UNIT), args, + return TypeCheckFromArgs(state().Primitive(builtin::Type::UNIT), args, current_pos); } @@ -324,15 +324,14 @@ CheckTask::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().add_modification_of(variable_type, nodes::Modifier::REF); + state().AddModificationOf(variable_type, nodes::Modifier::REF); // TODO: warning if name is same to package prefix, function prefix, etc. ?? if (not state().InsertVariable(expr.name.value, variable_type, @@ -341,7 +340,7 @@ CheckTask::operator()(const nodes::NameDefinition &expr, } // Return BOOL (as any := / =: expression) == true - return TypeCheckFromArgs(state().primitive(builtin::Type::BOOL), args, + return TypeCheckFromArgs(state().Primitive(builtin::Type::BOOL), args, current_pos); } @@ -370,8 +369,8 @@ Result CheckTask::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::CheckTupleAccess(const nodes::Access &expr, @@ -395,8 +394,8 @@ Result CheckTask::CheckTupleAccess(const nodes::Access &expr, .get() // 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::operator()(const nodes::Access &expr, @@ -418,7 +417,7 @@ Result CheckTask::operator()(const nodes::LoopControl &expr, // - return TypeCheckFromArgs(state().primitive(builtin::Type::UNIT), args, + return TypeCheckFromArgs(state().Primitive(builtin::Type::UNIT), args, current_pos); } @@ -432,8 +431,8 @@ Result CheckTask::operator()( // TODO: check expect for parametrized type without parameters auto given_args = nodes::utils::is_suffix_modifier(expr.modifier) ? Args{expr.expr}.Expect({ - state().primitive(builtin::Type::OPTIONAL), - state().primitive(builtin::Type::RESULT), + state().Primitive(builtin::Type::OPTIONAL), + state().Primitive(builtin::Type::RESULT), }) : Args{expr.expr}; @@ -444,14 +443,13 @@ Result CheckTask::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().ReturnType(underlying_type)) { @@ -463,8 +461,7 @@ Result CheckTask::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::operator()( // NOTE: other modifiers applied instead of current one // TODO: check that modification is possible (not all casts are possible) - modified_result.Set(state().add_modification_of( - modified_result.Get(), expr.modifier)); + modified_result.Set( + state().AddModificationOf(modified_result.Get(), expr.modifier)); } return TypeCheckFromArgs(modified_result.Get(), args, current_pos); @@ -510,7 +507,7 @@ Result CheckTask::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::operator()(const nodes::Lambda &expr, for (size_t i = 0; i < expr.args.size(); ++i) { if (not state().InsertVariable(expr.args.at(i).value, - state().add_generic_type(), + state().AddGenericType(), nodes::NameDefinition::Kind::LET)) { // TODO: choose LET / CONST TypeCheckError("Variable is already defined in this context", @@ -580,7 +577,7 @@ Result CheckTask::operator()(const nodes::Extra &, const Args &) { // - return Result(state().primitive(builtin::Type::UNIT)); + return Result(state().Primitive(builtin::Type::UNIT)); } // NOTE: CHECKED @@ -590,7 +587,7 @@ Result CheckTask::operator()(const nodes::EmptyLines &, // - return Result(state().primitive(builtin::Type::UNIT)); + return Result(state().Primitive(builtin::Type::UNIT)); } } // namespace type_check diff --git a/lang/type_check/src/type_check_utils.cpp b/lang/type_check/src/type_check_utils.cpp index 1b837ce..850aab1 100644 --- a/lang/type_check/src/type_check_utils.cpp +++ b/lang/type_check/src/type_check_utils.cpp @@ -20,7 +20,7 @@ nodes::Type CheckSameToPassTypeInArgs(nodes::Type type, const Args &args, logc.Error({{message}} /* TODO: node */); } - return executor.state().primitive(builtin::Type::BOOL); + return executor.state().Primitive(builtin::Type::BOOL); } Result CheckTypeSameToExpected(nodes::Type type, const Args &args, @@ -99,8 +99,8 @@ std::optional 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 UnfoldUserDefinedType(nodes::Type type, if (handle_errors) { logc.Error({{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(type.get()->parameters_size() == 0, + logc.Require(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( {{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; }