aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/expand/rust-macro-expand.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/expand/rust-macro-expand.cc')
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc87
1 files changed, 53 insertions, 34 deletions
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index fe20560..e7407a4 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -18,15 +18,17 @@
#include "rust-macro-expand.h"
#include "optional.h"
+#include "rust-ast-fragment.h"
#include "rust-macro-substitute-ctx.h"
#include "rust-ast-full.h"
#include "rust-ast-visitor.h"
#include "rust-diagnostics.h"
+#include "rust-macro.h"
#include "rust-parse.h"
#include "rust-cfg-strip.h"
#include "rust-early-name-resolver.h"
-#include "rust-session-manager.h"
#include "rust-proc-macro.h"
+#include "rust-token-tree-desugar.h"
namespace Rust {
@@ -34,7 +36,7 @@ AST::Fragment
MacroExpander::expand_decl_macro (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::MacroRulesDefinition &rules_def,
- bool semicolon)
+ AST::InvocKind semicolon)
{
// ensure that both invocation and rules are in a valid state
rust_assert (!invoc.is_marked_for_strip ());
@@ -43,9 +45,10 @@ MacroExpander::expand_decl_macro (location_t invoc_locus,
/* probably something here about parsing invoc and rules def token trees to
* token stream. if not, how would parser handle the captures of exprs and
- * stuff? on the other hand, token trees may be kind of useful in rules def as
- * creating a point where recursion can occur (like having
- * "compare_macro_match" and then it calling itself when it finds delimiters)
+ * stuff? on the other hand, token trees may be kind of useful in rules def
+ * as creating a point where recursion can occur (like having
+ * "compare_macro_match" and then it calling itself when it finds
+ * delimiters)
*/
/* find matching rule to invoc token tree, based on macro rule's matcher. if
@@ -70,12 +73,16 @@ MacroExpander::expand_decl_macro (location_t invoc_locus,
/* TODO: it is probably better to modify AST::Token to store a pointer to a
* Lexer::Token (rather than being converted) - i.e. not so much have
- * AST::Token as a Token but rather a TokenContainer (as it is another type of
- * TokenTree). This will prevent re-conversion of Tokens between each type
- * all the time, while still allowing the heterogenous storage of token trees.
+ * AST::Token as a Token but rather a TokenContainer (as it is another type
+ * of TokenTree). This will prevent re-conversion of Tokens between each
+ * type all the time, while still allowing the heterogenous storage of token
+ * trees.
*/
- AST::DelimTokenTree &invoc_token_tree = invoc.get_delim_tok_tree ();
+ AST::DelimTokenTree &invoc_token_tree_sugar = invoc.get_delim_tok_tree ();
+
+ // We must first desugar doc comments into proper attributes
+ auto invoc_token_tree = AST::TokenTreeDesugar ().go (invoc_token_tree_sugar);
// find matching arm
AST::MacroRule *matched_rule = nullptr;
@@ -116,7 +123,7 @@ MacroExpander::expand_decl_macro (location_t invoc_locus,
for (auto &ent : matched_fragments)
matched_fragments_ptr.emplace (ent.first, ent.second.get ());
- return transcribe_rule (*matched_rule, invoc_token_tree,
+ return transcribe_rule (rules_def, *matched_rule, invoc_token_tree,
matched_fragments_ptr, semicolon, peek_context ());
}
@@ -199,7 +206,7 @@ MacroExpander::expand_eager_invocations (AST::MacroInvocation &invoc)
for (auto kv : substitution_map)
{
auto &to_expand = kv.second;
- expand_invoc (*to_expand, false);
+ expand_invoc (*to_expand, AST::InvocKind::Expr);
auto fragment = take_expanded_fragment ();
auto &new_tokens = fragment.get_tokens ();
@@ -237,7 +244,8 @@ MacroExpander::expand_eager_invocations (AST::MacroInvocation &invoc)
}
void
-MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
+MacroExpander::expand_invoc (AST::MacroInvocation &invoc,
+ AST::InvocKind semicolon)
{
if (depth_exceeds_recursion_limit ())
{
@@ -246,7 +254,12 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
}
if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
- expand_eager_invocations (invoc);
+ {
+ // Eager expansions are always expressions
+ push_context (ContextType::EXPR);
+ expand_eager_invocations (invoc);
+ pop_context ();
+ }
AST::MacroInvocData &invoc_data = invoc.get_invoc_data ();
@@ -272,26 +285,28 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
invoc_data.set_expander (this);
// lookup the rules
- AST::MacroRulesDefinition *rules_def = nullptr;
- bool ok = mappings->lookup_macro_invocation (invoc, &rules_def);
+ auto rules_def = mappings.lookup_macro_invocation (invoc);
// If there's no rule associated with the invocation, we can simply return
// early. The early name resolver will have already emitted an error.
- if (!ok)
+ if (!rules_def)
return;
+ auto rdef = rules_def.value ();
+
// We store the last expanded invocation and macro definition for error
// reporting in case the recursion limit is reached
last_invoc = *invoc.clone_macro_invocation_impl ();
- last_def = *rules_def;
+ last_def = *rdef;
- if (rules_def->is_builtin ())
- fragment
- = rules_def->get_builtin_transcriber () (invoc.get_locus (), invoc_data)
- .value_or (AST::Fragment::create_empty ());
+ if (rdef->is_builtin ())
+ fragment = rdef
+ ->get_builtin_transcriber () (invoc.get_locus (), invoc_data,
+ semicolon)
+ .value_or (AST::Fragment::create_empty ());
else
- fragment = expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def,
- has_semicolon);
+ fragment
+ = expand_decl_macro (invoc.get_locus (), invoc_data, *rdef, semicolon);
set_expanded_fragment (std::move (fragment));
}
@@ -610,9 +625,10 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
// matched fragment get the offset in the token stream
size_t offs_end = source.get_offs ();
- sub_stack.insert_metavar (
- MatchedFragment (fragment->get_ident ().as_string (),
- offs_begin, offs_end));
+ if (valid_current_match)
+ sub_stack.insert_metavar (
+ MatchedFragment (fragment->get_ident ().as_string (),
+ offs_begin, offs_end));
}
break;
@@ -639,15 +655,15 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
}
auto old_stack = sub_stack.pop ();
- // nest metavars into repetitions
- for (auto &ent : old_stack)
- sub_stack.append_fragment (ent.first, std::move (ent.second));
-
// If we've encountered an error once, stop trying to match more
// repetitions
if (!valid_current_match)
break;
+ // nest metavars into repetitions
+ for (auto &ent : old_stack)
+ sub_stack.append_fragment (ent.first, std::move (ent.second));
+
match_amount++;
// Break early if we notice there's too many expressions already
@@ -1013,10 +1029,13 @@ 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,
+ AST::MacroRulesDefinition &definition, AST::MacroRule &match_rule,
+ AST::DelimTokenTree &invoc_token_tree,
std::map<std::string, MatchedFragmentContainer *> &matched_fragments,
- bool semicolon, ContextType ctx)
+ AST::InvocKind invoc_kind, ContextType ctx)
{
+ bool semicolon = invoc_kind == AST::InvocKind::Semicoloned;
+
// we can manipulate the token tree to substitute the dollar identifiers so
// that when we call parse its already substituted for us
AST::MacroTranscriber &transcriber = match_rule.get_transcriber ();
@@ -1025,8 +1044,8 @@ MacroExpander::transcribe_rule (
auto invoc_stream = invoc_token_tree.to_token_stream ();
auto macro_rule_tokens = transcribe_tree.to_token_stream ();
- auto substitute_context
- = SubstituteCtx (invoc_stream, macro_rule_tokens, matched_fragments);
+ auto substitute_context = SubstituteCtx (invoc_stream, macro_rule_tokens,
+ matched_fragments, definition);
std::vector<std::unique_ptr<AST::Token>> substituted_tokens
= substitute_context.substitute_tokens ();