aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-12-14 23:30:25 +0000
committerPhilip Herron <philip.herron@embecosm.com>2021-12-16 10:25:01 +0000
commit4dba290c35d2d5023173c6a2d75741b1a4d549ab (patch)
treeb28ac925df0e28c95cd5a6ad84173935783f346d
parent3629645386ad503606f29f95c2e16d0600df6e20 (diff)
downloadgcc-4dba290c35d2d5023173c6a2d75741b1a4d549ab.zip
gcc-4dba290c35d2d5023173c6a2d75741b1a4d549ab.tar.gz
gcc-4dba290c35d2d5023173c6a2d75741b1a4d549ab.tar.bz2
Add initial name-resolution for match-expr
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/ast/rust-expr.h9
-rw-r--r--gcc/rust/ast/rust-pattern.h61
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h36
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.cc104
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.h7
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) {}
};