diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 25 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-expr.h | 19 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-expr.h | 8 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.h | 5 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 24 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 11 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/struct_access1.rs | 10 |
7 files changed, 100 insertions, 2 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 682ff79..98e8ee1 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -433,6 +433,31 @@ public: translated = CompileExpr::Compile (expr.get_expr_in_parens ().get (), ctx); } + void visit (HIR::FieldAccessExpr &expr) + { + // resolve the receiver back to ADT type + TyTy::TyBase *receiver = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + expr.get_receiver_expr ()->get_mappings ().get_hirid (), &receiver)) + { + rust_error_at (expr.get_receiver_expr ()->get_locus_slow (), + "unresolved type for receiver"); + return; + } + rust_assert (receiver->get_kind () == TyTy::TypeKind::ADT); + + TyTy::ADTType *adt = (TyTy::ADTType *) receiver; + size_t index = 0; + adt->get_field (expr.get_field_name (), &index); + + Bexpression *struct_ref + = CompileExpr::Compile (expr.get_receiver_expr ().get (), ctx); + + translated + = ctx->get_backend ()->struct_field_expression (struct_ref, index, + expr.get_locus ()); + } + private: CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 1003e8c..29be5cc 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -544,6 +544,25 @@ public: std::move (outer_attribs), expr.get_locus ()); } + void visit (AST::FieldAccessExpr &expr) + { + std::vector<HIR::Attribute> inner_attribs; + std::vector<HIR::Attribute> outer_attribs; + + HIR::Expr *receiver + = ASTLoweringExpr::translate (expr.get_receiver_expr ().get ()); + + 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::FieldAccessExpr (mapping, + std::unique_ptr<HIR::Expr> (receiver), + expr.get_field_name (), + std::move (outer_attribs), expr.get_locus ()); + } + private: ASTLoweringExpr () : translated (nullptr), translated_array_elems (nullptr), terminated (false) diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index bb8499a..cc717a8 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2370,6 +2370,14 @@ public: void accept_vis (HIRVisitor &vis) override; + std::unique_ptr<Expr> &get_receiver_expr () + { + rust_assert (receiver != nullptr); + return receiver; + } + + Identifier get_field_name () const { return field; } + 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 58de087..21b2194 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -187,6 +187,11 @@ public: ResolveExpr::go (expr.get_expr_in_parens ().get (), expr.get_node_id ()); } + void visit (AST::FieldAccessExpr &expr) + { + ResolveExpr::go (expr.get_receiver_expr ().get (), expr.get_node_id ()); + } + private: ResolveExpr (NodeId parent) : ResolverBase (parent) {} }; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index dd3c8b9..a6cf286 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -440,6 +440,30 @@ public: infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get ()); } + void visit (HIR::FieldAccessExpr &expr) + { + auto struct_base + = TypeCheckExpr::Resolve (expr.get_receiver_expr ().get ()); + if (struct_base->get_kind () != TyTy::TypeKind::ADT) + { + rust_error_at (expr.get_locus (), "expected ADT Type got: [%s]", + struct_base->as_string ().c_str ()); + return; + } + + TyTy::ADTType *adt = (TyTy::ADTType *) struct_base; + auto resolved = adt->get_field (expr.get_field_name ()); + if (resolved == nullptr) + { + rust_error_at (expr.get_locus (), "unknown field [%s] for type [%s]", + expr.get_field_name ().c_str (), + adt->as_string ().c_str ()); + return; + } + + infered = resolved->get_field_type (); + } + private: TypeCheckExpr (bool is_final_expr) : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr), diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 1e529bd..db34f7e 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -194,12 +194,19 @@ public: StructFieldType *get_field (size_t index) { return fields.at (index); } - StructFieldType *get_field (const std::string &lookup) + StructFieldType *get_field (const std::string &lookup, + size_t *index = nullptr) { + size_t i = 0; for (auto &field : fields) { if (field->get_name ().compare (lookup) == 0) - return field; + { + if (index != nullptr) + *index = i; + return field; + } + i++; } return nullptr; } diff --git a/gcc/testsuite/rust.test/compilable/struct_access1.rs b/gcc/testsuite/rust.test/compilable/struct_access1.rs new file mode 100644 index 0000000..bc12b93 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/struct_access1.rs @@ -0,0 +1,10 @@ +struct Foo { + one: i32, + two: i32, +} + +fn main() { + let struct_test = Foo { one: 1, two: 2 }; + let a = struct_test.one; + let b = struct_test.two; +} |