lang_2023/src/types.cpp
2023-07-07 22:53:14 +03:00

733 lines
24 KiB
C++

// for clangd
#include "../include/types.hpp"
#include <string>
#include <variant>
namespace info::type {
std::optional<utils::IdType> AbstractType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
auto type_iter = context.find(typeclass_graph_.GetVertex(graph_id_).name);
if (type_iter != context.end()) {
return type_iter->second;
}
return std::nullopt;
}
bool AbstractType::Same(const AbstractType& type) const {
return graph_id_ == type.graph_id_;
}
bool AbstractType::Require(const AbstractType& type) const { // TODO: cache DependenciesSet
return typeclass_graph_.GetDependenciesSet(graph_id_).count(type.graph_id_) != 0 || graph_id_ == type.graph_id_;
}
bool AbstractType::DeduceContext(const AbstractType& actual_type,
std::unordered_map<std::string, std::optional<utils::IdType>>& context,
TypeManager& type_manager) const {
return typeclass_graph_.GetDependenciesSet(graph_id_).count(actual_type.graph_id_) != 0 || graph_id_ == actual_type.graph_id_;
}
std::optional<utils::IdType> AbstractType::GetFieldType(const std::string&,
const std::unordered_set<utils::IdType>&) const {
return std::nullopt;
}
//
std::optional<utils::IdType> DefinedType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
std::optional<utils::IdType> maybe_type_replacement = type_manager_->GetAnyValue(type_)->InContext(context);
if (maybe_type_replacement.has_value()) {
type_ = maybe_type_replacement.value();
}
return std::nullopt;
}
bool DefinedType::Same(const DefinedType& type) const {
return type_id_ == type.type_id_
&& type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_));
}
bool DefinedType::Require(const DefinedType& type) const {
return type_id_ == type.type_id_
&& type_manager_->GetAnyValue(type_)->Require(*type_manager_->GetAnyValue(type.type_));
}
bool DefinedType::DeduceContext(const DefinedType& actual_type,
std::unordered_map<std::string, std::optional<utils::IdType>>& context,
TypeManager& type_manager) const {
return type_id_ == actual_type.type_id_
&& type_manager_->GetAnyValue(type_)->DeduceContext(*type_manager_->GetAnyValue(actual_type.type_), context, type_manager);
}
std::optional<utils::IdType> DefinedType::GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const {
if (class_modifier_ == utils::ClassModifier::Struct || type_namespaces.count(type_id_) != 0) {
return type_manager_->GetAnyValue(type_)->GetFieldType(name, type_namespaces);
}
return std::nullopt;
}
std::string DefinedType::ToString() const {
return "Defined " + std::to_string(type_id_) + " ( " + type_manager_->GetAnyValue(type_)->ToString() + " )";
}
//
std::optional<utils::IdType> TupleType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
for (size_t i = 0; i < fields_.size(); ++i) {
std::optional<utils::IdType> maybe_field_replacement = type_manager_->GetAnyValue(fields_[i].second)->InContext(context);
if (maybe_field_replacement.has_value()) {
fields_[i].second = maybe_field_replacement.value();
}
}
return std::nullopt;
}
bool TupleType::Same(const TupleType& type) const {
if (fields_.size() != type.fields_.size()) {
return false;
}
for (size_t i = 0; i < fields_.size(); ++i) {
if (!type_manager_->GetAnyValue(fields_[i].second)->Same(*type_manager_->GetAnyValue(type.fields_[i].second))) {
return false;
}
}
return true;
}
bool TupleType::Require(const TupleType& type) const {
if (fields_.size() != type.fields_.size()) {
return false;
}
for (size_t i = 0; i < fields_.size(); ++i) {
if (!type_manager_->GetAnyValue(fields_[i].second)->Require(*type_manager_->GetAnyValue(type.fields_[i].second))) {
return false;
}
}
return true;
}
bool TupleType::DeduceContext(const TupleType& actual_type,
std::unordered_map<std::string, std::optional<utils::IdType>>& context,
TypeManager& type_manager) const {
if (fields_.size() != actual_type.fields_.size()) {
return false;
}
for (size_t i = 0; i < fields_.size(); ++i) {
if (!type_manager_->GetAnyValue(fields_[i].second)->DeduceContext(*type_manager_->GetAnyValue(actual_type.fields_[i].second), context, type_manager)) {
return false;
}
}
return true;
}
std::optional<utils::IdType> TupleType::GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>&) const {
for (size_t i = 0; i < fields_.size(); ++i) { // TODO: optimize??
if (fields_[i].first.has_value() && fields_[i].first.value() == name) {
return fields_[i].second;
}
}
return std::nullopt;
}
std::string TupleType::ToString() const {
std::string result;
result += "(";
for (auto& field : fields_) {
result += " & ";
result += type_manager_->GetAnyValue(field.second)->ToString();
}
result += ")";
return result;
}
//
std::optional<utils::IdType> VariantType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
for (size_t i = 0; i < constructors_.size(); ++i) {
if (constructors_[i].second.has_value()) {
constructors_[i].second.value().InContext(context);
}
}
return std::nullopt;
}
bool VariantType::Same(const VariantType& type) const {
if (constructors_.size() != type.constructors_.size()) {
return false;
}
for (size_t i = 0; i < constructors_.size(); ++i) {
if (constructors_[i].first != type.constructors_[i].first) { // TODO: decide
return false;
}
if (constructors_[i].second.has_value() != type.constructors_[i].second.has_value()) {
return false;
}
if (constructors_[i].second.has_value()) {
if (!constructors_[i].second.value().Same(type.constructors_[i].second.value())) {
return false;
}
}
}
return true;
}
bool VariantType::Require(const VariantType& type) const {
if (constructors_.size() != type.constructors_.size()) {
return false;
}
for (size_t i = 0; i < constructors_.size(); ++i) {
if (constructors_[i].first != type.constructors_[i].first) { // TODO: decide
return false;
}
if (constructors_[i].second.has_value() != type.constructors_[i].second.has_value()) {
return false;
}
if (constructors_[i].second.has_value()) {
if (!constructors_[i].second.value().Require(type.constructors_[i].second.value())) {
return false;
}
}
}
return true;
}
bool VariantType::DeduceContext(const VariantType& actual_type,
std::unordered_map<std::string, std::optional<utils::IdType>>& context,
TypeManager& type_manager) const {
if (constructors_.size() != actual_type.constructors_.size()) {
return false;
}
for (size_t i = 0; i < constructors_.size(); ++i) {
if (constructors_[i].first != actual_type.constructors_[i].first) { // TODO: decide
return false;
}
if (constructors_[i].second.has_value() != actual_type.constructors_[i].second.has_value()) {
return false;
}
if (constructors_[i].second.has_value()) {
if (!constructors_[i].second.value().DeduceContext(actual_type.constructors_[i].second.value(), context, type_manager)) {
return false;
}
}
}
return true;
}
std::optional<utils::IdType> VariantType::GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const {
if (current_constructor_.has_value() && constructors_.at(current_constructor_.value()).second.has_value()) {
return constructors_[current_constructor_.value()].second.value().GetFieldType(name, type_namespaces);
}
return std::nullopt;
}
std::string VariantType::ToString() const {
std::string result;
result += "(";
for (auto& constructor : constructors_) {
result += "& ";
result += constructor.first;
if (constructor.second.has_value()) {
result += " " + constructor.second.value().ToString();
}
}
result += ")";
return result;
}
//
std::optional<utils::IdType> OptionalType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
std::optional<utils::IdType> maybe_type_replacement = type_manager_->GetAnyValue(type_)->InContext(context);
if (maybe_type_replacement.has_value()) {
type_ = maybe_type_replacement.value();
}
return std::nullopt;
}
bool OptionalType::Same(const OptionalType& type) const {
return type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_));
}
bool OptionalType::Require(const OptionalType& type) const {
return type_manager_->GetAnyValue(type_)->Require(*type_manager_->GetAnyValue(type.type_));
}
bool OptionalType::DeduceContext(const OptionalType& actual_type,
std::unordered_map<std::string, std::optional<utils::IdType>>& context,
TypeManager& type_manager) const {
return type_manager_->GetAnyValue(type_)->DeduceContext(*type_manager_->GetAnyValue(actual_type.type_), context, type_manager);
}
std::optional<utils::IdType> OptionalType::GetFieldType(const std::string&,
const std::unordered_set<utils::IdType>&) const {
return std::nullopt;
}
std::string OptionalType::ToString() const {
return "Optional " + type_manager_->GetAnyValue(type_)->ToString();
}
//
std::optional<utils::IdType> ReferenceToType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
std::optional<utils::IdType> maybe_type_replacement = type_manager_->GetAnyValue(type_)->InContext(context);
if (maybe_type_replacement.has_value()) {
type_ = maybe_type_replacement.value();
}
return std::nullopt;
}
bool ReferenceToType::Same(const ReferenceToType& type) const {
return references_ == type.references_ && type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_));
}
bool ReferenceToType::Require(const ReferenceToType& type) const {
return references_ == type.references_ && type_manager_->GetAnyValue(type_)->Require(*type_manager_->GetAnyValue(type.type_));
}
bool ReferenceToType::DeduceContext(const ReferenceToType& actual_type,
std::unordered_map<std::string, std::optional<utils::IdType>>& context,
TypeManager& type_manager) const {
return references_ == actual_type.references_ && type_manager_->GetAnyValue(type_)->DeduceContext(*type_manager_->GetAnyValue(actual_type.type_), context, type_manager);
}
std::optional<utils::IdType> ReferenceToType::GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const {
return type_manager_->GetAnyValue(type_)->GetFieldType(name, type_namespaces);
}
std::string ReferenceToType::ToString() const {
std::string result;
for (auto& reference : references_) {
switch (reference) {
case utils::ReferenceModifier::Dereference:
result += '~';
break;
case utils::ReferenceModifier::Reference:
result += '^';
break;
case utils::ReferenceModifier::UniqueReference:
result += '@';
break;
}
}
result += type_manager_->GetAnyValue(type_)->ToString();
return result;
}
//
std::optional<utils::IdType> FunctionType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
for (size_t i = 0; i < argument_types_.size(); ++i) {
std::optional<utils::IdType> maybe_argument_type_replacement =
type_manager_->GetAnyValue(argument_types_[i])->InContext(context);
if (maybe_argument_type_replacement.has_value()) {
argument_types_[i] = maybe_argument_type_replacement.value();
}
}
return std::nullopt;
}
bool FunctionType::Same(const FunctionType& type) const {
if (argument_types_.size() != type.argument_types_.size()) {
return false;
}
for (size_t i = 0; i < argument_types_.size(); ++i) {
if (!type_manager_->GetAnyValue(argument_types_[i])->Same(*type_manager_->GetAnyValue(type.argument_types_[i]))) {
return false;
}
}
return true;
}
bool FunctionType::Require(const FunctionType& type) const {
if (argument_types_.size() != type.argument_types_.size()) {
return false;
}
for (size_t i = 0; i < argument_types_.size(); ++i) {
if (!type_manager_->GetAnyValue(argument_types_[i])->Require(*type_manager_->GetAnyValue(type.argument_types_[i]))) {
return false;
}
}
return true;
}
bool FunctionType::DeduceContext(const FunctionType& actual_type,
std::unordered_map<std::string, std::optional<utils::IdType>>& context,
TypeManager& type_manager) const {
if (argument_types_.size() != actual_type.argument_types_.size()) {
return false;
}
for (size_t i = 0; i < argument_types_.size(); ++i) {
if (!type_manager_->GetAnyValue(argument_types_[i])->DeduceContext(*type_manager_->GetAnyValue(actual_type.argument_types_[i]), context, type_manager)) {
return false;
}
}
return true;
}
std::optional<utils::IdType> FunctionType::GetFieldType(const std::string&,
const std::unordered_set<utils::IdType>&) const {
return std::nullopt;
}
std::string FunctionType::ToString() const {
std::string result;
result += "(";
bool is_first_argument = true;
for (auto& argument_type : argument_types_) {
if (is_first_argument) {
is_first_argument = false;
} else {
result += " -> ";
}
result += type_manager_->GetAnyValue(argument_type)->ToString();
}
result += " -> " + type_manager_->GetAnyValue(return_type_)->ToString() + ")";
return result;
}
//
std::optional<utils::IdType> ArrayType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
std::optional<utils::IdType> maybe_elements_type_replacement =
type_manager_->GetAnyValue(elements_type_)->InContext(context);
if (maybe_elements_type_replacement.has_value()) {
elements_type_ = maybe_elements_type_replacement.value();
}
return std::nullopt;
}
bool ArrayType::Same(const ArrayType& type) const {
return size_ == type.size_ && type_manager_->GetAnyValue(elements_type_)->Same(*type_manager_->GetAnyValue(type.elements_type_));
}
bool ArrayType::Require(const ArrayType& type) const {
return size_ == type.size_ && type_manager_->GetAnyValue(elements_type_)->Require(*type_manager_->GetAnyValue(type.elements_type_));
}
bool ArrayType::DeduceContext(const ArrayType& actual_type,
std::unordered_map<std::string, std::optional<utils::IdType>>& context,
TypeManager& type_manager) const {
return size_ == actual_type.size_ && type_manager_->GetAnyValue(elements_type_)->DeduceContext(*type_manager_->GetAnyValue(actual_type.elements_type_), context, type_manager);
}
std::optional<utils::IdType> ArrayType::GetFieldType(const std::string&,
const std::unordered_set<utils::IdType>&) const {
return std::nullopt;
}
std::string ArrayType::ToString() const {
return "Array (" + std::to_string(size_) + ") " + type_manager_->GetAnyValue(elements_type_)->ToString();
}
//
std::optional<utils::IdType> Type::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
size_t this_index = type_.index();
switch (this_index) {
case 0:
return std::get<AbstractType>(type_).InContext(context);
case 1:
return std::get<DefinedType>(type_).InContext(context);
case 2:
return std::nullopt;
case 3:
return std::get<TupleType>(type_).InContext(context);
case 4:
return std::get<VariantType>(type_).InContext(context);
case 5:
return std::get<ReferenceToType>(type_).InContext(context);
case 6:
return std::get<FunctionType>(type_).InContext(context);
case 7:
return std::get<ArrayType>(type_).InContext(context);
case 8:
return std::get<OptionalType>(type_).InContext(context);
default:
// error
break;
}
return std::nullopt;
}
bool Type::Same(const Type& type) const {
size_t this_index = type_.index();
size_t type_index = type.type_.index();
if (this_index == type_index) {
switch (this_index) {
case 0:
return std::get<AbstractType>(type_).Same(std::get<AbstractType>(type.type_));
case 1:
return std::get<DefinedType>(type_).Same(std::get<DefinedType>(type.type_));
case 2:
return std::get<InternalType>(type_) == std::get<InternalType>(type.type_);
case 3:
return std::get<TupleType>(type_).Same(std::get<TupleType>(type.type_));
case 4:
return std::get<VariantType>(type_).Same(std::get<VariantType>(type.type_));
case 5:
return std::get<ReferenceToType>(type_).Same(std::get<ReferenceToType>(type.type_));
case 6:
return std::get<FunctionType>(type_).Same(std::get<FunctionType>(type.type_));
case 7:
return std::get<ArrayType>(type_).Same(std::get<ArrayType>(type.type_));
case 8:
return std::get<OptionalType>(type_).Same(std::get<OptionalType>(type.type_));
default:
// error
break;
}
}
return false;
}
bool Type::Require(const Type& type) const { // TODO: check abstract type requirements for not abstract types
size_t this_index = type_.index();
size_t type_index = type.type_.index();
if (this_index == type_index) {
switch (this_index) {
case 0:
return std::get<AbstractType>(type_).Require(std::get<AbstractType>(type.type_));
case 1:
return std::get<DefinedType>(type_).Require(std::get<DefinedType>(type.type_));
case 2:
return std::get<InternalType>(type_) == std::get<InternalType>(type.type_);
case 3:
return std::get<TupleType>(type_).Require(std::get<TupleType>(type.type_));
case 4:
return std::get<VariantType>(type_).Require(std::get<VariantType>(type.type_));
case 5:
return std::get<ReferenceToType>(type_).Require(std::get<ReferenceToType>(type.type_));
case 6:
return std::get<FunctionType>(type_).Require(std::get<FunctionType>(type.type_));
case 7:
return std::get<ArrayType>(type_).Require(std::get<ArrayType>(type.type_));
case 8:
return std::get<OptionalType>(type_).Require(std::get<OptionalType>(type.type_));
default:
// error
break;
}
}
return false;
}
// TODO: check abstract type requirements for not abstract types
bool Type::DeduceContext(const Type& actual_type,
std::unordered_map<std::string, std::optional<utils::IdType>>& context,
TypeManager& type_manager) const {
size_t this_index = type_.index();
size_t type_index = actual_type.type_.index();
if (this_index == 0) {
std::string type_name = std::get<AbstractType>(type_).GetName();
if (context.count(type_name) != 0) { // is abstract type
context[type_name] = type_manager.AddAnyValue(Type(actual_type), utils::ValueType::Tmp);
// TODO: choose value type ?? (or should be set later ??)
}
}
error_handling::HandleGeneralError("Type::DeduceContext: not implemented");
if (this_index == type_index) {
switch (this_index) {
case 0:
return std::get<AbstractType>(type_).DeduceContext(std::get<AbstractType>(actual_type.type_),
context,
type_manager);
case 1:
return std::get<DefinedType>(type_).DeduceContext(std::get<DefinedType>(actual_type.type_),
context,
type_manager);
case 2:
return std::get<InternalType>(type_) == std::get<InternalType>(actual_type.type_);
case 3:
return std::get<TupleType>(type_).DeduceContext(std::get<TupleType>(actual_type.type_),
context,
type_manager);
case 4:
return std::get<VariantType>(type_).DeduceContext(std::get<VariantType>(actual_type.type_),
context,
type_manager);
case 5:
return std::get<ReferenceToType>(type_).DeduceContext(std::get<ReferenceToType>(actual_type.type_),
context,
type_manager);
case 6:
return std::get<FunctionType>(type_).DeduceContext(std::get<FunctionType>(actual_type.type_),
context,
type_manager);
case 7:
return std::get<ArrayType>(type_).DeduceContext(std::get<ArrayType>(actual_type.type_),
context,
type_manager);
case 8:
return std::get<OptionalType>(type_).DeduceContext(std::get<OptionalType>(actual_type.type_),
context,
type_manager);
default:
// error
break;
}
}
return false;
}
std::optional<utils::IdType> Type::GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const {
size_t index = type_.index();
switch (index) {
case 0:
return std::get<AbstractType>(type_).GetFieldType(name, type_namespaces);
case 1:
return std::get<DefinedType>(type_).GetFieldType(name, type_namespaces);
case 2:
return std::nullopt;
case 3:
return std::get<TupleType>(type_).GetFieldType(name, type_namespaces);
case 4:
return std::get<VariantType>(type_).GetFieldType(name, type_namespaces);
case 5:
return std::get<ReferenceToType>(type_).GetFieldType(name, type_namespaces);
case 6:
return std::get<FunctionType>(type_).GetFieldType(name, type_namespaces);
case 7:
return std::get<ArrayType>(type_).GetFieldType(name, type_namespaces);
case 8:
return std::get<OptionalType>(type_).GetFieldType(name, type_namespaces);
default:
// error
break;
}
return std::nullopt;
}
std::string Type::GetTypeName() const {
size_t index = type_.index();
switch (index) {
case 0:
return "AbstractType";
case 1:
return "DefinedType";
case 2:
return "Builtin";
case 3:
return "TupleType";
case 4:
return "VariantType";
case 5:
return "ReferenceToType";
case 6:
return "FunctionType";
case 7:
return "ArrayType";
case 8:
return "OptionalType";
default:
// error
break;
}
return ""; // ??
}
std::string Type::ToString() const {
size_t index = type_.index();
switch (index) {
case 0:
return std::get<AbstractType>(type_).ToString();
case 1:
return std::get<DefinedType>(type_).ToString();
case 2: // ??
return ::info::type::ToString(std::get<InternalType>(type_));
case 3:
return std::get<TupleType>(type_).ToString();
case 4:
return std::get<VariantType>(type_).ToString();
case 5:
return std::get<ReferenceToType>(type_).ToString();
case 6:
return std::get<FunctionType>(type_).ToString();
case 7:
return std::get<ArrayType>(type_).ToString();
case 8:
return std::get<OptionalType>(type_).ToString();
default:
// error
break;
}
return "";
}
} // namespace info::type