aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimplyTheOther <simplytheother@gmail.com>2020-12-25 16:25:40 +0800
committerSimplyTheOther <simplytheother@gmail.com>2020-12-25 16:25:40 +0800
commit7299d6d84ac4a1e8118915b00d361e7251e32b65 (patch)
tree0a386081e0b3ef3b21dd1e4c11692af70a8b6878
parent627121b6996146d7b14f2ad848f416682b1ce0fe (diff)
downloadgcc-7299d6d84ac4a1e8118915b00d361e7251e32b65.zip
gcc-7299d6d84ac4a1e8118915b00d361e7251e32b65.tar.gz
gcc-7299d6d84ac4a1e8118915b00d361e7251e32b65.tar.bz2
Test a new ASTFragment union representation
-rw-r--r--gcc/rust/ast/rust-ast-full-test.cc14
-rw-r--r--gcc/rust/ast/rust-ast.h56
-rw-r--r--gcc/rust/ast/rust-macro.h143
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc35
-rw-r--r--gcc/rust/expand/rust-macro-expand.h9
-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