From 9035128b75b9c8b4465e33bafed43649046534b6 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 25 May 2023 15:46:47 +0200 Subject: [PATCH] gccrs: expand: Derive statements Expand procedural macros on statements properly. gcc/rust/ChangeLog: * expand/rust-expand-visitor.cc : Change type from pointer to reference and expand statements from statements. * ast/rust-macro.h: Return macro kind. * ast/rust-ast.h: Add Statement kind. * ast/rust-item.h: Change module. * ast/rust-stmt.h: Return kind. Co-authored-by: Pierre-Emmanuel Patry Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-ast.h | 15 ++- gcc/rust/ast/rust-item.h | 2 +- gcc/rust/ast/rust-macro.h | 10 +- gcc/rust/ast/rust-stmt.h | 5 + gcc/rust/expand/rust-expand-visitor.cc | 134 +++++++++++++++++++------ 5 files changed, 129 insertions(+), 37 deletions(-) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 3c1f95a973f4..893b4bb17b91 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -884,6 +884,15 @@ class MetaListNameValueStr; class Stmt : public Node { public: + enum class Kind + { + Empty, + Item, + Let, + Expr, + MacroInvocation, + }; + // Unique pointer custom clone function std::unique_ptr clone_stmt () const { @@ -900,8 +909,10 @@ public: virtual bool is_marked_for_strip () const = 0; NodeId get_node_id () const { return node_id; } - virtual bool is_item () const = 0; + virtual Kind get_stmt_kind () = 0; + // TODO: Can we remove these two? + virtual bool is_item () const = 0; virtual bool is_expr () const { return false; } virtual void add_semicolon () {} @@ -931,6 +942,8 @@ public: add_crate_name (std::vector &names ATTRIBUTE_UNUSED) const {} + Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Item; } + // FIXME: ARTHUR: Is it okay to have removed that final? Is it *required* // behavior that we have items that can also be expressions? bool is_item () const override { return true; } diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 574f1fa3a653..4563f61b3940 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1003,7 +1003,7 @@ public: Identifier get_name () const { return module_name; } - Kind get_ast_kind () const override { return Kind::MODULE; } + AST::Kind get_ast_kind () const override { return AST::Kind::MODULE; } private: Identifier module_name; diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index a0d1adc7de19..77c9b8479bf4 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -571,7 +571,10 @@ public: is_builtin_rule = true; } - Kind get_ast_kind () const override { return Kind::MACRO_RULES_DEFINITION; } + AST::Kind get_ast_kind () const override + { + return AST::Kind::MACRO_RULES_DEFINITION; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -670,7 +673,10 @@ public: return ExprWithoutBlock::get_node_id (); } - Kind get_ast_kind () const override { return Kind::MACRO_INVOCATION; } + AST::Kind get_ast_kind () const override + { + return AST::Kind::MACRO_INVOCATION; + } NodeId get_macro_node_id () const { return node_id; } diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 95a5a62bfa4a..80395ab72ceb 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -48,6 +48,8 @@ public: bool is_item () const override final { return false; } + Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Empty; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -172,6 +174,7 @@ public: } bool is_item () const override final { return false; } + Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Let; } protected: /* Use covariance to implement clone function as returning this object rather @@ -199,6 +202,8 @@ public: std::string as_string () const override; + Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Expr; } + std::vector locals; ExprStmt (std::unique_ptr &&expr, Location locus, diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index 9183a63b9a9f..e9eefdb59f11 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -97,14 +97,14 @@ get_traits_to_derive (AST::Attribute &attr) } static std::unique_ptr -builtin_derive_item (std::unique_ptr &item, - const AST::Attribute &derive, BuiltinMacro to_derive) +builtin_derive_item (AST::Item &item, const AST::Attribute &derive, + BuiltinMacro to_derive) { - return AST::DeriveVisitor::derive (*item, derive, to_derive); + return AST::DeriveVisitor::derive (item, derive, to_derive); } static std::vector> -derive_item (std::unique_ptr &item, const std::string &to_derive, +derive_item (AST::Item &item, const std::string &to_derive, MacroExpander &expander) { std::vector> result; @@ -127,8 +127,8 @@ derive_item (std::unique_ptr &item, const std::string &to_derive, } static std::vector> -expand_attribute (std::unique_ptr &item, AST::SimplePath &name, - MacroExpander &expander) +expand_item_attribute (AST::Item &item, AST::SimplePath &name, + MacroExpander &expander) { std::vector> result; auto frag = expander.expand_attribute_proc_macro (item, name); @@ -149,6 +149,29 @@ expand_attribute (std::unique_ptr &item, AST::SimplePath &name, return result; } +static std::vector> +expand_stmt_attribute (AST::Item &item, AST::SimplePath &name, + MacroExpander &expander) +{ + std::vector> result; + auto frag = expander.expand_attribute_proc_macro (item, name); + if (!frag.is_error ()) + { + for (auto &node : frag.get_nodes ()) + { + switch (node.get_kind ()) + { + case AST::SingleASTNode::STMT: + result.push_back (node.take_stmt ()); + break; + default: + gcc_unreachable (); + } + } + } + return result; +} + void ExpandVisitor::expand_inner_items ( std::vector> &items) @@ -179,7 +202,7 @@ ExpandVisitor::expand_inner_items ( if (MacroBuiltin::builtins.is_iter_ok (maybe_builtin)) { auto new_item - = builtin_derive_item (item, current, + = builtin_derive_item (*item, current, maybe_builtin->second); // this inserts the derive *before* the item - is it a // problem? @@ -188,7 +211,7 @@ ExpandVisitor::expand_inner_items ( else { auto new_items - = derive_item (item, to_derive, expander); + = derive_item (*item, to_derive, expander); std::move (new_items.begin (), new_items.end (), std::inserter (items, it)); } @@ -204,8 +227,8 @@ ExpandVisitor::expand_inner_items ( { attr_it = attrs.erase (attr_it); auto new_items - = expand_attribute (item, current.get_path (), - expander); + = expand_item_attribute (*item, current.get_path (), + expander); it = items.erase (it); std::move (new_items.begin (), new_items.end (), std::inserter (items, it)); @@ -236,29 +259,74 @@ ExpandVisitor::expand_inner_stmts ( for (auto it = stmts.begin (); it != stmts.end (); it++) { - // TODO: Eventually we need to derive here as well - - // auto &stmt = *it; - - // if (stmt->has_outer_attrs ()) - // { - // auto traits_to_derive - // = get_traits_to_derive (stmt->get_outer_attrs ()); - - // // FIXME: This needs to be reworked absolutely - // static const std::set builtin_derives - // = {"Clone", "Copy", "Eq", "PartialEq", "Ord", "PartialOrd"}; - - // for (auto &to_derive : traits_to_derive) - // if (builtin_derives.find (to_derive) != builtin_derives.end ()) - // { - // auto new_item = derive_item ( - // item, item->get_outer_attrs ()[0] /* FIXME: This is wrong */, - // to_derive); - // // this inserts the derive *before* the item - is it a problem? - // it = items.insert (it, std::move (new_item)); - // } - // } + auto &stmt = *it; + + // skip all non-item statements + if (stmt->get_stmt_kind () != AST::Stmt::Kind::Item) + continue; + + auto &item = static_cast (*stmt.get ()); + + if (item.has_outer_attrs ()) + { + auto &attrs = item.get_outer_attrs (); + + for (auto attr_it = attrs.begin (); attr_it != attrs.end (); + /* erase => No increment*/) + { + auto current = *attr_it; + + if (is_derive (current)) + { + attr_it = attrs.erase (attr_it); + // Get traits to derive in the current attribute + auto traits_to_derive = get_traits_to_derive (current); + for (auto &to_derive : traits_to_derive) + { + auto maybe_builtin + = MacroBuiltin::builtins.lookup (to_derive); + if (MacroBuiltin::builtins.is_iter_ok (maybe_builtin)) + { + auto new_item + = builtin_derive_item (item, current, + maybe_builtin->second); + // this inserts the derive *before* the item - is it a + // problem? + it = stmts.insert (it, std::move (new_item)); + } + else + { + auto new_items + = derive_item (item, to_derive, expander); + std::move (new_items.begin (), new_items.end (), + std::inserter (stmts, it)); + } + } + } + else /* Attribute */ + { + if (is_builtin (current)) + { + attr_it++; + } + else + { + attr_it = attrs.erase (attr_it); + auto new_items + = expand_stmt_attribute (item, current.get_path (), + expander); + it = stmts.erase (it); + std::move (new_items.begin (), new_items.end (), + std::inserter (stmts, it)); + // TODO: Improve this ? + // item is invalid since it refers to now deleted, + // cancel the loop increment and break. + it--; + break; + } + } + } + } } std::function (AST::SingleASTNode)> extractor -- 2.47.2