diff options
author | Mark Wielaard <mark@klomp.org> | 2021-10-30 15:59:01 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-11-01 13:12:48 +0000 |
commit | d18672f220ba9377d8f86fb228b7142e98b23a44 (patch) | |
tree | 02b816d5ae2affa2eb98e093a4c46975152b9e9b /gcc | |
parent | faa1a005e92237a0188311b48455be88126e3e68 (diff) | |
download | gcc-d18672f220ba9377d8f86fb228b7142e98b23a44.zip gcc-d18672f220ba9377d8f86fb228b7142e98b23a44.tar.gz gcc-d18672f220ba9377d8f86fb228b7142e98b23a44.tar.bz2 |
Add type-resolution for enum items
This patch does the type resolution to actually create the types when we
encounter enums within toplevel HIR::Items and HIR::Stmt conext's.
We don't support actual creation of enums yet in this patch but this is
an isolated building block.
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Addresses #79
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-enumitem.h | 149 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-stmt.h | 53 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 52 |
3 files changed, 254 insertions, 0 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-enumitem.h b/gcc/rust/typecheck/rust-hir-type-check-enumitem.h new file mode 100644 index 0000000..1ab07b3 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-enumitem.h @@ -0,0 +1,149 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_ENUMITEM +#define RUST_HIR_TYPE_CHECK_ENUMITEM + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-type.h" +#include "rust-hir-type-check-expr.h" + +extern ::Backend * +rust_get_backend (); + +namespace Rust { +namespace Resolver { + +class TypeCheckEnumItem : public TypeCheckBase +{ + using Rust::Resolver::TypeCheckBase::visit; + +public: + static TyTy::VariantDef *Resolve (HIR::EnumItem *item, + int64_t last_discriminant) + { + TypeCheckEnumItem resolver (last_discriminant); + item->accept_vis (resolver); + return resolver.variant; + } + + void visit (HIR::EnumItem &item) override + { + if (last_discriminant == INT64_MAX) + rust_error_at (item.get_locus (), "discriminant too big"); + + variant + = new TyTy::VariantDef (item.get_identifier (), last_discriminant + 1); + } + + void visit (HIR::EnumItemDiscriminant &item) override + { + if (last_discriminant == INT64_MAX) + rust_error_at (item.get_locus (), "discriminant too big"); + + auto &discriminant = item.get_discriminant_expression (); + auto capacity_type = TypeCheckExpr::Resolve (discriminant.get (), false); + if (capacity_type->get_kind () == TyTy::TypeKind::ERROR) + return; + + TyTy::USizeType *expected_ty + = new TyTy::USizeType (discriminant->get_mappings ().get_hirid ()); + context->insert_type (discriminant->get_mappings (), expected_ty); + + auto unified = expected_ty->unify (capacity_type); + if (unified->get_kind () == TyTy::TypeKind::ERROR) + return; + + auto backend = rust_get_backend (); + auto folded_discriminant + = ConstFold::ConstFoldExpr::fold (discriminant.get ()); + if (folded_discriminant == nullptr + || backend->is_error_expression (folded_discriminant)) + return; + + size_t specified_discriminant; + bool ok + = backend->const_size_cast (folded_discriminant, &specified_discriminant); + rust_assert (ok); + + variant + = new TyTy::VariantDef (item.get_identifier (), specified_discriminant); + } + + void visit (HIR::EnumItemTuple &item) override + { + if (last_discriminant == INT64_MAX) + rust_error_at (item.get_locus (), "discriminant too big"); + + std::vector<TyTy::StructFieldType *> fields; + size_t idx = 0; + for (auto &field : item.get_tuple_fields ()) + { + TyTy::BaseType *field_type + = TypeCheckType::Resolve (field.get_field_type ().get ()); + TyTy::StructFieldType *ty_field + = new TyTy::StructFieldType (field.get_mappings ().get_hirid (), + std::to_string (idx), field_type); + fields.push_back (ty_field); + context->insert_type (field.get_mappings (), + ty_field->get_field_type ()); + idx++; + } + + variant + = new TyTy::VariantDef (item.get_identifier (), + TyTy::VariantDef::VariantType::TUPLE, fields); + } + + void visit (HIR::EnumItemStruct &item) override + { + if (last_discriminant == INT64_MAX) + rust_error_at (item.get_locus (), "discriminant too big"); + + std::vector<TyTy::StructFieldType *> fields; + for (auto &field : item.get_struct_fields ()) + { + TyTy::BaseType *field_type + = TypeCheckType::Resolve (field.get_field_type ().get ()); + TyTy::StructFieldType *ty_field + = new TyTy::StructFieldType (field.get_mappings ().get_hirid (), + field.get_field_name (), field_type); + fields.push_back (ty_field); + context->insert_type (field.get_mappings (), + ty_field->get_field_type ()); + } + + variant + = new TyTy::VariantDef (item.get_identifier (), + TyTy::VariantDef::VariantType::STRUCT, fields); + } + +private: + TypeCheckEnumItem (int64_t last_discriminant) + : TypeCheckBase (), variant (nullptr), last_discriminant (last_discriminant) + {} + + TyTy::VariantDef *variant; + int64_t last_discriminant; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_ENUMITEM diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index 2195968..7f98c46 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -23,6 +23,7 @@ #include "rust-hir-full.h" #include "rust-hir-type-check-type.h" #include "rust-hir-type-check-expr.h" +#include "rust-hir-type-check-enumitem.h" namespace Rust { namespace Resolver { @@ -187,6 +188,58 @@ public: infered = type; } + void visit (HIR::Enum &enum_decl) override + { + std::vector<TyTy::SubstitutionParamMapping> substitutions; + if (enum_decl.has_generics ()) + { + for (auto &generic_param : enum_decl.get_generic_params ()) + { + switch (generic_param.get ()->get_kind ()) + { + case HIR::GenericParam::GenericKind::LIFETIME: + // Skipping Lifetime completely until better handling. + break; + + case HIR::GenericParam::GenericKind::TYPE: { + auto param_type + = TypeResolveGenericParam::Resolve (generic_param.get ()); + context->insert_type (generic_param->get_mappings (), + param_type); + + substitutions.push_back (TyTy::SubstitutionParamMapping ( + static_cast<HIR::TypeParam &> (*generic_param), + param_type)); + } + break; + } + } + } + + std::vector<TyTy::VariantDef *> variants; + int64_t discriminant_value = 0; + for (auto &variant : enum_decl.get_variants ()) + { + TyTy::VariantDef *field_type + = TypeCheckEnumItem::Resolve (variant.get (), discriminant_value); + + variants.push_back (field_type); + if (field_type->get_variant_type () + == TyTy::VariantDef::VariantType::NUM) + discriminant_value = field_type->get_discriminant (); + } + + TyTy::BaseType *type + = new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (), + mappings->get_next_hir_id (), + enum_decl.get_identifier (), + TyTy::ADTType::ADTKind::ENUM, std::move (variants), + std::move (substitutions)); + + context->insert_type (enum_decl.get_mappings (), type); + infered = type; + } + void visit (HIR::StructStruct &struct_decl) override { std::vector<TyTy::SubstitutionParamMapping> substitutions; diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 4dae953..98f037e 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -24,6 +24,7 @@ #include "rust-hir-type-check-implitem.h" #include "rust-hir-type-check-type.h" #include "rust-hir-type-check-expr.h" +#include "rust-hir-type-check-enumitem.h" #include "rust-tyty.h" namespace Rust { @@ -188,6 +189,57 @@ public: context->insert_type (struct_decl.get_mappings (), type); } + void visit (HIR::Enum &enum_decl) override + { + std::vector<TyTy::SubstitutionParamMapping> substitutions; + if (enum_decl.has_generics ()) + { + for (auto &generic_param : enum_decl.get_generic_params ()) + { + switch (generic_param.get ()->get_kind ()) + { + case HIR::GenericParam::GenericKind::LIFETIME: + // Skipping Lifetime completely until better handling. + break; + + case HIR::GenericParam::GenericKind::TYPE: { + auto param_type + = TypeResolveGenericParam::Resolve (generic_param.get ()); + context->insert_type (generic_param->get_mappings (), + param_type); + + substitutions.push_back (TyTy::SubstitutionParamMapping ( + static_cast<HIR::TypeParam &> (*generic_param), + param_type)); + } + break; + } + } + } + + std::vector<TyTy::VariantDef *> variants; + int64_t discriminant_value = 0; + for (auto &variant : enum_decl.get_variants ()) + { + TyTy::VariantDef *field_type + = TypeCheckEnumItem::Resolve (variant.get (), discriminant_value); + + variants.push_back (field_type); + if (field_type->get_variant_type () + == TyTy::VariantDef::VariantType::NUM) + discriminant_value = field_type->get_discriminant (); + } + + TyTy::BaseType *type + = new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (), + mappings->get_next_hir_id (), + enum_decl.get_identifier (), + TyTy::ADTType::ADTKind::ENUM, std::move (variants), + std::move (substitutions)); + + context->insert_type (enum_decl.get_mappings (), type); + } + void visit (HIR::Union &union_decl) override { std::vector<TyTy::SubstitutionParamMapping> substitutions; |