diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-12-14 23:30:25 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-12-16 10:25:01 +0000 |
commit | 4dba290c35d2d5023173c6a2d75741b1a4d549ab (patch) | |
tree | b28ac925df0e28c95cd5a6ad84173935783f346d | |
parent | 3629645386ad503606f29f95c2e16d0600df6e20 (diff) | |
download | gcc-4dba290c35d2d5023173c6a2d75741b1a4d549ab.zip gcc-4dba290c35d2d5023173c6a2d75741b1a4d549ab.tar.gz gcc-4dba290c35d2d5023173c6a2d75741b1a4d549ab.tar.bz2 |
Add initial name-resolution for match-expr
-rw-r--r-- | gcc/rust/Make-lang.in | 1 | ||||
-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/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 |
6 files changed, 209 insertions, 9 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 3a5e7cc..a405428 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -77,6 +77,7 @@ GRS_OBJS = \ rust/rust-hir-map.o \ rust/rust-ast-lower.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/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) {} }; |