Fragment::Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes,
std::vector<std::unique_ptr<AST::Token>> tokens)
- : kind (kind), nodes (std::move (nodes)), tokens (std::move (tokens)),
- overwrite (true)
+ : kind (kind), nodes (std::move (nodes)), tokens (std::move (tokens))
{}
Fragment::Fragment (Fragment const &other) : kind (other.get_kind ())
for (auto &t : other.tokens)
tokens.emplace_back (t->clone_token ());
- overwrite = other.overwrite;
-
return *this;
}
}
Fragment::Fragment (std::vector<AST::SingleASTNode> nodes,
- std::vector<std::unique_ptr<AST::Token>> tokens,
- bool overwrite)
+ std::vector<std::unique_ptr<AST::Token>> tokens)
: kind (FragmentKind::Complete), nodes (std::move (nodes)),
- tokens (std::move (tokens)), overwrite (overwrite)
+ tokens (std::move (tokens))
{}
Fragment::Fragment (std::vector<AST::SingleASTNode> nodes,
std::unique_ptr<AST::Token> token)
- : kind (FragmentKind::Complete), nodes (std::move (nodes)), overwrite (true)
+ : kind (FragmentKind::Complete), nodes (std::move (nodes))
{
tokens.emplace_back (std::move (token));
}
return !is_error ();
}
-bool
-Fragment::should_overwrite () const
-{
- return overwrite;
-}
-
bool
Fragment::is_expression_fragment () const
{
* Create a complete AST fragment
*/
Fragment (std::vector<AST::SingleASTNode> nodes,
- std::vector<std::unique_ptr<AST::Token>> tokens,
- bool overwrite = true);
+ std::vector<std::unique_ptr<AST::Token>> tokens);
/**
* Create a complete AST fragment made of a single token
bool is_error () const;
bool should_expand () const;
- bool should_overwrite () const;
bool is_expression_fragment () const;
bool is_type_fragment () const;
*/
std::vector<std::unique_ptr<AST::Token>> tokens;
- /**
- * Whether the fragment should overwrite the original content. In most case
- * it should overwrite it, but not with derive procedural macros.
- */
- bool overwrite;
-
/**
* We need to make a special case for Expression and Type fragments as only
* one Node will be extracted from the `nodes` vector
}
static std::unique_ptr<AST::Item>
-derive_item (std::unique_ptr<AST::Item> &item, const AST::Attribute &derive,
- BuiltinMacro to_derive)
+builtin_derive_item (std::unique_ptr<AST::Item> &item,
+ const AST::Attribute &derive, BuiltinMacro to_derive)
{
return AST::DeriveVisitor::derive (*item, derive, to_derive);
}
+static std::vector<std::unique_ptr<AST::Item>>
+derive_item (std::unique_ptr<AST::Item> &item, std::string &to_derive,
+ MacroExpander &expander)
+{
+ std::vector<std::unique_ptr<AST::Item>> result;
+ auto frag = expander.expand_derive_proc_macro (item, to_derive);
+ if (!frag.is_error ())
+ {
+ for (auto &node : frag.get_nodes ())
+ {
+ switch (node.get_kind ())
+ {
+ case AST::SingleASTNode::ITEM:
+ result.push_back (node.take_item ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ }
+ return result;
+}
+
void
ExpandVisitor::expand_inner_items (
std::vector<std::unique_ptr<AST::Item>> &items)
if (MacroBuiltin::builtins.is_iter_ok (maybe_builtin))
{
auto new_item
- = derive_item (item, attr, maybe_builtin->second);
+ = builtin_derive_item (item, attr, maybe_builtin->second);
// this inserts the derive *before* the item - is it a
// problem?
it = items.insert (it, std::move (new_item));
}
+ else
+ {
+ auto new_items = derive_item (item, name, expander);
+ std::move (new_items.begin (), new_items.end (),
+ std::inserter (items, it));
+ }
}
}
}
void
ExpandVisitor::visit (AST::StructStruct &struct_item)
{
- visit_attrs_with_derive (struct_item);
visit_outer_attrs (struct_item);
for (auto &generic : struct_item.get_generic_params ())
visit (generic);
ExpandVisitor::visit (AST::TupleStruct &tuple_struct)
{
visit_outer_attrs (tuple_struct);
- visit_attrs_with_derive (tuple_struct);
for (auto &generic : tuple_struct.get_generic_params ())
visit (generic);
void
ExpandVisitor::visit (AST::Enum &enum_item)
{
- visit_attrs_with_derive (enum_item);
visit_outer_attrs (enum_item);
for (auto &generic : enum_item.get_generic_params ())
visit (generic);
void
ExpandVisitor::visit (AST::Union &union_item)
{
- visit_attrs_with_derive (union_item);
visit_outer_attrs (union_item);
for (auto &generic : union_item.get_generic_params ())
visit (generic);
visit_inner_using_attrs (item, item.get_inner_attrs ());
}
-template <typename T>
-void
-ExpandVisitor::expand_derive (T &item, std::unique_ptr<AST::TokenTree> trait)
-{
- auto trait_name = trait->as_string ();
- expander.expand_derive_proc_macro (item, trait_name);
-}
-
-template <typename T>
-void
-ExpandVisitor::expand_derive (T &item, AST::DelimTokenTree &attr)
-{
- // Item is const because even though the tokenstream might be modified, it
- // should appear as the same input for every derive proc macro.
- auto &trees = attr.get_token_trees ();
- if (trees.size () > 2)
- {
- // Skipping begin and end parenthesis
- for (auto it = trees.begin () + 1; it < trees.end () - 1;
- it += 2 /* Increment + skip comma */)
- {
- expand_derive (item, std::move (*it));
- }
- }
-}
-
-template <typename T>
-void
-ExpandVisitor::visit_attrs_with_derive (T &item)
-{
- auto &attrs = item.get_outer_attrs ();
- for (auto it = attrs.begin (); it != attrs.end (); /* erase => No increment*/)
- {
- auto current = *it;
-
- if (!is_builtin (current) && is_derive (current))
- {
- it = attrs.erase (it);
- // Downcasting checked in is_derive
- expand_derive (item, static_cast<AST::DelimTokenTree &> (
- current.get_attr_input ()));
- }
- else // Skip unknwown
- {
- it++;
- }
- }
-}
} // namespace Rust
}
else if (proc_macro_fragment.should_expand ())
{
- if (proc_macro_fragment.should_overwrite ())
- it = values.erase (it);
- else
- it++;
+ it = values.erase (it);
for (auto &node : proc_macro_fragment.get_nodes ())
{
auto new_node = extractor (node);
template <typename T> void visit_inner_attrs (T &item);
- template <typename T>
- void expand_derive (T &item, std::unique_ptr<AST::TokenTree> trait);
-
- template <typename T> void expand_derive (T &item, AST::DelimTokenTree &attr);
-
- template <typename T> void visit_attrs_with_derive (T &item);
-
private:
MacroExpander &expander;
};
}
}
-void
-MacroExpander::parse_procmacro_output (ProcMacro::TokenStream ts, bool derive)
+AST::Fragment
+MacroExpander::parse_proc_macro_output (ProcMacro::TokenStream ts)
{
ProcMacroInvocLexer lex (convert (ts));
Parser<ProcMacroInvocLexer> parser (lex);
}
if (parser.has_errors ())
- set_expanded_proc_macro_fragment (AST::Fragment::create_error ());
+ return AST::Fragment::create_error ();
else
- set_expanded_proc_macro_fragment (
- {nodes, std::vector<std::unique_ptr<AST::Token>> (), !derive});
+ return {nodes, std::vector<std::unique_ptr<AST::Token>> ()};
}
} // namespace Rust
void import_proc_macros (std::string extern_crate);
template <typename T>
- void expand_derive_proc_macro (T &item, std::string &trait_name)
+ AST::Fragment expand_derive_proc_macro (T &item, std::string &trait_name)
{
ProcMacro::CustomDerive macro;
auto c = collector.collect_tokens ();
std::vector<const_TokenPtr> vec (c.cbegin (), c.cend ());
- parse_procmacro_output (macro.macro (convert (vec)), true);
+ return parse_proc_macro_output (macro.macro (convert (vec)));
}
template <typename T>
- void expand_bang_proc_macro (T &item, AST::SimplePath &path)
+ AST::Fragment expand_bang_proc_macro (T &item, AST::SimplePath &path)
{
ProcMacro::Bang macro;
auto c = collector.collect_tokens ();
std::vector<const_TokenPtr> vec (c.cbegin (), c.cend ());
- parse_procmacro_output (macro.macro (convert (vec)), false);
+ return parse_proc_macro_output (macro.macro (convert (vec)));
}
template <typename T>
std::vector<const_TokenPtr> vec (c.cbegin (), c.cend ());
// FIXME: Handle attributes
- parse_procmacro_output (
- macro.macro (ProcMacro::TokenStream::make_tokenstream (), convert (vec)),
- false);
+ parse_proc_macro_output (
+ macro.macro (ProcMacro::TokenStream::make_tokenstream (), convert (vec)));
}
/**
AST::MacroInvocation *get_last_invocation () { return last_invoc; }
private:
- void parse_procmacro_output (ProcMacro::TokenStream ts, bool derive);
+ AST::Fragment parse_proc_macro_output (ProcMacro::TokenStream ts);
AST::Crate &crate;
Session &session;