#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(T&& type) : type_(std::forward(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; private: std::variant type_; }; class TypeManager { public: template utils::IdType AddType(T&& type, utils::ValueType value_type); utils::IdType AddAnyType(Type&& type, utils::ValueType value_type); template std::optional GetType(utils::IdType type_id); Type* GetAnyType(utils::IdType type_id); utils::ValueType GetValueType(utils::IdType type_id); bool AddTypeRequirement(utils::IdType type, utils::IdType requrement); bool EqualTypes(utils::IdType first_type, utils::IdType second_type); private: std::vector> types_; }; } // namespace info::type