From 7299d6d84ac4a1e8118915b00d361e7251e32b65 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Fri, 25 Dec 2020 16:25:40 +0800 Subject: Test a new ASTFragment union representation --- gcc/rust/ast/rust-ast-full-test.cc | 14 +-- gcc/rust/ast/rust-ast.h | 56 ++++++---- gcc/rust/ast/rust-macro.h | 143 ++++++++++++++++++++++++-- gcc/rust/expand/rust-macro-expand.cc | 35 ++++--- gcc/rust/expand/rust-macro-expand.h | 9 +- gcc/testsuite/rust.test/compilable/arrays2.rs | 66 ------------ gcc/testsuite/rust.test/compilable/arrays3.rs | 66 ++++++++++++ 7 files changed, 275 insertions(+), 114 deletions(-) delete mode 100644 gcc/testsuite/rust.test/compilable/arrays2.rs create mode 100644 gcc/testsuite/rust.test/compilable/arrays3.rs 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 > &get_items () { return items; } - const std::vector > &get_items () const { return items; } + const std::vector > &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 > new_items) - { - parsed_items = std::move (new_items); + void + set_meta_item_output (std::vector > new_items) + { + parsed_items = std::move (new_items); } // TODO: mutable getter seems kinda dodgy - std::vector > &get_meta_items () { return parsed_items; } - const std::vector > &get_meta_items () const { return parsed_items; } + std::vector > &get_meta_items () + { + return parsed_items; + } + const std::vector > &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 outer_attrs, Location locus) - : outer_attrs (std::move (outer_attrs)), invoc_data (std::move (invoc_data)), - locus (locus) {} + MacroInvocationSemi (MacroInvocData invoc_data, + std::vector 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 &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 outer_attrs, Location locus) - : ExprWithoutBlock (std::move (outer_attrs)), - invoc_data (std::move (invoc_data)), locus (locus) {} - + MacroInvocation (MacroInvocData invoc_data, + std::vector 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; + std::unique_ptr stmt; + std::unique_ptr item; + std::unique_ptr type; + std::unique_ptr pattern; + std::unique_ptr trait_item; + std::unique_ptr inherent_impl_item; + std::unique_ptr trait_impl_item; + std::unique_ptr 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) : tag (EXPR), expr (std::move (expr)) { + + } + + SingleASTNode (std::unique_ptr stmt) : tag (STMT), stmt (std::move (stmt)) { + + } + + SingleASTNode (std::unique_ptr item) : tag (ITEM), item (std::move (item)) { + + } + + SingleASTNode (std::unique_ptr type) : tag (TYPE), type (std::move (type)) { + + } + + SingleASTNode (std::unique_ptr pattern) : tag (PATTERN), pattern (std::move (pattern)) { + + } + + SingleASTNode (std::unique_ptr trait_item) : tag (TRAIT_ITEM), trait_item (std::move (trait_item)) { + + } + + SingleASTNode (std::unique_ptr inherent_impl_item) : tag (INHERENT_IMPL_ITEM), inherent_impl_item (std::move (inherent_impl_item)) { + + } + + SingleASTNode (std::unique_ptr trait_impl_item) : tag (TRAIT_IMPL_ITEM), trait_impl_item (std::move (trait_impl_item)) { + + } + + SingleASTNode (std::unique_ptr external_item) : tag (EXTERNAL_ITEM), external_item (std::move (external_item)) { + + } + + ~SingleASTNode () { + switch (tag) { + case EXPR: + expr.~unique_ptr (); + break; + case STMT: + stmt.~unique_ptr (); + break; + case ITEM: + item.~unique_ptr (); + break; + case TYPE: + type.~unique_ptr (); + break; + case PATTERN: + pattern.~unique_ptr (); + break; + case TRAIT_ITEM: + trait_item.~unique_ptr (); + break; + case INHERENT_IMPL_ITEM: + inherent_impl_item.~unique_ptr (); + break; + case TRAIT_IMPL_ITEM: + trait_impl_item.~unique_ptr (); + break; + case EXTERNAL_ITEM: + external_item.~unique_ptr (); + 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 nodes; + +public: + ASTFragment (std::vector 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 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 > meta_items (std::move (converted_input->get_items ())); - invoc.set_meta_item_output (std::move (meta_items)); - } + { + std::vector > 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 &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 &invoc); + // Expands a single declarative macro. + AST::ASTFragment expand_decl_macro (AST::MacroInvocData &invoc, AST::MacroRulesDefinition &rules_def); + void expand_cfg_attrs (std::vector &attrs); bool fails_cfg (const std::vector &attr) const; bool fails_cfg_with_expand (std::vector &attrs) const; diff --git a/gcc/testsuite/rust.test/compilable/arrays2.rs b/gcc/testsuite/rust.test/compilable/arrays2.rs deleted file mode 100644 index 974e346..0000000 --- a/gcc/testsuite/rust.test/compilable/arrays2.rs +++ /dev/null @@ -1,66 +0,0 @@ -fn main() { - // const, inferred array - let const_inferred_array = [0, 1, 2, 3]; - // const, inferred, copied array - let const_inferred_copied_array = [0; 4]; - - // const index of const, inferred array - let const_inferred_index = const_inferred_array[1]; - // variable index of const, inferred array - let some_var = 3; - let const_inferred_index_var = const_inferred_array[some_var]; - - // const index of const, inferred, copied array - let const_inferred_copied_index = const_inferred_copied_array[1]; - // variable index of const, inferred array - let const_inferred_copied_index_var = const_inferred_copied_array[some_var]; - - // mut, inferred array - let mut mut_inferred_array = [0, 1, 2, 3]; - // mut, inferred, copied array - let mut mut_inferred_copied_array = [0; 6]; - - // const index of mut, inferred array - let mut_inferred_index = mut_inferred_array[1]; - // variable index of mut, inferred array - let mut_inferred_index_var = mut_inferred_array[some_var]; - - // const index of mut, inferred, copied array - let mut_inferred_copied_index = mut_inferred_copied_array[1]; - // variable index of mut, inferred array - let mut_inferred_copied_index_var = mut_inferred_copied_array[some_var]; - - // const, typed array - let const_typed_array: [i32; 5] = [0, 1, 2, 3, 4]; - // const, typed, copied array - let const_typed_copied_array: [i32; 4] = [2; 4]; - - // const index of const, typed array - let const_typed_index = const_typed_array[1]; - // variable index of const, typed array - let const_typed_index_var = const_typed_array[some_var]; - - // const index of const, typed, copied array - let const_typed_copied_index = const_typed_copied_array[1]; - // variable index of const, typed array - let const_typed_copied_index_var = const_typed_copied_array[some_var]; - - // mut, typed array - let mut mut_typed_array: [i32; 4] = [0, 1, 2, 3]; - // mut, typed, copied array - let mut mut_typed_copied_array: [i32; 4] = [0; 4]; - - // const index of mut, typed array - let mut_typed_index = mut_typed_array[1]; - // variable index of mut, typed array - let mut_typed_index_var = mut_typed_array[some_var]; - - // const index of mut, typed, copied array - let mut_typed_copied_index = mut_typed_copied_array[1]; - // variable index of mut, typed array - let mut_typed_copied_index_var = mut_typed_copied_array[some_var]; - - - // index + 1 expression - let some_thing = mut_inferred_copied_array[some_var + 1]; -} \ No newline at end of file diff --git a/gcc/testsuite/rust.test/compilable/arrays3.rs b/gcc/testsuite/rust.test/compilable/arrays3.rs new file mode 100644 index 0000000..974e346 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/arrays3.rs @@ -0,0 +1,66 @@ +fn main() { + // const, inferred array + let const_inferred_array = [0, 1, 2, 3]; + // const, inferred, copied array + let const_inferred_copied_array = [0; 4]; + + // const index of const, inferred array + let const_inferred_index = const_inferred_array[1]; + // variable index of const, inferred array + let some_var = 3; + let const_inferred_index_var = const_inferred_array[some_var]; + + // const index of const, inferred, copied array + let const_inferred_copied_index = const_inferred_copied_array[1]; + // variable index of const, inferred array + let const_inferred_copied_index_var = const_inferred_copied_array[some_var]; + + // mut, inferred array + let mut mut_inferred_array = [0, 1, 2, 3]; + // mut, inferred, copied array + let mut mut_inferred_copied_array = [0; 6]; + + // const index of mut, inferred array + let mut_inferred_index = mut_inferred_array[1]; + // variable index of mut, inferred array + let mut_inferred_index_var = mut_inferred_array[some_var]; + + // const index of mut, inferred, copied array + let mut_inferred_copied_index = mut_inferred_copied_array[1]; + // variable index of mut, inferred array + let mut_inferred_copied_index_var = mut_inferred_copied_array[some_var]; + + // const, typed array + let const_typed_array: [i32; 5] = [0, 1, 2, 3, 4]; + // const, typed, copied array + let const_typed_copied_array: [i32; 4] = [2; 4]; + + // const index of const, typed array + let const_typed_index = const_typed_array[1]; + // variable index of const, typed array + let const_typed_index_var = const_typed_array[some_var]; + + // const index of const, typed, copied array + let const_typed_copied_index = const_typed_copied_array[1]; + // variable index of const, typed array + let const_typed_copied_index_var = const_typed_copied_array[some_var]; + + // mut, typed array + let mut mut_typed_array: [i32; 4] = [0, 1, 2, 3]; + // mut, typed, copied array + let mut mut_typed_copied_array: [i32; 4] = [0; 4]; + + // const index of mut, typed array + let mut_typed_index = mut_typed_array[1]; + // variable index of mut, typed array + let mut_typed_index_var = mut_typed_array[some_var]; + + // const index of mut, typed, copied array + let mut_typed_copied_index = mut_typed_copied_array[1]; + // variable index of mut, typed array + let mut_typed_copied_index_var = mut_typed_copied_array[some_var]; + + + // index + 1 expression + let some_thing = mut_inferred_copied_array[some_var + 1]; +} \ No newline at end of file -- cgit v1.1