diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-12-16 10:47:11 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-16 10:47:11 +0000 |
commit | 83a984b1a12694d8e06eb139089429b61e236fdd (patch) | |
tree | 715954488f9c719a3db3d98d29e8828df325c750 /gcc | |
parent | 768f926074a27a7b1a2179613eeeb8291648b8a7 (diff) | |
parent | a688913ac153a85aa803faad9d243e66fd12889d (diff) | |
download | gcc-83a984b1a12694d8e06eb139089429b61e236fdd.zip gcc-83a984b1a12694d8e06eb139089429b61e236fdd.tar.gz gcc-83a984b1a12694d8e06eb139089429b61e236fdd.tar.bz2 |
Merge #835
835: Add name-resolution and HIR lowering pass for MatchExpr r=philberty a=philberty
This adds the name-resolution and HIR lowering pass for the match-expr
the type checking pass patch needs some work to be split up but these are
two nice isolated commits which are easier to read.
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/Make-lang.in | 2 | ||||
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 9 | ||||
-rw-r--r-- | gcc/rust/ast/rust-pattern.h | 61 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-expr.h | 51 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-pattern.cc | 115 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-pattern.h | 12 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-expr.h | 52 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-full-decls.h | 1 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-full-test.cc | 10 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-pattern.h | 62 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.h | 36 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-pattern.cc | 104 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-pattern.h | 7 |
13 files changed, 396 insertions, 126 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 3a5e7cc..1274578 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -76,7 +76,9 @@ GRS_OBJS = \ rust/rust-hir-full-test.o \ rust/rust-hir-map.o \ rust/rust-ast-lower.o \ + rust/rust-ast-lower-pattern.o \ rust/rust-ast-resolve.o \ + rust/rust-ast-resolve-pattern.o \ rust/rust-hir-type-check.o \ rust/rust-tyty.o \ rust/rust-tyctx.o \ diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 7f6714a..48dcc10 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -4337,23 +4337,26 @@ struct MatchCase private: MatchArm arm; std::unique_ptr<Expr> expr; + NodeId node_id; /* TODO: does whether trailing comma exists need to be stored? currently * assuming it is only syntactical and has no effect on meaning. */ public: MatchCase (MatchArm arm, std::unique_ptr<Expr> expr) - : arm (std::move (arm)), expr (std::move (expr)) + : arm (std::move (arm)), expr (std::move (expr)), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} MatchCase (const MatchCase &other) - : arm (other.arm), expr (other.expr->clone_expr ()) + : arm (other.arm), expr (other.expr->clone_expr ()), node_id (other.node_id) {} MatchCase &operator= (const MatchCase &other) { arm = other.arm; expr = other.expr->clone_expr (); + node_id = other.node_id; return *this; } @@ -4378,6 +4381,8 @@ public: rust_assert (!arm.is_error ()); return arm; } + + NodeId get_node_id () const { return node_id; } }; #if 0 diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index b2c3686..d46bf0e 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -456,7 +456,17 @@ class StructPatternField std::vector<Attribute> outer_attrs; Location locus; +protected: + NodeId node_id; + public: + enum ItemType + { + TUPLE_PAT, + IDENT_PAT, + IDENT + }; + virtual ~StructPatternField () {} // Unique pointer custom clone function @@ -474,14 +484,18 @@ public: virtual void mark_for_strip () = 0; virtual bool is_marked_for_strip () const = 0; + virtual ItemType get_item_type () const = 0; + + NodeId get_node_id () const { return node_id; } // TODO: seems kinda dodgy. Think of better way. std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } protected: - StructPatternField (std::vector<Attribute> outer_attribs, Location locus) - : outer_attrs (std::move (outer_attribs)), locus (locus) + StructPatternField (std::vector<Attribute> outer_attribs, Location locus, + NodeId node_id) + : outer_attrs (std::move (outer_attribs)), locus (locus), node_id (node_id) {} // Clone function implementation as pure virtual method @@ -499,8 +513,9 @@ public: std::unique_ptr<Pattern> tuple_pattern, std::vector<Attribute> outer_attribs, Location locus) - : StructPatternField (std::move (outer_attribs), locus), index (index), - tuple_pattern (std::move (tuple_pattern)) + : StructPatternField (std::move (outer_attribs), locus, + Analysis::Mappings::get ()->get_next_node_id ()), + index (index), tuple_pattern (std::move (tuple_pattern)) {} // Copy constructor requires clone @@ -508,6 +523,7 @@ public: : StructPatternField (other), index (other.index) { // guard to prevent null dereference (only required if error state) + node_id = other.get_node_id (); if (other.tuple_pattern != nullptr) tuple_pattern = other.tuple_pattern->clone_pattern (); } @@ -519,6 +535,7 @@ public: StructPatternField::operator= (other); index = other.index; // outer_attrs = other.outer_attrs; + node_id = other.get_node_id (); // guard to prevent null dereference (only required if error state) if (other.tuple_pattern != nullptr) @@ -552,6 +569,8 @@ public: return tuple_pattern; } + ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -572,7 +591,8 @@ public: std::unique_ptr<Pattern> ident_pattern, std::vector<Attribute> outer_attrs, Location locus) - : StructPatternField (std::move (outer_attrs), locus), + : StructPatternField (std::move (outer_attrs), locus, + Analysis::Mappings::get ()->get_next_node_id ()), ident (std::move (ident)), ident_pattern (std::move (ident_pattern)) {} @@ -581,6 +601,7 @@ public: : StructPatternField (other), ident (other.ident) { // guard to prevent null dereference (only required if error state) + node_id = other.get_node_id (); if (other.ident_pattern != nullptr) ident_pattern = other.ident_pattern->clone_pattern (); } @@ -592,6 +613,7 @@ public: StructPatternField::operator= (other); ident = other.ident; // outer_attrs = other.outer_attrs; + node_id = other.get_node_id (); // guard to prevent null dereference (only required if error state) if (other.ident_pattern != nullptr) @@ -618,6 +640,8 @@ public: return ident_pattern == nullptr; } + const Identifier &get_identifier () const { return ident; } + // TODO: is this better? Or is a "vis_pattern" better? std::unique_ptr<Pattern> &get_ident_pattern () { @@ -625,6 +649,8 @@ public: return ident_pattern; } + ItemType get_item_type () const override final { return ItemType::IDENT_PAT; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -644,8 +670,9 @@ class StructPatternFieldIdent : public StructPatternField public: StructPatternFieldIdent (Identifier ident, bool is_ref, bool is_mut, std::vector<Attribute> outer_attrs, Location locus) - : StructPatternField (std::move (outer_attrs), locus), has_ref (is_ref), - has_mut (is_mut), ident (std::move (ident)) + : StructPatternField (std::move (outer_attrs), locus, + Analysis::Mappings::get ()->get_next_node_id ()), + has_ref (is_ref), has_mut (is_mut), ident (std::move (ident)) {} std::string as_string () const override; @@ -656,6 +683,14 @@ public: void mark_for_strip () override { ident = {}; } bool is_marked_for_strip () const override { return ident.empty (); } + const Identifier &get_identifier () const { return ident; } + + ItemType get_item_type () const override final { return ItemType::IDENT; } + + bool is_ref () const { return has_ref; } + + bool is_mut () const { return has_mut; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -827,6 +862,12 @@ protected: class TupleStructItems { public: + enum ItemType + { + RANGE, + NO_RANGE + }; + virtual ~TupleStructItems () {} // TODO: should this store location data? @@ -841,6 +882,8 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + virtual ItemType get_item_type () const = 0; + protected: // pure virtual clone implementation virtual TupleStructItems *clone_tuple_struct_items_impl () const = 0; @@ -890,6 +933,8 @@ public: return patterns; } + ItemType get_item_type () const override final { return ItemType::NO_RANGE; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -966,6 +1011,8 @@ public: return upper_patterns; } + ItemType get_item_type () const override final { return ItemType::RANGE; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index d6e2194..8cd4fb5 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -23,6 +23,7 @@ #include "rust-ast-lower-base.h" #include "rust-ast-lower-block.h" #include "rust-ast-lower-struct-field-expr.h" +#include "rust-ast-lower-pattern.h" namespace Rust { namespace HIR { @@ -667,6 +668,56 @@ public: expr.get_outer_attrs (), expr.get_locus ()); } + void visit (AST::MatchExpr &expr) override + { + HIR::Expr *branch_value + = ASTLoweringExpr::translate (expr.get_scrutinee_expr ().get ()); + + std::vector<HIR::MatchCase> match_arms; + for (auto &match_case : expr.get_match_cases ()) + { + HIR::Expr *kase_expr + = ASTLoweringExpr::translate (match_case.get_expr ().get ()); + + HIR::Expr *kase_guard_expr = nullptr; + if (match_case.get_arm ().has_match_arm_guard ()) + { + kase_guard_expr = ASTLoweringExpr::translate ( + match_case.get_arm ().get_guard_expr ().get ()); + } + + std::vector<std::unique_ptr<HIR::Pattern> > match_arm_patterns; + for (auto &pattern : match_case.get_arm ().get_patterns ()) + { + HIR::Pattern *ptrn = ASTLoweringPattern::translate (pattern.get ()); + match_arm_patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn)); + } + + HIR::MatchArm arm (std::move (match_arm_patterns), + std::unique_ptr<HIR::Expr> (kase_guard_expr), + match_case.get_arm ().get_outer_attrs ()); + + 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); + + HIR::MatchCase kase (std::move (mapping), std::move (arm), + std::unique_ptr<HIR::Expr> (kase_expr)); + match_arms.push_back (std::move (kase)); + } + + 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::MatchExpr (mapping, std::unique_ptr<HIR::Expr> (branch_value), + std::move (match_arms), expr.get_inner_attrs (), + expr.get_outer_attrs (), expr.get_locus ()); + } + private: ASTLoweringExpr () : ASTLoweringBase (), translated (nullptr), diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc new file mode 100644 index 0000000..4ff61cd --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -0,0 +1,115 @@ +// Copyright (C) 2020-2021 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/>. + +#include "rust-ast-lower-pattern.h" +#include "rust-ast-lower-expr.h" + +namespace Rust { +namespace HIR { + +void +ASTLoweringPattern::visit (AST::PathInExpression &pattern) +{ + translated = ASTLowerPathInExpression::translate (&pattern); +} + +void +ASTLoweringPattern::visit (AST::TupleStructPattern &pattern) +{ + HIR::PathInExpression *path + = ASTLowerPathInExpression::translate (&pattern.get_path ()); + + TupleStructItems *lowered = nullptr; + auto &items = pattern.get_items (); + switch (items->get_item_type ()) + { + case AST::TupleStructItems::RANGE: { + // TODO + gcc_unreachable (); + } + break; + + case AST::TupleStructItems::NO_RANGE: { + AST::TupleStructItemsNoRange &items_no_range + = static_cast<AST::TupleStructItemsNoRange &> (*items.get ()); + + std::vector<std::unique_ptr<HIR::Pattern> > patterns; + for (auto &inner_pattern : items_no_range.get_patterns ()) + { + HIR::Pattern *p + = ASTLoweringPattern::translate (inner_pattern.get ()); + patterns.push_back (std::unique_ptr<HIR::Pattern> (p)); + } + + lowered = new HIR::TupleStructItemsNoRange (std::move (patterns)); + } + break; + } + + translated = new HIR::TupleStructPattern ( + *path, std::unique_ptr<HIR::TupleStructItems> (lowered)); +} + +void +ASTLoweringPattern::visit (AST::StructPattern &pattern) +{ + HIR::PathInExpression *path + = ASTLowerPathInExpression::translate (&pattern.get_path ()); + + auto &raw_elems = pattern.get_struct_pattern_elems (); + rust_assert (!raw_elems.has_etc ()); + + std::vector<std::unique_ptr<HIR::StructPatternField> > fields; + for (auto &field : raw_elems.get_struct_pattern_fields ()) + { + HIR::StructPatternField *f = nullptr; + switch (field->get_item_type ()) + { + case AST::StructPatternField::ItemType::TUPLE_PAT: { + // TODO + gcc_unreachable (); + } + break; + + case AST::StructPatternField::ItemType::IDENT_PAT: { + // TODO + gcc_unreachable (); + } + break; + + case AST::StructPatternField::ItemType::IDENT: { + AST::StructPatternFieldIdent &ident + = static_cast<AST::StructPatternFieldIdent &> (*field.get ()); + + f = new HIR::StructPatternFieldIdent ( + ident.get_identifier (), ident.is_ref (), + ident.is_mut () ? Mutability::Mut : Mutability::Imm, + ident.get_outer_attrs (), ident.get_locus ()); + } + break; + } + + fields.push_back (std::unique_ptr<HIR::StructPatternField> (f)); + } + + HIR::StructPatternElements elems (std::move (fields)); + translated = new HIR::StructPattern (*path, std::move (elems)); +} + +} // namespace HIR +} // namespace Rust diff --git a/gcc/rust/hir/rust-ast-lower-pattern.h b/gcc/rust/hir/rust-ast-lower-pattern.h index d7b6a47..d8c03ce 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.h +++ b/gcc/rust/hir/rust-ast-lower-pattern.h @@ -20,7 +20,6 @@ #define RUST_AST_LOWER_PATTERN #include "rust-ast-lower-base.h" -#include "rust-diagnostics.h" namespace Rust { namespace HIR { @@ -34,12 +33,11 @@ public: { ASTLoweringPattern resolver; pattern->accept_vis (resolver); + rust_assert (resolver.translated != nullptr); return resolver.translated; } - virtual ~ASTLoweringPattern () override {} - - void visit (AST::IdentifierPattern &pattern) + void visit (AST::IdentifierPattern &pattern) override { std::unique_ptr<Pattern> to_bind; translated @@ -50,6 +48,12 @@ public: std::move (to_bind)); } + void visit (AST::PathInExpression &pattern) override; + + void visit (AST::StructPattern &pattern) override; + + void visit (AST::TupleStructPattern &pattern) override; + private: ASTLoweringPattern () : translated (nullptr) {} diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 901feda..0e5d97b 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -3681,57 +3681,29 @@ public: std::string as_string () const; }; -/* -// Base "match case" for a match expression - abstract -class MatchCase -{ - MatchArm arm; - -protected: - MatchCase (MatchArm arm) : arm (std::move (arm)) {} - - // Should not require copy constructor or assignment operator overloading - - // Clone function implementation as pure virtual method - virtual MatchCase *clone_match_case_impl () const = 0; - -public: - virtual ~MatchCase () {} - - // Unique pointer custom clone function - std::unique_ptr<MatchCase> clone_match_case () const - { - return std::unique_ptr<MatchCase> (clone_match_case_impl ()); - } - - virtual std::string as_string () const; - - virtual void accept_vis (HIRVisitor &vis) = 0; -}; -*/ - /* A "match case" - a correlated match arm and resulting expression. Not * abstract. */ struct MatchCase { private: + Analysis::NodeMapping mappings; MatchArm arm; std::unique_ptr<Expr> expr; - /* TODO: does whether trailing comma exists need to be stored? currently - * assuming it is only syntactical and has no effect on meaning. */ - public: - MatchCase (MatchArm arm, std::unique_ptr<Expr> expr) - : arm (std::move (arm)), expr (std::move (expr)) + MatchCase (Analysis::NodeMapping mappings, MatchArm arm, + std::unique_ptr<Expr> expr) + : mappings (mappings), arm (std::move (arm)), expr (std::move (expr)) {} MatchCase (const MatchCase &other) - : arm (other.arm), expr (other.expr->clone_expr ()) + : mappings (other.mappings), arm (other.arm), + expr (other.expr->clone_expr ()) {} MatchCase &operator= (const MatchCase &other) { + mappings = other.mappings; arm = other.arm; expr = other.expr->clone_expr (); @@ -3744,6 +3716,8 @@ public: ~MatchCase () = default; std::string as_string () const; + + Analysis::NodeMapping get_mappings () const { return mappings; } }; #if 0 @@ -3841,23 +3815,15 @@ class MatchExpr : public ExprWithBlock { std::unique_ptr<Expr> branch_value; AST::AttrVec inner_attrs; - - // bool has_match_arms; - // MatchArms match_arms; - // std::vector<std::unique_ptr<MatchCase> > match_arms; // inlined from - // MatchArms std::vector<MatchCase> match_arms; - Location locus; public: std::string as_string () const override; - // Returns whether the match expression has any match arms. bool has_match_arms () const { return !match_arms.empty (); } MatchExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> branch_value, - // std::vector<std::unique_ptr<MatchCase> > match_arms, std::vector<MatchCase> match_arms, AST::AttrVec inner_attrs, AST::AttrVec outer_attrs, Location locus) : ExprWithBlock (std::move (mappings), std::move (outer_attrs)), diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h index 3e9d8b2..79f3789 100644 --- a/gcc/rust/hir/tree/rust-hir-full-decls.h +++ b/gcc/rust/hir/tree/rust-hir-full-decls.h @@ -199,7 +199,6 @@ class StructPatternField; class StructPatternFieldTuplePat; class StructPatternFieldIdentPat; class StructPatternFieldIdent; -struct StructPatternElements; class StructPattern; class TupleStructItems; class TupleStructItemsNoRange; diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc index 843e32c..76b8825 100644 --- a/gcc/rust/hir/tree/rust-hir-full-test.cc +++ b/gcc/rust/hir/tree/rust-hir-full-test.cc @@ -2575,16 +2575,6 @@ StructPatternElements::as_string () const } } - str += "\n Etc: "; - if (has_struct_pattern_etc) - { - str += "true"; - } - else - { - str += "false"; - } - return str; } diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h index 4f0bfe6..1373cc7 100644 --- a/gcc/rust/hir/tree/rust-hir-pattern.h +++ b/gcc/rust/hir/tree/rust-hir-pattern.h @@ -377,26 +377,6 @@ protected: } }; -// aka StructPatternEtCetera; potential element in struct pattern -struct StructPatternEtc -{ -private: - AST::AttrVec outer_attrs; - - // should this store location data? - -public: - StructPatternEtc (AST::AttrVec outer_attribs) - : outer_attrs (std::move (outer_attribs)) - {} - - // Creates an empty StructPatternEtc - static StructPatternEtc create_empty () - { - return StructPatternEtc (AST::AttrVec ()); - } -}; - // Base class for a single field in a struct pattern - abstract class StructPatternField { @@ -561,45 +541,24 @@ protected: struct StructPatternElements { private: - // bool has_struct_pattern_fields; std::vector<std::unique_ptr<StructPatternField> > fields; - bool has_struct_pattern_etc; - StructPatternEtc etc; - - // must have at least one of the two and maybe both - - // should this store location data? - public: // Returns whether there are any struct pattern fields bool has_struct_pattern_fields () const { return !fields.empty (); } /* Returns whether the struct pattern elements is entirely empty (no fields, * no etc). */ - bool is_empty () const - { - return !has_struct_pattern_fields () && !has_struct_pattern_etc; - } + bool is_empty () const { return !has_struct_pattern_fields (); } // Constructor for StructPatternElements with both (potentially) StructPatternElements ( - std::vector<std::unique_ptr<StructPatternField> > fields, - StructPatternEtc etc) - : fields (std::move (fields)), has_struct_pattern_etc (true), - etc (std::move (etc)) - {} - - // Constructor for StructPatternElements with no StructPatternEtc - StructPatternElements ( std::vector<std::unique_ptr<StructPatternField> > fields) - : fields (std::move (fields)), has_struct_pattern_etc (false), - etc (StructPatternEtc::create_empty ()) + : fields (std::move (fields)) {} // Copy constructor with vector clone StructPatternElements (StructPatternElements const &other) - : has_struct_pattern_etc (other.has_struct_pattern_etc), etc (other.etc) { fields.reserve (other.fields.size ()); for (const auto &e : other.fields) @@ -609,9 +568,6 @@ public: // Overloaded assignment operator with vector clone StructPatternElements &operator= (StructPatternElements const &other) { - etc = other.etc; - has_struct_pattern_etc = other.has_struct_pattern_etc; - fields.reserve (other.fields.size ()); for (const auto &e : other.fields) fields.push_back (e->clone_struct_pattern_field ()); @@ -637,27 +593,15 @@ public: class StructPattern : public Pattern { PathInExpression path; - - // bool has_struct_pattern_elements; StructPatternElements elems; - // TODO: should this store location data? Accessor uses path location data. - public: std::string as_string () const override; - // Constructs a struct pattern from specified StructPatternElements - StructPattern (PathInExpression struct_path, - StructPatternElements elems - = StructPatternElements::create_empty ()) + StructPattern (PathInExpression struct_path, StructPatternElements elems) : path (std::move (struct_path)), elems (std::move (elems)) {} - /* TODO: constructor to construct via elements included in - * StructPatternElements */ - - /* Returns whether struct pattern has any struct pattern elements (if not, it - * is empty). */ bool has_struct_pattern_elems () const { return !elems.is_empty (); } Location get_locus () const { return path.get_locus (); } diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 05d116f..5f496a6 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -24,6 +24,7 @@ #include "rust-ast-resolve-struct-expr-field.h" #include "rust-ast-verify-assignee.h" #include "rust-ast-resolve-type.h" +#include "rust-ast-resolve-pattern.h" namespace Rust { namespace Resolver { @@ -409,6 +410,41 @@ public: ResolveExpr::go (expr.get_dereferenced_expr ().get (), expr.get_node_id ()); } + void visit (AST::MatchExpr &expr) override + { + ResolveExpr::go (expr.get_scrutinee_expr ().get (), expr.get_node_id ()); + for (auto &match_case : expr.get_match_cases ()) + { + // each arm is in its own scope + NodeId scope_node_id = match_case.get_node_id (); + resolver->get_name_scope ().push (scope_node_id); + resolver->get_type_scope ().push (scope_node_id); + resolver->get_label_scope ().push (scope_node_id); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); + + // resolve + AST::MatchArm &arm = match_case.get_arm (); + if (arm.has_match_arm_guard ()) + ResolveExpr::go (arm.get_guard_expr ().get (), expr.get_node_id ()); + + // insert any possible new patterns + for (auto &pattern : arm.get_patterns ()) + { + PatternDeclaration::go (pattern.get (), expr.get_node_id ()); + } + + // resolve the body + ResolveExpr::go (match_case.get_expr ().get (), expr.get_node_id ()); + + // done + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); + resolver->get_label_scope ().pop (); + } + } + private: ResolveExpr (NodeId parent) : ResolverBase (parent) {} }; diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc new file mode 100644 index 0000000..c97a83f --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc @@ -0,0 +1,104 @@ +// Copyright (C) 2020-2021 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/>. + +#include "rust-ast-resolve-pattern.h" +#include "rust-ast-resolve-expr.h" + +namespace Rust { +namespace Resolver { + +void +PatternDeclaration::visit (AST::PathInExpression &pattern) +{ + ResolveExpr::go (&pattern, parent); +} + +void +PatternDeclaration::visit (AST::TupleStructPattern &pattern) +{ + ResolveExpr::go (&pattern.get_path (), parent); + + std::unique_ptr<AST::TupleStructItems> &items = pattern.get_items (); + switch (items->get_item_type ()) + { + case AST::TupleStructItems::RANGE: { + // TODO + gcc_unreachable (); + } + break; + + case AST::TupleStructItems::NO_RANGE: { + AST::TupleStructItemsNoRange &items_no_range + = static_cast<AST::TupleStructItemsNoRange &> (*items.get ()); + + for (auto &inner_pattern : items_no_range.get_patterns ()) + { + PatternDeclaration::go (inner_pattern.get (), + pattern.get_node_id ()); + } + } + break; + } +} + +void +PatternDeclaration::visit (AST::StructPattern &pattern) +{ + ResolveExpr::go (&pattern.get_path (), parent); + + auto &struct_pattern_elems = pattern.get_struct_pattern_elems (); + for (auto &field : struct_pattern_elems.get_struct_pattern_fields ()) + { + switch (field->get_item_type ()) + { + case AST::StructPatternField::ItemType::TUPLE_PAT: { + // TODO + gcc_unreachable (); + } + break; + + case AST::StructPatternField::ItemType::IDENT_PAT: { + // TODO + gcc_unreachable (); + } + break; + + case AST::StructPatternField::ItemType::IDENT: { + AST::StructPatternFieldIdent &ident + = static_cast<AST::StructPatternFieldIdent &> (*field.get ()); + + resolver->get_name_scope ().insert ( + CanonicalPath::new_seg (ident.get_node_id (), + ident.get_identifier ()), + ident.get_node_id (), pattern.get_locus ()); + resolver->insert_new_definition ( + ident.get_node_id (), + Definition{ident.get_node_id (), pattern.get_node_id ()}); + resolver->mark_decl_mutability (ident.get_node_id (), + ident.is_mut ()); + } + break; + } + } + + // TODO + rust_assert (!struct_pattern_elems.has_etc ()); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h index a88811e..57c73ba 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h @@ -83,6 +83,13 @@ public: pattern.get_is_mut ()); } + // cases in a match expression + void visit (AST::PathInExpression &pattern) override; + + void visit (AST::StructPattern &pattern) override; + + void visit (AST::TupleStructPattern &pattern) override; + private: PatternDeclaration (NodeId parent) : ResolverBase (parent) {} }; |