diff options
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: |