diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2020-12-25 16:25:40 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2020-12-25 16:25:40 +0800 |
commit | 7299d6d84ac4a1e8118915b00d361e7251e32b65 (patch) | |
tree | 0a386081e0b3ef3b21dd1e4c11692af70a8b6878 /gcc | |
parent | 627121b6996146d7b14f2ad848f416682b1ce0fe (diff) | |
download | gcc-7299d6d84ac4a1e8118915b00d361e7251e32b65.zip gcc-7299d6d84ac4a1e8118915b00d361e7251e32b65.tar.gz gcc-7299d6d84ac4a1e8118915b00d361e7251e32b65.tar.bz2 |
Test a new ASTFragment union representation
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/ast/rust-ast-full-test.cc | 14 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 56 | ||||
-rw-r--r-- | gcc/rust/ast/rust-macro.h | 143 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 35 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.h | 9 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/arrays3.rs (renamed from gcc/testsuite/rust.test/compilable/arrays2.rs) | 0 |
6 files changed, 209 insertions, 48 deletions
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index e6bcdb3..1329978 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -1358,9 +1358,9 @@ TypeAlias::as_string () const str += "\n Where clause: "; if (!has_where_clause ()) - str += "none"; + str += "none"; else - str += where_clause.as_string (); + str += where_clause.as_string (); str += "\n Type: " + existing_type->as_string (); @@ -5398,7 +5398,7 @@ Attribute::check_cfg_predicate (const Session &session) const if (!has_attr_input () || (path.as_string () != "cfg" && path.as_string () != "cfg_attr")) return false; - + // assume that it has already been parsed if (!is_parsed_to_meta_item ()) return false; @@ -5419,10 +5419,10 @@ Attribute::separate_cfg_attrs () const return attr_input->separate_cfg_attrs (); } -bool -Attribute::is_parsed_to_meta_item () const -{ - return has_attr_input () && attr_input->is_meta_item (); +bool +Attribute::is_parsed_to_meta_item () const +{ + return has_attr_input () && attr_input->is_meta_item (); } /* Visitor implementations - these are short but inlining can't happen anyway diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 8ca89fa..46dde8c 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -363,7 +363,9 @@ public: }; // path-to-string inverse comparison operator -inline bool operator!= (const SimplePath& lhs, const std::string &rhs) { +inline bool +operator!= (const SimplePath &lhs, const std::string &rhs) +{ return !(lhs == rhs); } @@ -632,7 +634,10 @@ public: // TODO: this mutable getter seems dodgy std::vector<std::unique_ptr<MetaItemInner> > &get_items () { return items; } - const std::vector<std::unique_ptr<MetaItemInner> > &get_items () const { return items; } + const std::vector<std::unique_ptr<MetaItemInner> > &get_items () const + { + return items; + } protected: // Use covariance to implement clone function as returning this type @@ -1371,7 +1376,7 @@ protected: virtual ExternalItem *clone_external_item_impl () const = 0; }; -/* Data structure to store the data used in macro invocations and macro +/* Data structure to store the data used in macro invocations and macro * invocations with semicolons. */ struct MacroInvocData { @@ -1386,11 +1391,15 @@ private: public: std::string as_string () const; - MacroInvocData (SimplePath path, DelimTokenTree token_tree) - : path (std::move (path)), token_tree (std::move (token_tree)) {} - + MacroInvocData (SimplePath path, DelimTokenTree token_tree) + : path (std::move (path)), token_tree (std::move (token_tree)) + {} + // Copy constructor with vector clone - MacroInvocData (const MacroInvocData &other) : path (other.path), token_tree (other.token_tree), parsed_to_meta_item (other.parsed_to_meta_item) { + MacroInvocData (const MacroInvocData &other) + : path (other.path), token_tree (other.token_tree), + parsed_to_meta_item (other.parsed_to_meta_item) + { parsed_items.reserve (other.parsed_items.size ()); for (const auto &e : other.parsed_items) parsed_items.push_back (e->clone_meta_item_inner ()); @@ -1413,7 +1422,7 @@ public: // Move constructors MacroInvocData (MacroInvocData &&other) = default; MacroInvocData &operator= (MacroInvocData &&other) = default; - + // Invalid if path is empty, so base stripping on that. void mark_for_strip () { path = SimplePath::create_empty (); } bool is_marked_for_strip () const { return path.is_empty (); } @@ -1430,13 +1439,20 @@ public: SimplePath &get_path () { return path; } const SimplePath &get_path () const { return path; } - void set_meta_item_output (std::vector<std::unique_ptr<MetaItemInner> > new_items) - { - parsed_items = std::move (new_items); + void + set_meta_item_output (std::vector<std::unique_ptr<MetaItemInner> > new_items) + { + parsed_items = std::move (new_items); } // TODO: mutable getter seems kinda dodgy - std::vector<std::unique_ptr<MetaItemInner> > &get_meta_items () { return parsed_items; } - const std::vector<std::unique_ptr<MetaItemInner> > &get_meta_items () const { return parsed_items; } + std::vector<std::unique_ptr<MetaItemInner> > &get_meta_items () + { + return parsed_items; + } + const std::vector<std::unique_ptr<MetaItemInner> > &get_meta_items () const + { + return parsed_items; + } }; /* A macro invocation item (or statement) AST node (i.e. semi-coloned macro @@ -1467,10 +1483,11 @@ public: delim_type (delim_type), token_trees (std::move (token_trees)), locus (locus) {}*/ - MacroInvocationSemi (MacroInvocData invoc_data, - std::vector<Attribute> outer_attrs, Location locus) - : outer_attrs (std::move (outer_attrs)), invoc_data (std::move (invoc_data)), - locus (locus) {} + MacroInvocationSemi (MacroInvocData invoc_data, + std::vector<Attribute> outer_attrs, Location locus) + : outer_attrs (std::move (outer_attrs)), + invoc_data (std::move (invoc_data)), locus (locus) + {} /* // Copy constructor with vector clone @@ -1525,7 +1542,10 @@ public: bool is_marked_for_strip () const override { return path.is_empty (); } */ void mark_for_strip () override { invoc_data.mark_for_strip (); } - bool is_marked_for_strip () const override { return invoc_data.is_marked_for_strip (); } + bool is_marked_for_strip () const override + { + return invoc_data.is_marked_for_strip (); + } // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 3971572..eeb8ecf 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -349,11 +349,12 @@ public: : ExprWithoutBlock (std::move (outer_attrs)), path (std::move (path)), token_tree (std::move (token_tree)), locus (locus) {}*/ - MacroInvocation (MacroInvocData invoc_data, - std::vector<Attribute> outer_attrs, Location locus) - : ExprWithoutBlock (std::move (outer_attrs)), - invoc_data (std::move (invoc_data)), locus (locus) {} - + MacroInvocation (MacroInvocData invoc_data, + std::vector<Attribute> outer_attrs, Location locus) + : ExprWithoutBlock (std::move (outer_attrs)), + invoc_data (std::move (invoc_data)), locus (locus) + {} + Location get_locus () const { return locus; } Location get_locus_slow () const final override { return get_locus (); } @@ -361,7 +362,10 @@ public: // Invalid if path is empty, so base stripping on that. void mark_for_strip () override { invoc_data.mark_for_strip (); } - bool is_marked_for_strip () const override { return invoc_data.is_marked_for_strip (); } + bool is_marked_for_strip () const override + { + return invoc_data.is_marked_for_strip (); + } protected: /* Use covariance to implement clone function as returning this object rather @@ -586,6 +590,133 @@ protected: } }; +/* A "tagged union" describing a single AST node. Due to technical difficulties + * with unions, had to use raw pointers. */ +struct SingleASTNode +{ + public: + union { + std::unique_ptr<Expr> expr; + std::unique_ptr<Stmt> stmt; + std::unique_ptr<Item> item; + std::unique_ptr<Type> type; + std::unique_ptr<Pattern> pattern; + std::unique_ptr<TraitItem> trait_item; + std::unique_ptr<InherentImplItem> inherent_impl_item; + std::unique_ptr<TraitImplItem> trait_impl_item; + std::unique_ptr<ExternalItem> external_item; + }; + + enum tag_types { + EXPR, + STMT, + ITEM, + TYPE, + PATTERN, + TRAIT_ITEM, + INHERENT_IMPL_ITEM, + TRAIT_IMPL_ITEM, + EXTERNAL_ITEM + // TODO: other types like inside macro_rules? + }; + + SingleASTNode (std::unique_ptr<Expr> expr) : tag (EXPR), expr (std::move (expr)) { + + } + + SingleASTNode (std::unique_ptr<Stmt> stmt) : tag (STMT), stmt (std::move (stmt)) { + + } + + SingleASTNode (std::unique_ptr<Item> item) : tag (ITEM), item (std::move (item)) { + + } + + SingleASTNode (std::unique_ptr<Type> type) : tag (TYPE), type (std::move (type)) { + + } + + SingleASTNode (std::unique_ptr<Pattern> pattern) : tag (PATTERN), pattern (std::move (pattern)) { + + } + + SingleASTNode (std::unique_ptr<TraitItem> trait_item) : tag (TRAIT_ITEM), trait_item (std::move (trait_item)) { + + } + + SingleASTNode (std::unique_ptr<InherentImplItem> inherent_impl_item) : tag (INHERENT_IMPL_ITEM), inherent_impl_item (std::move (inherent_impl_item)) { + + } + + SingleASTNode (std::unique_ptr<TraitImplItem> trait_impl_item) : tag (TRAIT_IMPL_ITEM), trait_impl_item (std::move (trait_impl_item)) { + + } + + SingleASTNode (std::unique_ptr<ExternalItem> external_item) : tag (EXTERNAL_ITEM), external_item (std::move (external_item)) { + + } + + ~SingleASTNode () { + switch (tag) { + case EXPR: + expr.~unique_ptr<Expr> (); + break; + case STMT: + stmt.~unique_ptr<Stmt> (); + break; + case ITEM: + item.~unique_ptr<Item> (); + break; + case TYPE: + type.~unique_ptr<Type> (); + break; + case PATTERN: + pattern.~unique_ptr<Pattern> (); + break; + case TRAIT_ITEM: + trait_item.~unique_ptr<TraitItem> (); + break; + case INHERENT_IMPL_ITEM: + inherent_impl_item.~unique_ptr<InherentImplItem> (); + break; + case TRAIT_IMPL_ITEM: + trait_impl_item.~unique_ptr<TraitImplItem> (); + break; + case EXTERNAL_ITEM: + external_item.~unique_ptr<ExternalItem> (); + break; + default: + // should not happen + gcc_unreachable (); + break; + } + } + + private: + tag_types tag; + +}; + +/* Basically, a "fragment" that can be incorporated into the AST, created as + * a result of macro expansion. Really annoying to work with due to the fact + * that macros can really expand to anything. As such, horrible representation + * at the moment. */ +struct ASTFragment +{ +private: + /* basic idea: essentially, a vector of tagged unions of different AST node + * types. Now, this could actually be stored without a tagged union if the + * different AST node types had a unified parent, but that would create + * issues with the diamond problem or significant performance penalties. So + * a tagged union had to be used instead. A vector is used to represent the + * ability for a macro to expand to two statements, for instance. */ + + std::vector<SingleASTNode> nodes; + +public: + ASTFragment (std::vector<SingleASTNode> nodes) : nodes (std::move (nodes)) {} +}; + // Object that parses macros from a token stream. /* TODO: would "AttributeParser" be a better name? MetaItems are only for * attributes, I believe */ diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 97e455e..02dcf87 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -3561,17 +3561,18 @@ MacroExpander::parse_macro_to_meta_item (AST::MacroInvocData &invoc) std::unique_ptr<AST::AttrInputMetaItemContainer> converted_input ( invoc.get_delim_tok_tree ().parse_to_meta_item ()); - - if (converted_input == nullptr) - { - fprintf (stderr, "DEBUG: failed to parse macro to meta item\n"); - // TODO: do something now? is this an actual error? - } + + if (converted_input == nullptr) + { + fprintf (stderr, "DEBUG: failed to parse macro to meta item\n"); + // TODO: do something now? is this an actual error? + } else - { - std::vector<std::unique_ptr<AST::MetaItemInner> > meta_items (std::move (converted_input->get_items ())); - invoc.set_meta_item_output (std::move (meta_items)); - } + { + std::vector<std::unique_ptr<AST::MetaItemInner> > meta_items ( + std::move (converted_input->get_items ())); + invoc.set_meta_item_output (std::move (meta_items)); + } } AST::Literal @@ -3583,17 +3584,23 @@ MacroExpander::expand_cfg_macro (AST::MacroInvocData &invoc) parse_macro_to_meta_item (invoc); - // TODO: assuming that cfg! macros can only have one meta item inner, like cfg attributes - if (invoc.get_meta_items ().size () != 1) + /* TODO: assuming that cfg! macros can only have one meta item inner, like cfg + * attributes */ + if (invoc.get_meta_items ().size () != 1) return AST::Literal::create_error (); - + bool result = invoc.get_meta_items ()[0]->check_cfg_predicate (session); if (result) return AST::Literal ("true", AST::Literal::BOOL); - else + else return AST::Literal ("false", AST::Literal::BOOL); } +AST::ASTFragment +MacroExpander::expand_decl_macro (AST::MacroInvocData &invoc, AST::MacroRulesDefinition &rules_def) { + +} + void MacroExpander::expand_invoc (std::unique_ptr<AST::MacroInvocation> &invoc) { diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index 0218600..66e506d 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -16,9 +16,9 @@ struct ExpansionCfg { // features? unsigned int recursion_limit = 50; // TODO: determine default recursion limit - // trace macros? - // should test? - // more default stuff? + // trace macros? + // should test? + // more default stuff? }; // Object used to store shared data (between functions) for macro expansion. @@ -41,6 +41,9 @@ struct MacroExpander // should this be public or private? void expand_invoc (std::unique_ptr<AST::MacroInvocation> &invoc); + // Expands a single declarative macro. + AST::ASTFragment expand_decl_macro (AST::MacroInvocData &invoc, AST::MacroRulesDefinition &rules_def); + void expand_cfg_attrs (std::vector<AST::Attribute> &attrs); bool fails_cfg (const std::vector<AST::Attribute> &attr) const; bool fails_cfg_with_expand (std::vector<AST::Attribute> &attrs) const; diff --git a/gcc/testsuite/rust.test/compilable/arrays2.rs b/gcc/testsuite/rust.test/compilable/arrays3.rs index 974e346..974e346 100644 --- a/gcc/testsuite/rust.test/compilable/arrays2.rs +++ b/gcc/testsuite/rust.test/compilable/arrays3.rs |