return expr;
}
+ std::unique_ptr<Expr> take_tail_expr ()
+ {
+ rust_assert (has_tail_expr ());
+ return std::move (expr);
+ }
+
+ void set_tail_expr (std::unique_ptr<Expr> expr)
+ {
+ this->expr = std::move (expr);
+ }
+
// Removes the tail expression from the block.
void strip_tail_expr () { expr = nullptr; }
// Normalizes a trailing statement without a semicolon to a tail expression.
return result;
}
+template <typename T>
static std::vector<std::unique_ptr<AST::Stmt>>
-expand_stmt_attribute (AST::Item &item, AST::SimplePath &name,
- MacroExpander &expander)
+expand_stmt_attribute (T &item, AST::SimplePath &name, MacroExpander &expander)
{
std::vector<std::unique_ptr<AST::Stmt>> result;
auto frag = expander.expand_attribute_proc_macro (item, name);
return result;
}
+void
+expand_tail_expr (AST::BlockExpr &item, MacroExpander &expander)
+{
+ if (item.has_tail_expr ())
+ {
+ auto tail = item.take_tail_expr ();
+ auto attrs = tail->get_outer_attrs ();
+ bool changed = false;
+ for (auto it = attrs.begin (); it != attrs.end ();)
+ {
+ auto current = *it;
+ if (is_builtin (current))
+ {
+ it++;
+ }
+ else
+ {
+ it = attrs.erase (it);
+ changed = true;
+ auto new_stmts
+ = expand_stmt_attribute (item, current.get_path (), expander);
+ auto &stmts = item.get_statements ();
+ std::move (new_stmts.begin (), new_stmts.end (),
+ std::inserter (stmts, stmts.end ()));
+ }
+ }
+ if (changed)
+ item.strip_tail_expr ();
+ else
+ item.set_tail_expr (std::move (tail));
+ }
+}
+
void
ExpandVisitor::expand_inner_items (
std::vector<std::unique_ptr<AST::Item>> &items)
{
expand_inner_stmts (expr.get_statements ());
+ expand_tail_expr (expr, expander);
if (expr.has_tail_expr ())
maybe_expand_expr (expr.get_tail_expr ());
}