#pragma once #include #include #include #include #include #include // for clangd #include "utils.hpp" namespace info::type { // TODO: move in constructors class TypeManager; class AbstractType { // later will be found in context public: AbstractType() = default; AbstractType(utils::AbstractTypeModifier modifier, const std::string& name, const std::vector& requirements) : modifier_(modifier), name_(name) { for (auto& typeclass : requirements) { requirements_.insert(typeclass); } } std::optional InContext(const std::unordered_map& context); bool Same(const AbstractType& type) const; bool operator<(const AbstractType& type) const; bool operator>(const AbstractType& type) const; std::optional GetFieldType(const std::string& name) const; private: utils::AbstractTypeModifier modifier_; std::string name_; std::unordered_set requirements_; // TODO: all typeclasses from tree }; class DefinedType { public: DefinedType() = default; DefinedType(utils::IdType type_id, utils::IdType type, TypeManager* type_manager) : type_id_(type_id), type_(type), type_manager_(type_manager) {} std::optional InContext(const std::unordered_map& context); bool Same(const DefinedType& type) const; bool operator<(const DefinedType& type) const; bool operator>(const DefinedType& type) const; std::optional GetFieldType(const std::string& name) const; utils::IdType GetTypeId() const { return type_id_; } utils::IdType GetType() const { return type_; } private: utils::IdType type_id_; // in defined types utils::IdType type_; // in types manager, created using context types (if specific type) TypeManager* type_manager_ = nullptr; }; enum class InternalType { Float = 0, Int = 1, String = 2, Char = 3, Bool = 4, Unit = 5, }; class TupleType { public: TupleType() = default; TupleType(const std::optional& name, const std::vector, utils::IdType>>& fields, TypeManager* type_manager) : name_(name), fields_(fields), type_manager_(type_manager) {} std::optional InContext(const std::unordered_map& context); bool Same(const TupleType& type) const; bool operator<(const TupleType& type) const; bool operator>(const TupleType& type) const; std::optional GetFieldType(const std::string& name) const; const std::vector, utils::IdType>>& GetFields() const { return fields_; } private: std::optional name_; std::vector, utils::IdType>> fields_; TypeManager* type_manager_ = nullptr; }; class VariantType { public: VariantType() = default; VariantType(const std::optional& name, const std::vector& constructors, std::optional current_constructor) : name_(name), constructors_(constructors), current_constructor_(current_constructor) {} std::optional InContext(const std::unordered_map& context); bool Same(const VariantType& type) const; bool operator<(const VariantType& type) const; bool operator>(const VariantType& type) const; std::optional GetFieldType(const std::string& name) const; const std::vector& GetConstructors() const { return constructors_; } const void SetCurrentConstructor(size_t constructor) { current_constructor_ = constructor; } private: std::optional name_; std::vector constructors_; std::optional current_constructor_; }; class OptionalType { public: OptionalType() = default; OptionalType(utils::IdType type, TypeManager* type_manager) : type_(type), type_manager_(type_manager) {} std::optional InContext(const std::unordered_map& context); bool Same(const OptionalType& type) const; bool operator<(const OptionalType& type) const; bool operator>(const OptionalType& type) const; std::optional GetFieldType(const std::string& name) const; private: utils::IdType type_; TypeManager* type_manager_ = nullptr; }; class ReferenceToType { public: ReferenceToType() = default; ReferenceToType(const std::vector& references, utils::IdType type, TypeManager* type_manager) : references_(references), type_(type), type_manager_(type_manager) {} std::optional InContext(const std::unordered_map& context); bool Same(const ReferenceToType& type) const; bool operator<(const ReferenceToType& type) const; bool operator>(const ReferenceToType& type) const; std::optional GetFieldType(const std::string& name) const; private: std::vector references_; utils::IdType type_; TypeManager* type_manager_ = nullptr; }; ///////////////////////////// class FunctionType { public: FunctionType() = default; FunctionType(const std::vector& argument_types, utils::IdType return_type, TypeManager* type_manager) : argument_types_(argument_types), return_type_(return_type), type_manager_(type_manager) {} std::optional InContext(const std::unordered_map& context); bool Same(const FunctionType& type) const; bool operator<(const FunctionType& type) const; bool operator>(const FunctionType& type) const; std::optional GetFieldType(const std::string& name) const; private: std::vector argument_types_; utils::IdType return_type_; TypeManager* type_manager_ = nullptr; }; class ArrayType { public: ArrayType() = default; ArrayType(size_t size, utils::IdType elements_type, TypeManager* type_manager) : size_(size), elements_type_(elements_type), type_manager_(type_manager) {} std::optional InContext(const std::unordered_map& context); bool Same(const ArrayType& type) const; bool operator<(const ArrayType& type) const; bool operator>(const ArrayType& type) const; std::optional GetFieldType(const std::string& name) const; utils::IdType GetElementsType() { return elements_type_; } private: size_t size_; // = 0 for dynamic utils::IdType elements_type_; TypeManager* type_manager_ = nullptr; }; class Type { public: Type() = default; template explicit Type(const T& type) : type_(type) {} std::optional InContext(const std::unordered_map& context); bool Same(const Type& type) const; bool operator<(const Type& type) const; // TODO: rule exceptions bool operator>(const Type& type) const; std::optional GetFieldType(const std::string& name) const; std::string GetTypeName() const; std::variant& GetType() { return type_; } private: std::variant type_; }; class TypeManager { public: template utils::IdType AddType(const T& type, utils::ValueType value_type) { types_.push_back(std::pair {type, value_type}); return types_.size() - 1; } utils::IdType AddAnyType(Type&& type, utils::ValueType value_type) { types_.push_back(std::pair {std::move(type), value_type}); return types_.size() - 1; } template std::optional GetType(utils::IdType type_id) { if (!std::holds_alternative(types_.at(type_id).first.GetType())) { return std::nullopt; } return &std::get(types_.at(type_id).first.GetType()); } Type* GetAnyType(utils::IdType type_id) { return &types_.at(type_id).first; } utils::ValueType GetValueType(utils::IdType type_id) { return types_.at(type_id).second; } bool EqualTypes(utils::IdType first_type, utils::IdType second_type) { return GetAnyType(first_type)->Same(*GetAnyType(second_type)); } bool AddTypeRequirement(utils::IdType type, utils::IdType requrement) { return *GetAnyType(requrement) < *GetAnyType(type); } private: std::vector> types_; }; } // namespace info::type