aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorOwen Avery <powerboat9.gamer@gmail.com>2023-06-01 13:37:35 -0400
committerCohenArthur <arthur.cohen@embecosm.com>2023-06-22 08:38:34 +0000
commitd3b247e73368e2e50d71ce8c003e761469b1ec98 (patch)
treeed314de55ec22ff8eb055e578a2d0011bed8f013 /gcc
parentc93eb308c5ad272059d690980813746895116c71 (diff)
downloadgcc-d3b247e73368e2e50d71ce8c003e761469b1ec98.zip
gcc-d3b247e73368e2e50d71ce8c003e761469b1ec98.tar.gz
gcc-d3b247e73368e2e50d71ce8c003e761469b1ec98.tar.bz2
Make MatchedFragmentContainer a tree-like structure
gcc/rust/ChangeLog: * expand/rust-macro-expand.cc (MacroExpander::expand_decl_macro): Use pointers/smart pointers to refer to MatchedFragmentContainer instances. (MacroExpander::transcribe_rule): Likewise. (MatchedFragmentContainer::get_single_fragment): New implementation. (MatchedFragmentContainer::get_fragments): Likewise. (MatchedFragmentContainer::add_fragment): Likewise. (MatchedFragmentContainer::zero): Likewise. (MatchedFragmentContainer::metavar): Likewise. * expand/rust-macro-expand.h (class MatchedFragmentContainer): Make abstract. (class MatchedFragmentContainerMetaVar): New. (class MatchedFragmentContainerRepetition): New. (class SubstitutionScope): Use pointers/smart pointers to refer to MatchedFragmentContainer instances. (MacroExpander::transcribe_rule): Likewise. * expand/rust-macro-substitute-ctx.cc (SubstituteCtx::substitute_metavar): Likewise. (SubstituteCtx::check_repetition_amount): Likewise. (SubstituteCtx::substitute_repetition): Likewise. * expand/rust-macro-substitute-ctx.h (class SubstituteCtx): Likewise. Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc54
-rw-r--r--gcc/rust/expand/rust-macro-expand.h123
-rw-r--r--gcc/rust/expand/rust-macro-substitute-ctx.cc37
-rw-r--r--gcc/rust/expand/rust-macro-substitute-ctx.h4
4 files changed, 140 insertions, 78 deletions
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index bb981a3..358d8fb 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -78,7 +78,8 @@ MacroExpander::expand_decl_macro (Location invoc_locus,
// find matching arm
AST::MacroRule *matched_rule = nullptr;
- std::map<std::string, MatchedFragmentContainer> matched_fragments;
+ std::map<std::string, std::unique_ptr<MatchedFragmentContainer>>
+ matched_fragments;
for (auto &rule : rules_def.get_rules ())
{
sub_stack.push ();
@@ -109,8 +110,13 @@ MacroExpander::expand_decl_macro (Location invoc_locus,
return AST::Fragment::create_error ();
}
- return transcribe_rule (*matched_rule, invoc_token_tree, matched_fragments,
- semicolon, peek_context ());
+ std::map<std::string, MatchedFragmentContainer *> matched_fragments_ptr;
+
+ for (auto &ent : matched_fragments)
+ matched_fragments_ptr.emplace (ent.first, ent.second.get ());
+
+ return transcribe_rule (*matched_rule, invoc_token_tree,
+ matched_fragments_ptr, semicolon, peek_context ());
}
void
@@ -961,7 +967,7 @@ tokens_to_str (std::vector<std::unique_ptr<AST::Token>> &tokens)
AST::Fragment
MacroExpander::transcribe_rule (
AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree,
- std::map<std::string, MatchedFragmentContainer> &matched_fragments,
+ std::map<std::string, MatchedFragmentContainer *> &matched_fragments,
bool semicolon, ContextType ctx)
{
// we can manipulate the token tree to substitute the dollar identifiers so
@@ -1129,4 +1135,44 @@ MacroExpander::parse_proc_macro_output (ProcMacro::TokenStream ts)
return {nodes, std::vector<std::unique_ptr<AST::Token>> ()};
}
+MatchedFragment &
+MatchedFragmentContainer::get_single_fragment ()
+{
+ rust_assert (is_single_fragment ());
+
+ return static_cast<MatchedFragmentContainerMetaVar &> (*this).get_fragment ();
+}
+
+std::vector<std::unique_ptr<MatchedFragmentContainer>> &
+MatchedFragmentContainer::get_fragments ()
+{
+ rust_assert (!is_single_fragment ());
+
+ return static_cast<MatchedFragmentContainerRepetition &> (*this)
+ .get_fragments ();
+}
+
+void
+MatchedFragmentContainer::add_fragment (MatchedFragment fragment)
+{
+ rust_assert (!is_single_fragment ());
+
+ return static_cast<MatchedFragmentContainerRepetition &> (*this)
+ .add_fragment (fragment);
+}
+
+std::unique_ptr<MatchedFragmentContainer>
+MatchedFragmentContainer::zero ()
+{
+ return std::unique_ptr<MatchedFragmentContainer> (
+ new MatchedFragmentContainerRepetition ());
+}
+
+std::unique_ptr<MatchedFragmentContainer>
+MatchedFragmentContainer::metavar (MatchedFragment fragment)
+{
+ return std::unique_ptr<MatchedFragmentContainer> (
+ new MatchedFragmentContainerMetaVar (fragment));
+}
+
} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index a03de5a..d8c8147 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -90,66 +90,88 @@ public:
Repetition,
};
- MatchedFragmentContainer (std::vector<MatchedFragment> fragments,
- Kind kind = Kind::Repetition)
- : fragments (fragments), kind (kind)
- {}
+ virtual Kind get_kind () const = 0;
+
+ virtual std::string as_string () const = 0;
/**
* Create a valid fragment matched zero times. This is useful for repetitions
* which allow the absence of a fragment, such as * and ?
*/
- static MatchedFragmentContainer zero ()
- {
- return MatchedFragmentContainer ({});
- }
+ static std::unique_ptr<MatchedFragmentContainer> zero ();
/**
* Create a valid fragment matched one time
*/
- static MatchedFragmentContainer metavar (MatchedFragment fragment)
- {
- return MatchedFragmentContainer ({fragment}, Kind::MetaVar);
- }
+ static std::unique_ptr<MatchedFragmentContainer>
+ metavar (MatchedFragment fragment);
/**
* Add a matched fragment to the container
*/
- void add_fragment (MatchedFragment fragment)
- {
- rust_assert (!is_single_fragment ());
+ void add_fragment (MatchedFragment fragment);
- fragments.emplace_back (fragment);
- }
+ // const std::string &get_fragment_name () const { return fragment_name; }
+
+ bool is_single_fragment () const { return get_kind () == Kind::MetaVar; }
+
+ MatchedFragment &get_single_fragment ();
+
+ std::vector<std::unique_ptr<MatchedFragmentContainer>> &get_fragments ();
+};
+
+class MatchedFragmentContainerMetaVar : public MatchedFragmentContainer
+{
+ MatchedFragment fragment;
+
+public:
+ MatchedFragmentContainerMetaVar (const MatchedFragment &fragment)
+ : fragment (fragment)
+ {}
+
+ MatchedFragment &get_fragment () { return fragment; }
+
+ virtual Kind get_kind () const { return Kind::MetaVar; }
+
+ virtual std::string as_string () const { return fragment.as_string (); }
+};
+
+class MatchedFragmentContainerRepetition : public MatchedFragmentContainer
+{
+ std::vector<std::unique_ptr<MatchedFragmentContainer>> fragments;
+
+public:
+ MatchedFragmentContainerRepetition () {}
size_t get_match_amount () const { return fragments.size (); }
- const std::vector<MatchedFragment> &get_fragments () const
+
+ std::vector<std::unique_ptr<MatchedFragmentContainer>> &get_fragments ()
{
return fragments;
}
- // const std::string &get_fragment_name () const { return fragment_name; }
- bool is_single_fragment () const
+ /**
+ * Add a matched fragment to the container
+ */
+ void add_fragment (MatchedFragment fragment)
{
- return get_match_amount () == 1 && kind == Kind::MetaVar;
+ fragments.emplace_back (metavar (fragment));
}
- const MatchedFragment get_single_fragment () const
- {
- rust_assert (is_single_fragment ());
+ virtual Kind get_kind () const { return Kind::Repetition; }
- return fragments[0];
+ virtual std::string as_string () const
+ {
+ std::string acc = "[";
+ for (size_t i = 0; i < fragments.size (); i++)
+ {
+ if (i)
+ acc += " ";
+ acc += fragments[i]->as_string ();
+ }
+ acc += "]";
+ return acc;
}
-
- const Kind &get_kind () const { return kind; }
-
-private:
- /**
- * Fragments matched `match_amount` times. This can be an empty vector
- * in case having zero matches is allowed (i.e ? or * operators)
- */
- std::vector<MatchedFragment> fragments;
- Kind kind;
};
class SubstitutionScope
@@ -159,14 +181,14 @@ public:
void push () { stack.push_back ({}); }
- std::map<std::string, MatchedFragmentContainer> pop ()
+ std::map<std::string, std::unique_ptr<MatchedFragmentContainer>> pop ()
{
- auto top = stack.back ();
+ auto top = std::move (stack.back ());
stack.pop_back ();
return top;
}
- std::map<std::string, MatchedFragmentContainer> &peek ()
+ std::map<std::string, std::unique_ptr<MatchedFragmentContainer>> &peek ()
{
return stack.back ();
}
@@ -180,8 +202,8 @@ public:
auto it = current_map.find (fragment.fragment_ident);
if (it == current_map.end ())
- current_map.insert ({fragment.fragment_ident,
- MatchedFragmentContainer::metavar (fragment)});
+ current_map.emplace (fragment.fragment_ident,
+ MatchedFragmentContainer::metavar (fragment));
else
gcc_unreachable ();
}
@@ -196,23 +218,28 @@ public:
auto it = current_map.find (fragment.fragment_ident);
if (it == current_map.end ())
- current_map.insert (
- {fragment.fragment_ident, MatchedFragmentContainer ({fragment})});
- else
- it->second.add_fragment (fragment);
+ it = current_map
+ .emplace (fragment.fragment_ident,
+ std::unique_ptr<MatchedFragmentContainer> (
+ new MatchedFragmentContainerRepetition ()))
+ .first;
+
+ it->second->add_fragment (fragment);
}
- void insert_matches (std::string key, MatchedFragmentContainer matches)
+ void insert_matches (std::string key,
+ std::unique_ptr<MatchedFragmentContainer> matches)
{
auto &current_map = stack.back ();
auto it = current_map.find (key);
rust_assert (it == current_map.end ());
- current_map.insert ({key, matches});
+ current_map.emplace (std::move (key), std::move (matches));
}
private:
- std::vector<std::map<std::string, MatchedFragmentContainer>> stack;
+ std::vector<std::map<std::string, std::unique_ptr<MatchedFragmentContainer>>>
+ stack;
};
// Object used to store shared data (between functions) for macro expansion.
@@ -269,7 +296,7 @@ struct MacroExpander
AST::Fragment transcribe_rule (
AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree,
- std::map<std::string, MatchedFragmentContainer> &matched_fragments,
+ std::map<std::string, MatchedFragmentContainer *> &matched_fragments,
bool semicolon, ContextType ctx);
bool match_fragment (Parser<MacroInvocLexer> &parser,
diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc
index 60e9b63..6eeb82b 100644
--- a/gcc/rust/expand/rust-macro-substitute-ctx.cc
+++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc
@@ -45,7 +45,7 @@ SubstituteCtx::substitute_metavar (
// currently expanding a repetition metavar - not a simple metavar. We
// need to error out and inform the user.
// Associated test case for an example: compile/macro-issue1224.rs
- if (it->second.get_match_amount () != 1)
+ if (!it->second->is_single_fragment ())
{
rust_error_at (metavar->get_locus (),
"metavariable is still repeating at this depth");
@@ -58,7 +58,7 @@ SubstituteCtx::substitute_metavar (
// We only care about the vector when expanding repetitions.
// Just access the first element of the vector.
- auto &frag = it->second.get_single_fragment ();
+ auto &frag = it->second->get_single_fragment ();
for (size_t offs = frag.token_offset_begin; offs < frag.token_offset_end;
offs++)
{
@@ -100,11 +100,14 @@ SubstituteCtx::check_repetition_amount (size_t pattern_start,
is_valid = false;
}
- auto &fragment = it->second;
+ auto &fragment = *it->second;
if (!fragment.is_single_fragment ())
{
- size_t repeat_amount = fragment.get_match_amount ();
+ auto &fragment_rep
+ = static_cast<MatchedFragmentContainerRepetition &> (
+ fragment);
+ size_t repeat_amount = fragment_rep.get_match_amount ();
if (!first_fragment_found)
{
first_fragment_found = true;
@@ -170,32 +173,18 @@ SubstituteCtx::substitute_repetition (
for (size_t i = 0; i < repeat_amount; i++)
{
- std::map<std::string, MatchedFragmentContainer> sub_map;
+ std::map<std::string, MatchedFragmentContainer *> sub_map;
for (auto &kv_match : fragments)
{
- MatchedFragment sub_fragment;
-
+ if (kv_match.second->is_single_fragment ())
+ sub_map.emplace (kv_match.first, kv_match.second);
// Hack: A repeating meta variable might not be present in the new
// macro. Don't include this match if the fragment doesn't have enough
// items, as check_repetition_amount should prevent repetition amount
// mismatches anyway.
- bool is_used = true;
-
- // FIXME: Hack: If a fragment is not repeated, how does it fit in the
- // submap? Do we really want to expand it? Is this normal behavior?
- if (kv_match.second.is_single_fragment ())
- sub_fragment = kv_match.second.get_single_fragment ();
- else
- {
- if (kv_match.second.get_fragments ().size () > i)
- sub_fragment = kv_match.second.get_fragments ().at (i);
- else
- is_used = false;
- }
-
- if (is_used)
- sub_map.insert ({kv_match.first,
- MatchedFragmentContainer::metavar (sub_fragment)});
+ else if (kv_match.second->get_fragments ().size () > i)
+ sub_map.emplace (kv_match.first,
+ kv_match.second->get_fragments ().at (i).get ());
}
auto substitute_context = SubstituteCtx (input, new_macro, sub_map);
diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.h b/gcc/rust/expand/rust-macro-substitute-ctx.h
index d8e4e31..70c76e4 100644
--- a/gcc/rust/expand/rust-macro-substitute-ctx.h
+++ b/gcc/rust/expand/rust-macro-substitute-ctx.h
@@ -24,7 +24,7 @@ class SubstituteCtx
{
std::vector<std::unique_ptr<AST::Token>> &input;
std::vector<std::unique_ptr<AST::Token>> &macro;
- std::map<std::string, MatchedFragmentContainer> &fragments;
+ std::map<std::string, MatchedFragmentContainer *> &fragments;
/**
* Find the repetition amount to use when expanding a repetition, and
@@ -40,7 +40,7 @@ class SubstituteCtx
public:
SubstituteCtx (std::vector<std::unique_ptr<AST::Token>> &input,
std::vector<std::unique_ptr<AST::Token>> &macro,
- std::map<std::string, MatchedFragmentContainer> &fragments)
+ std::map<std::string, MatchedFragmentContainer *> &fragments)
: input (input), macro (macro), fragments (fragments)
{}