From: Owen Avery Date: Thu, 1 Jun 2023 17:37:35 +0000 (-0400) Subject: gccrs: Make MatchedFragmentContainer a tree-like structure X-Git-Tag: basepoints/gcc-15~2454 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f1dbdb63dc78378aa91fb9e8bc1ff9401ef81c42;p=thirdparty%2Fgcc.git gccrs: 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 --- diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 225049ad2e4c..d14b3b3806a7 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 matched_fragments; + std::map> + 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 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> &tokens) AST::Fragment MacroExpander::transcribe_rule ( AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree, - std::map &matched_fragments, + std::map &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> ()}; } +MatchedFragment & +MatchedFragmentContainer::get_single_fragment () +{ + rust_assert (is_single_fragment ()); + + return static_cast (*this).get_fragment (); +} + +std::vector> & +MatchedFragmentContainer::get_fragments () +{ + rust_assert (!is_single_fragment ()); + + return static_cast (*this) + .get_fragments (); +} + +void +MatchedFragmentContainer::add_fragment (MatchedFragment fragment) +{ + rust_assert (!is_single_fragment ()); + + return static_cast (*this) + .add_fragment (fragment); +} + +std::unique_ptr +MatchedFragmentContainer::zero () +{ + return std::unique_ptr ( + new MatchedFragmentContainerRepetition ()); +} + +std::unique_ptr +MatchedFragmentContainer::metavar (MatchedFragment fragment) +{ + return std::unique_ptr ( + new MatchedFragmentContainerMetaVar (fragment)); +} + } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index 1e3da0b21721..ce8d0f2c7d4a 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 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 zero (); /** * Create a valid fragment matched one time */ - static MatchedFragmentContainer metavar (MatchedFragment fragment) - { - return MatchedFragmentContainer ({fragment}, Kind::MetaVar); - } + static std::unique_ptr + 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> &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> fragments; + +public: + MatchedFragmentContainerRepetition () {} size_t get_match_amount () const { return fragments.size (); } - const std::vector &get_fragments () const + + std::vector> &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 fragments; - Kind kind; }; class SubstitutionScope @@ -159,14 +181,14 @@ public: void push () { stack.push_back ({}); } - std::map pop () + std::map> pop () { - auto top = stack.back (); + auto top = std::move (stack.back ()); stack.pop_back (); return top; } - std::map &peek () + std::map> &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 ( + 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 matches) { auto ¤t_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> stack; + std::vector>> + 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 &matched_fragments, + std::map &matched_fragments, bool semicolon, ContextType ctx); bool match_fragment (Parser &parser, diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc index 60e9b63de947..6eeb82b10314 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 ( + 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 sub_map; + std::map 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 dd49bb1ddca1..835f48a3d984 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> &input; std::vector> ¯o; - std::map &fragments; + std::map &fragments; /** * Find the repetition amount to use when expanding a repetition, and @@ -40,7 +40,7 @@ class SubstituteCtx public: SubstituteCtx (std::vector> &input, std::vector> ¯o, - std::map &fragments) + std::map &fragments) : input (input), macro (macro), fragments (fragments) {}