lang_2023/include/types.hpp
2023-05-23 11:54:15 +03:00

405 lines
12 KiB
C++

#pragma once
#include <optional>
#include <string>
#include <variant>
#include <memory>
#include <unordered_set>
#include <unordered_map>
// for clangd
#include "error_handling.hpp"
#include "typeclass_graph.hpp"
#include "utils.hpp"
namespace info::type {
// TODO: move in constructors
class TypeManager;
class AbstractType { // latter will be found in context
public:
AbstractType(utils::AbstractTypeModifier modifier,
utils::IdType graph_id,
info::TypeclassGraph& typeclass_graph)
: modifier_(modifier),
graph_id_(graph_id),
typeclass_graph_(typeclass_graph) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const AbstractType& type) const;
bool operator<(const AbstractType& type) const;
bool operator>(const AbstractType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
utils::IdType GetGraphId() {
return graph_id_;
}
bool HasTypeclass(utils::IdType graph_id) { // TODO: cache dependencies set
return graph_id == graph_id_ || typeclass_graph_.GetDependenciesSet(graph_id_).count(graph_id) != 0;
}
std::string ToString() const {
return "Abstract " + std::to_string(graph_id_);
}
private:
utils::AbstractTypeModifier modifier_;
utils::IdType graph_id_;
info::TypeclassGraph& typeclass_graph_;
};
class DefinedType {
public:
DefinedType() = default;
DefinedType(utils::IdType type_id,
utils::IdType type,
utils::ClassModifier class_modifier,
TypeManager* type_manager)
: type_id_(type_id), type_(type), class_modifier_(class_modifier), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const DefinedType& type) const;
bool operator<(const DefinedType& type) const;
bool operator>(const DefinedType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
utils::IdType GetTypeId() const {
return type_id_;
}
utils::IdType GetType() const {
return type_;
}
utils::ClassModifier GetClassModifier() const {
return class_modifier_;
}
std::string ToString() const {
return "Defined";
}
private:
utils::IdType type_id_; // in defined types
utils::IdType type_; // in types manager, created using context types (if specific type)
utils::ClassModifier class_modifier_;
TypeManager* type_manager_ = nullptr;
};
const size_t InternalTypesCount = 6;
enum class InternalType {
Float = 0,
Int = 1,
String = 2,
Char = 3,
Bool = 4,
Unit = 5,
};
inline std::optional<InternalType> ToInternalType(const std::string& type) {
if (type.empty()) {
return std::nullopt;
}
switch (type[0]) {
case 'F':
if (type == "Float") { return InternalType::Float; }
break;
case 'I':
if (type == "Int") { return InternalType::Int; }
break;
case 'S':
if (type == "String") { return InternalType::String; }
break;
case 'C':
if (type == "Char") { return InternalType::Char; }
break;
case 'B':
if (type == "Bool") { return InternalType::Bool; }
break;
case 'U':
if (type == "Unit") { return InternalType::Unit; }
break;
default:
break;
}
return std::nullopt;
}
inline std::string ToString(InternalType type) {
std::string result;
switch (type) {
case InternalType::Float:
result = "Float";
break;
case InternalType::Int:
result = "Int";
break;
case InternalType::String:
result = "String";
break;
case InternalType::Char:
result = "Char";
break;
case InternalType::Bool:
result = "Bool";
break;
case InternalType::Unit:
result = "Unit";
break;
}
return result;
}
class TupleType {
public:
TupleType() = default;
TupleType(const std::optional<std::string>& name,
const std::vector<std::pair<std::optional<std::string>, utils::IdType>>& fields,
TypeManager* type_manager)
: name_(name), fields_(fields), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const TupleType& type) const;
bool operator<(const TupleType& type) const;
bool operator>(const TupleType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
const std::vector<std::pair<std::optional<std::string>, utils::IdType>>& GetFields() const {
return fields_;
}
std::string ToString() const;
private:
std::optional<std::string> name_;
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields_;
TypeManager* type_manager_ = nullptr;
};
class VariantType {
public:
VariantType() = default;
VariantType(const std::optional<std::string>& name,
const std::vector<TupleType>& constructors,
std::optional<size_t> current_constructor)
: name_(name), constructors_(constructors), current_constructor_(current_constructor) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const VariantType& type) const;
bool operator<(const VariantType& type) const;
bool operator>(const VariantType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
const std::vector<TupleType>& GetConstructors() const {
return constructors_;
}
void SetCurrentConstructor(size_t constructor) {
current_constructor_ = constructor;
}
std::string ToString() const;
private:
std::optional<std::string> name_;
std::vector<TupleType> constructors_;
std::optional<size_t> current_constructor_;
};
class OptionalType {
public:
OptionalType() = default;
OptionalType(utils::IdType type,
TypeManager* type_manager)
: type_(type), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const OptionalType& type) const;
bool operator<(const OptionalType& type) const;
bool operator>(const OptionalType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
std::string ToString() const;
private:
utils::IdType type_;
TypeManager* type_manager_ = nullptr;
};
class ReferenceToType {
public:
ReferenceToType() = default;
ReferenceToType(const std::vector<utils::ReferenceModifier>& references,
utils::IdType type,
TypeManager* type_manager)
: references_(references), type_(type), type_manager_(type_manager) {
if (references.empty()) {
error_handling::HandleInternalError("ReferenceToType with 0 references", "Type.ReferenceToType", std::nullopt);
}
}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const ReferenceToType& type) const;
bool operator<(const ReferenceToType& type) const;
bool operator>(const ReferenceToType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
std::string ToString() const;
private:
std::vector<utils::ReferenceModifier> references_;
utils::IdType type_;
TypeManager* type_manager_ = nullptr;
};
/////////////////////////////
class FunctionType {
public:
FunctionType() = default;
FunctionType(const std::vector<utils::IdType>& argument_types,
utils::IdType return_type,
TypeManager* type_manager)
: argument_types_(argument_types), return_type_(return_type), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const FunctionType& type) const;
bool operator<(const FunctionType& type) const;
bool operator>(const FunctionType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
std::string ToString() const;
private:
std::vector<utils::IdType> 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<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const ArrayType& type) const;
bool operator<(const ArrayType& type) const;
bool operator>(const ArrayType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
utils::IdType GetElementsType() {
return elements_type_;
}
std::string ToString() const;
private:
size_t size_; // = 0 for dynamic
utils::IdType elements_type_;
TypeManager* type_manager_ = nullptr;
};
class Type {
public:
template<typename T>
explicit Type(const T& type) : type_(type) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const Type& type) const;
bool operator<(const Type& type) const; // TODO: rule exceptions
bool operator>(const Type& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
std::string GetTypeName() const;
std::variant<AbstractType,
DefinedType,
InternalType,
TupleType,
VariantType,
ReferenceToType,
FunctionType,
ArrayType,
OptionalType>& GetType() {
return type_;
}
std::string ToString() const;
private:
std::variant<AbstractType,
DefinedType,
InternalType,
TupleType,
VariantType,
ReferenceToType,
FunctionType,
ArrayType,
OptionalType> type_;
};
class TypeManager {
public:
template<typename T>
utils::IdType AddValue(const T& type, utils::ValueType value_type) {
types_.push_back(std::pair<Type, utils::ValueType> {type, value_type});
return types_.size() - 1;
}
utils::IdType AddAnyValue(Type&& type, utils::ValueType value_type) {
types_.push_back(std::pair<Type, utils::ValueType> {std::move(type), value_type});
return types_.size() - 1;
}
template<typename T>
std::optional<T*> GetValue(utils::IdType type_id) {
if (!std::holds_alternative<T>(types_.at(type_id).first.GetType())) {
return std::nullopt;
}
return &std::get<T>(types_.at(type_id).first.GetType());
}
Type* GetAnyValue(utils::IdType type_id) {
return &types_.at(type_id).first;
}
utils::ValueType GetValueType(utils::IdType type_id) {
return types_.at(type_id).second;
}
void SetValueType(utils::IdType type_id, utils::ValueType value_type) {
types_.at(type_id).second = value_type;
}
bool EqualValues(utils::IdType first_type, utils::IdType second_type) {
return GetAnyValue(first_type)->Same(*GetAnyValue(second_type));
}
bool AddValueRequirement(utils::IdType type, utils::IdType requrement) {
return *GetAnyValue(requrement) < *GetAnyValue(type);
}
private:
std::vector<std::pair<Type, utils::ValueType>> types_;
};
} // namespace info::type