diff options
author | Philip Herron <philip.herron@embecosm.com> | 2020-12-30 22:13:41 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2021-01-06 10:01:17 +0000 |
commit | 36ebe9a0380694c8517536eb37c7134f1323a30b (patch) | |
tree | 06901ff25aa5ea093184e0713bd0363735408959 /gcc | |
parent | 467141184aa274126ff7e2a41d08bb621b7a3fdf (diff) | |
download | gcc-36ebe9a0380694c8517536eb37c7134f1323a30b.zip gcc-36ebe9a0380694c8517536eb37c7134f1323a30b.tar.gz gcc-36ebe9a0380694c8517536eb37c7134f1323a30b.tar.bz2 |
This brings structs back in post HIR changes. It supports structs
where no base struct is referenced and the constructor is in order.
Diffstat (limited to 'gcc')
29 files changed, 933 insertions, 88 deletions
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index cc87498..584e210 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1571,9 +1571,16 @@ public: virtual Location get_locus_slow () const = 0; + NodeId get_node_id () const { return node_id; } + protected: // pure virtual clone implementation virtual StructExprField *clone_struct_expr_field_impl () const = 0; + + StructExprField () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + NodeId node_id; }; // Identifier-only variant of StructExprField AST node @@ -1584,7 +1591,8 @@ class StructExprFieldIdentifier : public StructExprField public: StructExprFieldIdentifier (Identifier field_identifier, Location locus) - : field_name (std::move (field_identifier)), locus (locus) + : StructExprField (), field_name (std::move (field_identifier)), + locus (locus) {} std::string as_string () const override { return field_name; } @@ -1611,7 +1619,7 @@ class StructExprFieldWithVal : public StructExprField protected: StructExprFieldWithVal (std::unique_ptr<Expr> field_value) - : value (std::move (field_value)) + : StructExprField (), value (std::move (field_value)) {} // Copy constructor requires clone @@ -1769,6 +1777,15 @@ public: return fields; } + void iterate (std::function<bool (StructExprField *)> cb) + { + for (auto &field : fields) + { + if (!cb (field.get ())) + return; + } + } + StructBase &get_struct_base () { return struct_base; } const StructBase &get_struct_base () const { return struct_base; } diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 1088842..9bd8de4 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1746,6 +1746,8 @@ public: return where_clause; } + Identifier get_identifier () const { return struct_name; } + protected: Struct (Identifier struct_name, std::vector<std::unique_ptr<GenericParam> > generic_params, @@ -1802,6 +1804,8 @@ private: // should this store location info? + NodeId node_id; + public: // Returns whether struct field has any outer attributes. bool has_outer_attributes () const { return !outer_attrs.empty (); } @@ -1877,6 +1881,8 @@ public: } Visibility get_visibility () const { return visibility; } + + NodeId get_node_id () const { return node_id; } }; // Rust struct declaration with true struct type AST node @@ -1922,6 +1928,15 @@ public: std::vector<StructField> &get_fields () { return fields; } const std::vector<StructField> &get_fields () const { return fields; } + void iterate (std::function<bool (StructField &)> cb) + { + for (auto &field : fields) + { + if (!cb (field)) + return; + } + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 288dbda..9f1475a 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -227,6 +227,14 @@ public: void visit (TyTy::FnType &type) override { gcc_unreachable (); } + void visit (TyTy::ADTType &type) override + { + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + void visit (TyTy::ArrayType &type) override { mpz_t ival; diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 871b4ba..7b01e0e 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -23,6 +23,7 @@ #include "rust-compile-tyty.h" #include "rust-compile-resolve-path.h" #include "rust-compile-block.h" +#include "rust-compile-struct-field-expr.h" namespace Rust { namespace Compile { @@ -56,7 +57,7 @@ public: void visit (HIR::CallExpr &expr) { - Bexpression *fn = ResolvePath::Compile (expr.get_fnexpr (), ctx); + Bexpression *fn = ResolvePathRef::Compile (expr.get_fnexpr (), ctx); rust_assert (fn != nullptr); std::vector<Bexpression *> args; @@ -355,6 +356,25 @@ public: ctx->add_statement (block_stmt); } + void visit (HIR::StructExprStructFields &struct_expr) + { + Btype *type + = ResolvePathType::Compile (&struct_expr.get_struct_name (), ctx); + + // this assumes all fields are in order from type resolution and if a base + // struct was specified those fields are filed via accesors + std::vector<Bexpression *> vals; + struct_expr.iterate ([&] (HIR::StructExprField *field) mutable -> bool { + Bexpression *expr = CompileStructExprField::Compile (field, ctx); + vals.push_back (expr); + return true; + }); + + translated + = ctx->get_backend ()->constructor_expression (type, vals, + struct_expr.get_locus ()); + } + private: CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 10bdce0..aa65962 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -39,6 +39,35 @@ public: virtual ~CompileItem () {} + void visit (HIR::StructStruct &struct_decl) + { + std::vector<Backend::Btyped_identifier> fields; + struct_decl.iterate ([&] (HIR::StructField &field) mutable -> bool { + TyTy::TyBase *resolved_type = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (field.get_mappings ().get_hirid (), + &resolved_type); + rust_assert (ok); + + Btype *compiled_field_ty + = TyTyCompile::compile (ctx->get_backend (), resolved_type); + + Backend::Btyped_identifier f (field.field_name, compiled_field_ty, + field.get_locus ()); + fields.push_back (std::move (f)); + return true; + }); + + Btype *struct_type_record = ctx->get_backend ()->struct_type (fields); + Btype *named_struct + = ctx->get_backend ()->named_type (struct_decl.get_identifier (), + struct_type_record, + struct_decl.get_locus ()); + ctx->push_type (named_struct); + ctx->insert_compiled_type (struct_decl.get_mappings ().get_hirid (), + named_struct); + } + void visit (HIR::ConstantItem &constant) { TyTy::TyBase *resolved_type = nullptr; diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index c5c646d..c24005e 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -25,7 +25,7 @@ namespace Rust { namespace Compile { void -ResolvePath::visit (HIR::PathInExpression &expr) +ResolvePathRef::visit (HIR::PathInExpression &expr) { // need to look up the reference for this identifier NodeId ref_node_id; @@ -70,5 +70,33 @@ ResolvePath::visit (HIR::PathInExpression &expr) = ctx->get_backend ()->function_code_expression (fn, expr.get_locus ()); } +void +ResolvePathType::visit (HIR::PathInExpression &expr) +{ + // need to look up the reference for this identifier + NodeId ref_node_id; + if (!ctx->get_resolver ()->lookup_resolved_name ( + expr.get_mappings ().get_nodeid (), &ref_node_id)) + { + rust_fatal_error (expr.get_locus (), "failed to look up resolved name"); + return; + } + + HirId ref; + if (!ctx->get_mappings ()->lookup_node_to_hir ( + expr.get_mappings ().get_crate_num (), ref_node_id, &ref)) + { + rust_fatal_error (expr.get_locus (), "reverse lookup failure"); + return; + } + + // assumes paths are functions for now + if (!ctx->lookup_compiled_types (ref, &resolved)) + { + rust_fatal_error (expr.get_locus (), "forward decl was not compiled"); + return; + } +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h index d8f393d..a5543d2 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.h +++ b/gcc/rust/backend/rust-compile-resolve-path.h @@ -25,27 +25,44 @@ namespace Rust { namespace Compile { -class ResolvePath : public HIRCompileBase +class ResolvePathRef : public HIRCompileBase { public: static Bexpression *Compile (HIR::Expr *expr, Context *ctx) { - ResolvePath resolver (ctx); + ResolvePathRef resolver (ctx); expr->accept_vis (resolver); rust_assert (resolver.resolved != nullptr); return resolver.resolved; } - virtual ~ResolvePath () {} - void visit (HIR::PathInExpression &expr); private: - ResolvePath (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {} + ResolvePathRef (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {} Bexpression *resolved; }; +class ResolvePathType : public HIRCompileBase +{ +public: + static Btype *Compile (HIR::Expr *expr, Context *ctx) + { + ResolvePathType resolver (ctx); + expr->accept_vis (resolver); + rust_assert (resolver.resolved != nullptr); + return resolver.resolved; + } + + void visit (HIR::PathInExpression &expr); + +private: + ResolvePathType (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {} + + Btype *resolved; +}; + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.h b/gcc/rust/backend/rust-compile-struct-field-expr.h new file mode 100644 index 0000000..a394f7a --- /dev/null +++ b/gcc/rust/backend/rust-compile-struct-field-expr.h @@ -0,0 +1,52 @@ +// 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_COMPILE_STRUCT_FIELD_EXPR +#define RUST_COMPILE_STRUCT_FIELD_EXPR + +#include "rust-compile-base.h" +#include "rust-compile-tyty.h" + +namespace Rust { +namespace Compile { + +class CompileStructExprField : public HIRCompileBase +{ +public: + static Bexpression *Compile (HIR::StructExprField *field, Context *ctx) + { + CompileStructExprField compiler (ctx); + field->accept_vis (compiler); + rust_assert (compiler.translated != nullptr); + return compiler.translated; + } + + void visit (HIR::StructExprFieldIdentifierValue &field); + +private: + CompileStructExprField (Context *ctx) + : HIRCompileBase (ctx), translated (nullptr) + {} + + Bexpression *translated; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_STRUCT_FIELD_EXPR diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 02fa3a0..24b45ee 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -19,6 +19,7 @@ #include "rust-compile.h" #include "rust-compile-item.h" #include "rust-compile-expr.h" +#include "rust-compile-struct-field-expr.h" namespace Rust { namespace Compile { @@ -152,5 +153,13 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr) else_block, expr.get_locus ()); } +// rust-compile-struct-field-expr.h + +void +CompileStructExprField::visit (HIR::StructExprFieldIdentifierValue &field) +{ + translated = CompileExpr::Compile (field.get_value (), ctx); +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index a165eaf..6fdb32c 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -22,6 +22,7 @@ #include "rust-diagnostics.h" #include "rust-ast-lower-base.h" #include "rust-ast-lower-block.h" +#include "rust-ast-lower-struct-field-expr.h" namespace Rust { namespace HIR { @@ -62,6 +63,47 @@ private: size_t result; }; // namespace Resolver +class ASTLowerPathInExpression : public ASTLoweringBase +{ +public: + static HIR::PathInExpression *translate (AST::PathInExpression *expr) + { + ASTLowerPathInExpression compiler; + expr->accept_vis (compiler); + rust_assert (compiler.translated); + return compiler.translated; + } + + ~ASTLowerPathInExpression () {} + + void visit (AST::PathInExpression &expr) + { + std::vector<HIR::PathExprSegment> path_segments; + expr.iterate_path_segments ([&] (AST::PathExprSegment &s) mutable -> bool { + rust_assert (s.has_generic_args () == false); // TODO + + HIR::PathIdentSegment is (s.get_ident_segment ().as_string ()); + HIR::PathExprSegment seg (is, s.get_locus ()); + path_segments.push_back (seg); + return true; + }); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::PathInExpression (mapping, std::move (path_segments), + expr.get_locus (), + expr.opening_scope_resolution ()); + } + +private: + ASTLowerPathInExpression () : translated (nullptr) {} + + HIR::PathInExpression *translated; +}; + class ASTLoweringExpr : public ASTLoweringBase { public: @@ -107,24 +149,7 @@ public: void visit (AST::PathInExpression &expr) { - std::vector<HIR::PathExprSegment> path_segments; - expr.iterate_path_segments ([&] (AST::PathExprSegment &s) mutable -> bool { - rust_assert (s.has_generic_args () == false); // TODO - - HIR::PathIdentSegment is (s.get_ident_segment ().as_string ()); - HIR::PathExprSegment seg (is, s.get_locus ()); - path_segments.push_back (seg); - return true; - }); - - auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), - mappings->get_next_hir_id (crate_num), - UNKNOWN_LOCAL_DEFID); - - translated = new HIR::PathInExpression (mapping, std::move (path_segments), - expr.get_locus (), - expr.opening_scope_resolution ()); + translated = ASTLowerPathInExpression::translate (&expr); } void visit (AST::ReturnExpr &expr) @@ -431,6 +456,46 @@ public: expr.get_locus ()); } + void visit (AST::StructExprStructFields &struct_expr) + { + std::vector<HIR::Attribute> inner_attribs; + std::vector<HIR::Attribute> outer_attribs; + + // bit of a hack for now + HIR::PathInExpression *path + = ASTLowerPathInExpression::translate (&struct_expr.get_struct_name ()); + HIR::PathInExpression copied_path (*path); + delete path; + + HIR::StructBase *base = nullptr; + if (struct_expr.has_struct_base ()) + { + HIR::Expr *translated_base = ASTLoweringExpr::translate ( + struct_expr.get_struct_base ().get_base_struct ().get ()); + base + = new HIR::StructBase (std::unique_ptr<HIR::Expr> (translated_base)); + } + + std::vector<std::unique_ptr<HIR::StructExprField> > fields; + struct_expr.iterate ([&] (AST::StructExprField *field) mutable -> bool { + HIR::StructExprField *translated + = ASTLowerStructExprField::translate (field); + fields.push_back (std::unique_ptr<HIR::StructExprField> (translated)); + return true; + }); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::StructExprStructFields (mapping, copied_path, + std::move (fields), + struct_expr.get_locus (), base, + inner_attribs, outer_attribs); + } + private: ASTLoweringExpr () : translated (nullptr), translated_array_elems (nullptr) {} diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 9722390..3ac85aa 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -43,6 +43,57 @@ public: virtual ~ASTLoweringItem () {} + void visit (AST::StructStruct &struct_decl) + { + std::vector<std::unique_ptr<HIR::GenericParam> > generic_params; + std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items; + HIR::WhereClause where_clause (std::move (where_clause_items)); + HIR::Visibility vis = HIR::Visibility::create_public (); + std::vector<HIR::Attribute> outer_attrs; + + bool is_unit = false; + std::vector<HIR::StructField> fields; + struct_decl.iterate ([&] (AST::StructField &field) mutable -> bool { + std::vector<HIR::Attribute> outer_attrs; + HIR::Visibility vis = HIR::Visibility::create_public (); + HIR::Type *type + = ASTLoweringType::translate (field.get_field_type ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, field.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id ( + crate_num)); + + // FIXME + // AST::StructField is missing Location info + Location field_locus; + HIR::StructField translated_field (mapping, field.get_field_name (), + std::unique_ptr<HIR::Type> (type), vis, + field_locus, outer_attrs); + fields.push_back (std::move (translated_field)); + return true; + }); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, struct_decl.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated = new HIR::StructStruct (mapping, std::move (fields), + struct_decl.get_identifier (), + std::move (generic_params), + std::move (where_clause), is_unit, vis, + std::move (outer_attrs), + struct_decl.get_locus ()); + + mappings->insert_defid_mapping (mapping.get_defid (), translated); + mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (), + translated); + mappings->insert_location (crate_num, mapping.get_hirid (), + struct_decl.get_locus ()); + } + void visit (AST::ConstantItem &constant) { std::vector<HIR::Attribute> outer_attrs; diff --git a/gcc/rust/hir/rust-ast-lower-struct-field-expr.h b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h new file mode 100644 index 0000000..1b444a5 --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h @@ -0,0 +1,58 @@ +// 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_AST_LOWER_STRUCT_FIELD_EXPR +#define RUST_AST_LOWER_STRUCT_FIELD_EXPR + +#include "rust-diagnostics.h" +#include "rust-ast-lower-base.h" + +namespace Rust { +namespace HIR { + +class ASTLowerStructExprField : public ASTLoweringBase +{ +public: + static HIR::StructExprField *translate (AST::StructExprField *field) + { + ASTLowerStructExprField compiler; + field->accept_vis (compiler); + rust_assert (compiler.translated != nullptr); + + // compiler.mappings->insert_hir_expr ( + // compiler.translated->get_mappings ().get_crate_num (), + // compiler.translated->get_mappings ().get_hirid (), + // compiler.translated); + + return compiler.translated; + } + + ~ASTLowerStructExprField () {} + + void visit (AST::StructExprFieldIdentifierValue &field); + +private: + ASTLowerStructExprField () : translated (nullptr) {} + + HIR::StructExprField *translated; +}; + +} // namespace HIR +} // namespace Rust + +#endif // RUST_AST_LOWER_STRUCT_FIELD_EXPR diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index 93288c3..8dd8800 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -149,5 +149,22 @@ ASTLoweringIfBlock::visit (AST::IfExprConseqIf &expr) expr.get_locus ()); } +// rust-ast-lower-struct-field-expr.h + +void +ASTLowerStructExprField::visit (AST::StructExprFieldIdentifierValue &field) +{ + HIR::Expr *value = ASTLoweringExpr::translate (field.get_value ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, field.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::StructExprFieldIdentifierValue ( + mapping, field.get_field_name (), std::unique_ptr<HIR::Expr> (value), + field.get_locus ()); +} + } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 1110f98..bf564cd 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -1315,9 +1315,9 @@ protected: // Base struct/tuple/union value creator HIR node (abstract) class StructExpr : public ExprWithoutBlock { +protected: PathInExpression struct_name; -protected: // Protected constructor to allow initialising struct_name StructExpr (Analysis::NodeMapping mappings, PathInExpression struct_path, std::vector<Attribute> outer_attribs) @@ -1326,7 +1326,7 @@ protected: {} public: - const PathInExpression &get_struct_name () const { return struct_name; } + PathInExpression &get_struct_name () { return struct_name; } std::string as_string () const override; }; @@ -1417,6 +1417,8 @@ public: bool is_invalid () const { return base_struct == nullptr; } std::string as_string () const; + + Expr *get_base () { return base_struct.get (); } }; /* Base HIR node for a single struct expression field (in struct instance @@ -1436,9 +1438,20 @@ public: virtual void accept_vis (HIRVisitor &vis) = 0; + Analysis::NodeMapping &get_mappings () { return mappings; } + + Location get_locus () { return locus; } + protected: // pure virtual clone implementation virtual StructExprField *clone_struct_expr_field_impl () const = 0; + + StructExprField (Analysis::NodeMapping mapping, Location locus) + : mappings (mapping), locus (locus) + {} + + Analysis::NodeMapping mappings; + Location locus; }; // Identifier-only variant of StructExprField HIR node @@ -1449,8 +1462,10 @@ public: // TODO: should this store location data? - StructExprFieldIdentifier (Identifier field_identifier) - : field_name (std::move (field_identifier)) + StructExprFieldIdentifier (Analysis::NodeMapping mapping, + Identifier field_identifier, Location locus) + : StructExprField (mapping, locus), + field_name (std::move (field_identifier)) {} std::string as_string () const override { return field_name; } @@ -1470,23 +1485,26 @@ protected: * abstract */ class StructExprFieldWithVal : public StructExprField { -public: std::unique_ptr<Expr> value; protected: - StructExprFieldWithVal (std::unique_ptr<Expr> field_value) - : value (std::move (field_value)) + StructExprFieldWithVal (Analysis::NodeMapping mapping, + std::unique_ptr<Expr> field_value, Location locus) + : StructExprField (mapping, locus), value (std::move (field_value)) {} // Copy constructor requires clone StructExprFieldWithVal (StructExprFieldWithVal const &other) - : value (other.value->clone_expr ()) + : StructExprField (other.mappings, other.locus), + value (other.value->clone_expr ()) {} // Overload assignment operator to clone unique_ptr StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other) { value = other.value->clone_expr (); + mappings = other.mappings; + locus = other.locus; return *this; } @@ -1497,6 +1515,8 @@ protected: public: std::string as_string () const override; + + Expr *get_value () { return value.get (); } }; // Identifier and value variant of StructExprField HIR node @@ -1507,9 +1527,11 @@ public: // TODO: should this store location data? - StructExprFieldIdentifierValue (Identifier field_identifier, - std::unique_ptr<Expr> field_value) - : StructExprFieldWithVal (std::move (field_value)), + StructExprFieldIdentifierValue (Analysis::NodeMapping mapping, + Identifier field_identifier, + std::unique_ptr<Expr> field_value, + Location locus) + : StructExprFieldWithVal (mapping, std::move (field_value), locus), field_name (std::move (field_identifier)) {} @@ -1534,9 +1556,11 @@ public: // TODO: should this store location data? - StructExprFieldIndexValue (TupleIndex tuple_index, - std::unique_ptr<Expr> field_value) - : StructExprFieldWithVal (std::move (field_value)), index (tuple_index) + StructExprFieldIndexValue (Analysis::NodeMapping mapping, + TupleIndex tuple_index, + std::unique_ptr<Expr> field_value, Location locus) + : StructExprFieldWithVal (mapping, std::move (field_value), locus), + index (tuple_index) {} std::string as_string () const override; @@ -1560,31 +1584,24 @@ public: std::vector<std::unique_ptr<StructExprField> > fields; // bool has_struct_base; - StructBase struct_base; + // FIXME make unique_ptr + StructBase *struct_base; std::string as_string () const override; - bool has_struct_base () const { return !struct_base.is_invalid (); } - - /*inline std::vector<std::unique_ptr<StructExprField>> get_fields() - const { return fields; - }*/ - - /*inline StructBase get_struct_base() const { - return has_struct_base ? struct_base : StructBase::error(); - }*/ + bool has_struct_base () const { return struct_base != nullptr; } // Constructor for StructExprStructFields when no struct base is used StructExprStructFields ( Analysis::NodeMapping mappings, PathInExpression struct_path, std::vector<std::unique_ptr<StructExprField> > expr_fields, Location locus, - StructBase base_struct = StructBase::error (), + StructBase *base_struct, std::vector<Attribute> inner_attribs = std::vector<Attribute> (), std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : StructExprStruct (std::move (mappings), std::move (struct_path), std::move (inner_attribs), std::move (outer_attribs), locus), - fields (std::move (expr_fields)), struct_base (std::move (base_struct)) + fields (std::move (expr_fields)), struct_base (base_struct) {} // copy constructor with vector clone @@ -1615,6 +1632,15 @@ public: void accept_vis (HIRVisitor &vis) override; + void iterate (std::function<bool (StructExprField *)> cb) + { + for (auto &field : fields) + { + if (!cb (field.get ())) + return; + } + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1752,11 +1778,7 @@ class StructExprUnit : public StructExpr Location locus; public: - std::string as_string () const override - { - return get_struct_name ().as_string (); - // return struct_name.as_string(); - } + std::string as_string () const override { return struct_name.as_string (); } StructExprUnit (Analysis::NodeMapping mappings, PathInExpression struct_path, std::vector<Attribute> outer_attribs, Location locus) diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc index 2e30b59..c72ca65 100644 --- a/gcc/rust/hir/tree/rust-hir-full-test.cc +++ b/gcc/rust/hir/tree/rust-hir-full-test.cc @@ -3683,7 +3683,7 @@ StructExprStruct::as_string () const { std::string str ("StructExprStruct (or subclass): "); - str += "\n Path: " + get_struct_name ().as_string (); + str += "\n Path: " + struct_name.as_string (); // inner attributes str += "\n inner attributes: "; @@ -3761,7 +3761,7 @@ StructExprStructFields::as_string () const } else { - str += struct_base.as_string (); + str += struct_base->as_string (); } return str; diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index b961a6c..1046186 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -1390,7 +1390,7 @@ protected: // Rust base struct declaration HIR node - abstract base class class Struct : public VisItem { -public: +protected: // protected to enable access by derived classes - allows better as_string Identifier struct_name; @@ -1403,6 +1403,9 @@ public: Location locus; +public: + Identifier get_identifier () const { return struct_name; } + // Returns whether struct has generic parameters. bool has_generics () const { return !generic_params.empty (); } @@ -1465,6 +1468,10 @@ public: Identifier field_name; std::unique_ptr<Type> field_type; + Analysis::NodeMapping mappings; + + Location locus; + // should this store location info? // Returns whether struct field has any outer attributes. @@ -1473,18 +1480,19 @@ public: // Returns whether struct field has a non-private (non-default) visibility. bool has_visibility () const { return !visibility.is_error (); } - StructField (Identifier field_name, std::unique_ptr<Type> field_type, - Visibility vis, + StructField (Analysis::NodeMapping mappings, Identifier field_name, + std::unique_ptr<Type> field_type, Visibility vis, Location locus, std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), - field_name (std::move (field_name)), field_type (std::move (field_type)) + field_name (std::move (field_name)), field_type (std::move (field_type)), + mappings (mappings), locus (locus) {} // Copy constructor StructField (StructField const &other) : outer_attrs (other.outer_attrs), visibility (other.visibility), field_name (other.field_name), - field_type (other.field_type->clone_type ()) + field_type (other.field_type->clone_type ()), mappings (other.mappings) {} ~StructField () = default; @@ -1496,6 +1504,7 @@ public: field_type = other.field_type->clone_type (); visibility = other.visibility; outer_attrs = other.outer_attrs; + mappings = other.mappings; return *this; } @@ -1504,20 +1513,19 @@ public: StructField (StructField &&other) = default; StructField &operator= (StructField &&other) = default; - // Returns whether struct field is in an error state. - bool is_error () const - { - return field_name.empty () && field_type == nullptr; - // this should really be an or since neither are allowed - } + std::string as_string () const; - // Creates an error state struct field. - static StructField create_error () + Identifier get_field_name () const { return field_name; } + + std::unique_ptr<Type> &get_field_type () { - return StructField (std::string (""), nullptr, Visibility::create_error ()); + rust_assert (field_type != nullptr); + return field_type; } - std::string as_string () const; + Analysis::NodeMapping get_mappings () const { return mappings; } + + Location get_locus () { return locus; } }; // Rust struct declaration with true struct type HIR node @@ -1560,6 +1568,15 @@ public: void accept_vis (HIRVisitor &vis) override; + void iterate (std::function<bool (StructField &)> cb) + { + for (auto &field : fields) + { + if (!cb (field)) + return; + } + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index d86866c..2292d16 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -21,6 +21,7 @@ #include "rust-ast-resolve-base.h" #include "rust-ast-full.h" +#include "rust-ast-resolve-struct-expr-field.h" namespace Rust { namespace Resolver { @@ -38,19 +39,22 @@ public: void visit (AST::PathInExpression &expr) { + // name scope first if (!resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) { - rust_error_at (expr.get_locus (), "unknown path %s", - expr.as_string ().c_str ()); - return; - } - else - { - resolver->insert_resolved_name (expr.get_node_id (), resolved_node); - resolver->insert_new_definition (expr.get_node_id (), - Definition{expr.get_node_id (), - parent}); + // check the type scope + if (!resolver->get_type_scope ().lookup (expr.as_string (), + &resolved_node)) + { + rust_error_at (expr.get_locus (), "unknown path %s", + expr.as_string ().c_str ()); + return; + } } + + resolver->insert_resolved_name (expr.get_node_id (), resolved_node); + resolver->insert_new_definition (expr.get_node_id (), + Definition{expr.get_node_id (), parent}); } void visit (AST::ReturnExpr &expr) @@ -154,6 +158,17 @@ public: ResolveExpr::go (elems.get_elem_to_copy ().get (), elems.get_node_id ()); } + void visit (AST::StructExprStructFields &struct_expr) + { + ResolveExpr::go (&struct_expr.get_struct_name (), + struct_expr.get_node_id ()); + struct_expr.iterate ( + [&] (AST::StructExprField *struct_field) mutable -> bool { + ResolveStructExprField::go (struct_field, struct_expr.get_node_id ()); + return true; + }); + } + private: ResolveExpr (NodeId parent) : ResolverBase (parent) {} }; diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index eca52dc..523f985 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -39,6 +39,14 @@ public: ~ResolveItem () {} + void visit (AST::StructStruct &struct_decl) + { + struct_decl.iterate ([&] (AST::StructField &field) mutable -> bool { + ResolveType::go (field.get_field_type ().get (), field.get_node_id ()); + return true; + }); + } + void visit (AST::ConstantItem &constant) { ResolveType::go (constant.get_type ().get (), constant.get_node_id ()); diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h new file mode 100644 index 0000000..c705a03 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h @@ -0,0 +1,53 @@ +// 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_AST_RESOLVE_STRUCT_EXPR_FIELD +#define RUST_AST_RESOLVE_STRUCT_EXPR_FIELD + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Resolver { + +// this resolves values being assigned not that the field actually exists yet. +// We cant resolve the field to struct until type resolution since the HIR +// Mappings don't exist yet. +class ResolveStructExprField : public ResolverBase +{ +public: + static void go (AST::StructExprField *field, NodeId parent) + { + ResolveStructExprField resolver (parent); + field->accept_vis (resolver); + } + + virtual ~ResolveStructExprField () {} + + void visit (AST::StructExprFieldIdentifierValue &field); + + // TODO + +private: + ResolveStructExprField (NodeId parent) : ResolverBase (parent) {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_STRUCT_EXPR_FIELD diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index 0b6256e..f770ed7 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -36,6 +36,12 @@ public: ~ResolveTopLevel () {} + void visit (AST::StructStruct &struct_decl) + { + resolver->get_type_scope ().insert (struct_decl.get_identifier (), + struct_decl.get_node_id ()); + } + void visit (AST::ConstantItem &constant) { resolver->get_name_scope ().insert (constant.get_identifier (), diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 8370a5b..dc368aa 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -271,5 +271,13 @@ ResolveExpr::visit (AST::BlockExpr &expr) resolver->get_type_scope ().pop (); } +// rust-ast-resolve-struct-expr-field.h + +void +ResolveStructExprField::visit (AST::StructExprFieldIdentifierValue &field) +{ + ResolveExpr::go (field.get_value ().get (), field.get_node_id ()); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 116fab7..fd5a617 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -24,6 +24,7 @@ #include "rust-tyty.h" #include "rust-tyty-call.h" #include "rust-tyty-resolver.h" +#include "rust-hir-type-check-struct-field.h" namespace Rust { namespace Resolver { @@ -136,9 +137,8 @@ public: TyTy::TyBase *lookup; if (!context->lookup_type (ref, &lookup)) { - // FIXME we need to be able to lookup the location info for the - // reference here - rust_error_at (expr.get_locus (), "consider giving this a type: %s", + rust_error_at (mappings->lookup_location (ref), + "consider giving this a type: %s", expr.as_string ().c_str ()); return; } @@ -269,6 +269,11 @@ public: infered_array_elems = TypeCheckExpr::Resolve (elems.get_elem_to_copy ()); } + void visit (HIR::StructExprStructFields &struct_expr) + { + infered = TypeCheckStructExpr::Resolve (&struct_expr); + } + private: TypeCheckExpr () : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr) diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h new file mode 100644 index 0000000..727569d --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -0,0 +1,61 @@ +// 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_STRUCT_FIELD +#define RUST_HIR_TYPE_CHECK_STRUCT_FIELD + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-type.h" +#include "rust-tyty.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckStructExpr : public TypeCheckBase +{ +public: + static TyTy::TyBase *Resolve (HIR::StructExprStructFields *expr) + { + TypeCheckStructExpr resolver; + expr->accept_vis (resolver); + rust_assert (resolver.resolved != nullptr); + return resolver.resolved; + } + + void visit (HIR::StructExprStructFields &struct_expr); + + void visit (HIR::PathInExpression &path); + + void visit (HIR::StructExprFieldIdentifierValue &field); + +private: + TypeCheckStructExpr () + : TypeCheckBase (), resolved (nullptr), struct_path_resolved (nullptr) + {} + + TyTy::TyBase *resolved; + TyTy::ADTType *struct_path_resolved; + TyTy::TyBase *resolved_field; + std::set<std::string> fields_assigned; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_STRUCT_FIELD diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 85cfe92..bcffe24 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -37,6 +37,28 @@ public: item->accept_vis (resolver); } + void visit (HIR::StructStruct &struct_decl) + { + std::vector<TyTy::StructFieldType *> fields; + struct_decl.iterate ([&] (HIR::StructField &field) mutable -> bool { + TyTy::TyBase *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 ().get_hirid (), + ty_field->get_field_type ()); + return true; + }); + + TyTy::TyBase *type + = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), + struct_decl.get_identifier (), std::move (fields)); + + context->insert_type (struct_decl.get_mappings ().get_hirid (), type); + } + void visit (HIR::ConstantItem &constant) { TyTy::TyBase *type = TypeCheckType::Resolve (constant.get_type ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 79e0190..e7d3366 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -21,6 +21,7 @@ #include "rust-hir-type-check-toplevel.h" #include "rust-hir-type-check-item.h" #include "rust-hir-type-check-expr.h" +#include "rust-hir-type-check-struct-field.h" namespace Rust { namespace Resolver { @@ -45,5 +46,123 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) }); } +// RUST_HIR_TYPE_CHECK_STRUCT_FIELD + +void +TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) +{ + struct_expr.get_struct_name ().accept_vis (*this); + if (struct_path_resolved == nullptr) + { + rust_fatal_error (struct_expr.get_struct_name ().get_locus (), + "Failed to resolve type"); + return; + } + + struct_expr.iterate ([&] (HIR::StructExprField *field) mutable -> bool { + resolved_field = nullptr; + field->accept_vis (*this); + if (resolved_field == nullptr) + { + rust_fatal_error (field->get_locus (), + "failed to resolve type for field"); + return false; + } + + context->insert_type (field->get_mappings ().get_hirid (), resolved_field); + return true; + }); + + TyTy::TyBase *expr_type = struct_path_resolved; + if (struct_expr.has_struct_base ()) + { + TyTy::TyBase *base_resolved + = TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ()); + expr_type = expr_type->combine (base_resolved); + if (resolved == nullptr) + { + rust_fatal_error ( + struct_expr.struct_base->base_struct->get_locus_slow (), + "incompatible types for base struct reference"); + return; + } + } + else if (fields_assigned.size () != struct_path_resolved->num_fields ()) + { + rust_fatal_error (struct_expr.get_locus (), + "some fields are not fully assigned"); + return; + } + + resolved = expr_type; +} + +void +TypeCheckStructExpr::visit (HIR::PathInExpression &expr) +{ + NodeId ast_node_id = expr.get_mappings ().get_nodeid (); + + // then lookup the reference_node_id + NodeId ref_node_id; + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + { + rust_error_at (expr.get_locus (), + "Failed to lookup reference for node: %s", + expr.as_string ().c_str ()); + return; + } + + // node back to HIR + HirId ref; + if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), + ref_node_id, &ref)) + { + rust_error_at (expr.get_locus (), "reverse lookup failure"); + return; + } + + // the base reference for this name _must_ have a type set + TyTy::TyBase *lookup; + if (!context->lookup_type (ref, &lookup)) + { + rust_error_at (mappings->lookup_location (ref), + "consider giving this a type: %s", + expr.as_string ().c_str ()); + return; + } + + if (lookup->get_kind () != TyTy::TypeKind::ADT) + { + rust_fatal_error (mappings->lookup_location (ref), + "expected an ADT type"); + return; + } + struct_path_resolved = (TyTy::ADTType *) lookup; +} + +void +TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) +{ + auto it = fields_assigned.find (field.field_name); + if (it != fields_assigned.end ()) + { + rust_fatal_error (field.get_locus (), "used more than once"); + return; + } + + TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ()); + TyTy::StructFieldType *field_type + = struct_path_resolved->get_field (field.field_name); + if (field_type == nullptr) + { + rust_error_at (field.get_locus (), "unknown field"); + return; + } + + resolved_field = field_type->get_field_type ()->combine (value); + if (resolved_field != nullptr) + fields_assigned.insert (field.field_name); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 97ee895..e5d3398 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -134,6 +134,24 @@ private: TyBase *resolved; }; +class StructFieldTypeRules : protected BaseRules +{ +public: + StructFieldTypeRules (StructFieldType *base) + : BaseRules (base), base (base), resolved (nullptr) + {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + +private: + StructFieldType *base; + TyBase *resolved; +}; + class UnitRules : protected BaseRules { public: diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h index 427190f..7658fed 100644 --- a/gcc/rust/typecheck/rust-tyty-visitor.h +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -29,6 +29,8 @@ class TyVisitor public: virtual void visit (UnitType &type) {} virtual void visit (InferType &type) {} + virtual void visit (StructFieldType &type) {} + virtual void visit (ADTType &type) {} virtual void visit (FnType &type) {} virtual void visit (ParamType &type) {} virtual void visit (ArrayType &type) {} diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 2023523..756301b 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -64,6 +64,47 @@ InferType::combine (TyBase *other) } void +StructFieldType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +StructFieldType::as_string () const +{ + return name + ":" + ty->as_string (); +} + +TyBase * +StructFieldType::combine (TyBase *other) +{ + StructFieldTypeRules r (this); + return r.combine (other); +} + +void +ADTType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +ADTType::as_string () const +{ + std::string fields_buffer; + for (auto &field : fields) + fields_buffer += field->as_string () + "\n"; + + return identifier + "{\n" + fields_buffer + "\n}"; +} + +TyBase * +ADTType::combine (TyBase *other) +{ + return nullptr; +} + +void FnType::accept_vis (TyVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index b9dc268..4ff78ff 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -41,6 +41,7 @@ enum TypeKind UINT, FLOAT, UNIT, + FIELD, // there are more to add... }; @@ -60,6 +61,8 @@ public: virtual bool is_unit () const { return kind == TypeKind::UNIT; } + TypeKind get_kind () const { return kind; } + protected: TyBase (HirId ref, TypeKind kind) : kind (kind), ref (ref) {} @@ -95,6 +98,65 @@ public: TyBase *combine (TyBase *other) override; }; +class StructFieldType : public TyBase +{ +public: + StructFieldType (HirId ref, std::string name, TyBase *ty) + : TyBase (ref, TypeKind::FIELD), name (name), ty (ty) + {} + + void accept_vis (TyVisitor &vis) override; + + bool is_unit () const override { return ty->is_unit (); } + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + std::string get_name () const { return name; } + + TyBase *get_field_type () { return ty; } + +private: + std::string name; + TyBase *ty; +}; + +class ADTType : public TyBase +{ +public: + ADTType (HirId ref, std::string identifier, + std::vector<StructFieldType *> fields) + : TyBase (ref, TypeKind::ADT), identifier (identifier), fields (fields) + {} + + void accept_vis (TyVisitor &vis) override; + + bool is_unit () const override { return false; } + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + size_t num_fields () const { return fields.size (); } + + StructFieldType *get_field (size_t index) { return fields.at (index); } + + StructFieldType *get_field (const std::string &lookup) + { + for (auto &field : fields) + { + if (field->get_name ().compare (lookup) == 0) + return field; + } + return nullptr; + } + +private: + std::string identifier; + std::vector<StructFieldType *> fields; +}; + class ParamType : public TyBase { public: |