From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7905) id 04293387415F; Tue, 13 Dec 2022 13:17:41 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 04293387415F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1670937462; bh=PAf4xR2Efxvv1g+Pphi8Dxqe1jG8aAAnCyMz+8kHE94=; h=From:To:Subject:Date:From; b=BcjiKNlyKqmxOQonD5ZTKzFweiWtO8b+pIPGQbgMtmQHZbwRuuW5h9HTm2g/bnDG7 ewrrvYq0HQHRVLQmpm6flHGhLR3Ddi4mQXNKtDkhtDx9aW+yNV6N3zICXuGyzWKvEj R0rGC67ZLGyOYXDOyt+4LCSxkxoYfeNvgKPldNoo= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Arthur Cohen To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-4641] gccrs: Add Rust AST visitors X-Act-Checkin: gcc X-Git-Author: Joel Phillips X-Git-Refname: refs/heads/master X-Git-Oldrev: d588754c8266d74c9eef1e38d2d96e66ff876107 X-Git-Newrev: 5b981e9c7411e68bdd73365dbd94ed3844bce2c8 Message-Id: <20221213131742.04293387415F@sourceware.org> Date: Tue, 13 Dec 2022 13:17:41 +0000 (GMT) List-Id: https://gcc.gnu.org/g:5b981e9c7411e68bdd73365dbd94ed3844bce2c8 commit r13-4641-g5b981e9c7411e68bdd73365dbd94ed3844bce2c8 Author: Joel Phillips Date: Fri Oct 21 13:35:58 2022 +0200 gccrs: Add Rust AST visitors This patch contains the basic framework of our AST visitors, as well as one aimed at pretty-printing and exporting these AST nodes. gcc/rust/ * ast/rust-ast-dump.cc: New. * ast/rust-ast-dump.h: New. * ast/rust-ast-visitor.h: New. * ast/rust-cond-compilation.h: New. Co-authored-by: Philip Herron Co-authored-by: Arthur Cohen Signed-off-by: Joel Phillips Diff: --- gcc/rust/ast/rust-ast-dump.cc | 1089 ++++++++++++++++++++++++++++++++++ gcc/rust/ast/rust-ast-dump.h | 246 ++++++++ gcc/rust/ast/rust-ast-visitor.h | 234 ++++++++ gcc/rust/ast/rust-cond-compilation.h | 249 ++++++++ 4 files changed, 1818 insertions(+) diff --git a/gcc/rust/ast/rust-ast-dump.cc b/gcc/rust/ast/rust-ast-dump.cc new file mode 100644 index 00000000000..ad9ad0b7de7 --- /dev/null +++ b/gcc/rust/ast/rust-ast-dump.cc @@ -0,0 +1,1089 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-ast-dump.h" + +namespace Rust { +namespace AST { + +Indent::Indent () : tabs (0) {} + +std::ostream & +operator<< (std::ostream &stream, const Indent &indent) +{ + return stream << std::string (indent.tabs, '\t'); +} + +void +Indent::increment () +{ + tabs++; +} + +void +Indent::decrement () +{ + rust_assert (tabs != 0); + tabs--; +} + +Dump::Dump (std::ostream &stream) : stream (stream), indentation (Indent ()) {} + +void +Dump::go (AST::Crate &crate) +{ + for (auto &item : crate.items) + { + stream << indentation; + item->accept_vis (*this); + stream << "\n"; + } +} + +void +Dump::go (AST::Item &item) +{ + item.accept_vis (*this); +} + +void +Dump::format_function_param (FunctionParam ¶m) +{ + param.get_pattern ()->accept_vis (*this); + stream << ": "; + param.get_type ()->accept_vis (*this); +} + +void +Dump::emit_attrib (const Attribute &attrib) +{ + stream << "#"; + stream << "["; + + for (size_t i = 0; i < attrib.get_path ().get_segments ().size (); i++) + { + const auto &seg = attrib.get_path ().get_segments ().at (i); + bool has_next = (i + 1) < attrib.get_path ().get_segments ().size (); + + stream << seg.get_segment_name (); + if (has_next) + stream << "::"; + } + + if (attrib.has_attr_input ()) + { + stream << " = "; + + bool is_literal = attrib.get_attr_input ().get_attr_input_type () + == AST::AttrInput::AttrInputType::LITERAL; + if (is_literal) + { + auto &literal + = static_cast (attrib.get_attr_input ()); + const auto &value = literal.get_literal ().as_string (); + + stream << "\"" << value << "\""; + } + else + { + stream << "FIXME"; + } + } + + stream << "]"; +} + +void +Dump::visit (Token &tok) +{} + +void +Dump::visit (DelimTokenTree &delim_tok_tree) +{} + +void +Dump::visit (AttrInputMetaItemContainer &input) +{} + +void +Dump::visit (IdentifierExpr &ident_expr) +{ + stream << ident_expr.get_ident (); +} + +void +Dump::visit (Lifetime &lifetime) +{} + +void +Dump::visit (LifetimeParam &lifetime_param) +{} + +void +Dump::visit (ConstGenericParam &lifetime_param) +{} + +// rust-path.h +void +Dump::visit (PathInExpression &path) +{} + +void +Dump::visit (TypePathSegment &segment) +{} + +void +Dump::visit (TypePathSegmentGeneric &segment) +{} + +void +Dump::visit (TypePathSegmentFunction &segment) +{} + +void +Dump::visit (TypePath &path) +{ + stream << path.as_string (); +} + +void +Dump::visit (QualifiedPathInExpression &path) +{} + +void +Dump::visit (QualifiedPathInType &path) +{} + +// rust-expr.h +void +Dump::visit (LiteralExpr &expr) +{ + stream << expr.as_string (); +} + +void +Dump::visit (AttrInputLiteral &attr_input) +{} + +void +Dump::visit (MetaItemLitExpr &meta_item) +{} + +void +Dump::visit (MetaItemPathLit &meta_item) +{} + +void +Dump::visit (BorrowExpr &expr) +{} + +void +Dump::visit (DereferenceExpr &expr) +{} + +void +Dump::visit (ErrorPropagationExpr &expr) +{} + +void +Dump::visit (NegationExpr &expr) +{} + +void +Dump::visit (ArithmeticOrLogicalExpr &expr) +{ + expr.get_left_expr ()->accept_vis (*this); + stream << " "; + + switch (expr.get_expr_type ()) + { + case ArithmeticOrLogicalOperator::ADD: + stream << "+"; + break; + + case ArithmeticOrLogicalOperator::SUBTRACT: + stream << "-"; + break; + + case ArithmeticOrLogicalOperator::MULTIPLY: + stream << "*"; + break; + + case ArithmeticOrLogicalOperator::DIVIDE: + stream << "/"; + break; + + case ArithmeticOrLogicalOperator::MODULUS: + stream << "%"; + break; + + case ArithmeticOrLogicalOperator::BITWISE_AND: + stream << "&"; + break; + + case ArithmeticOrLogicalOperator::BITWISE_OR: + stream << "|"; + break; + + case ArithmeticOrLogicalOperator::BITWISE_XOR: + stream << "^"; + break; + + case ArithmeticOrLogicalOperator::LEFT_SHIFT: + stream << "<<"; + break; + + case ArithmeticOrLogicalOperator::RIGHT_SHIFT: + stream << ">>"; + break; + } + + stream << " "; + expr.get_right_expr ()->accept_vis (*this); +} + +void +Dump::visit (ComparisonExpr &expr) +{} + +void +Dump::visit (LazyBooleanExpr &expr) +{} + +void +Dump::visit (TypeCastExpr &expr) +{} + +void +Dump::visit (AssignmentExpr &expr) +{} + +void +Dump::visit (CompoundAssignmentExpr &expr) +{} + +void +Dump::visit (GroupedExpr &expr) +{} + +void +Dump::visit (ArrayElemsValues &elems) +{} + +void +Dump::visit (ArrayElemsCopied &elems) +{} + +void +Dump::visit (ArrayExpr &expr) +{} + +void +Dump::visit (ArrayIndexExpr &expr) +{} + +void +Dump::visit (TupleExpr &expr) +{} + +void +Dump::visit (TupleIndexExpr &expr) +{} + +void +Dump::visit (StructExprStruct &expr) +{} + +void +Dump::visit (StructExprFieldIdentifier &field) +{} + +void +Dump::visit (StructExprFieldIdentifierValue &field) +{} + +void +Dump::visit (StructExprFieldIndexValue &field) +{} + +void +Dump::visit (StructExprStructFields &expr) +{} + +void +Dump::visit (StructExprStructBase &expr) +{} + +void +Dump::visit (CallExpr &expr) +{} + +void +Dump::visit (MethodCallExpr &expr) +{} + +void +Dump::visit (FieldAccessExpr &expr) +{} + +void +Dump::visit (ClosureExprInner &expr) +{} + +void +Dump::visit (BlockExpr &expr) +{ + stream << "{\n"; + indentation.increment (); + + for (auto &stmt : expr.get_statements ()) + { + stream << indentation; + stmt->accept_vis (*this); + stream << ";\n"; + } + + if (expr.has_tail_expr ()) + { + stream << indentation; + expr.get_tail_expr ()->accept_vis (*this); + } + + indentation.decrement (); + stream << "\n" << indentation << "}\n"; +} + +void +Dump::visit (ClosureExprInnerTyped &expr) +{} + +void +Dump::visit (ContinueExpr &expr) +{} + +void +Dump::visit (BreakExpr &expr) +{} + +void +Dump::visit (RangeFromToExpr &expr) +{} + +void +Dump::visit (RangeFromExpr &expr) +{} + +void +Dump::visit (RangeToExpr &expr) +{} + +void +Dump::visit (RangeFullExpr &expr) +{} + +void +Dump::visit (RangeFromToInclExpr &expr) +{} + +void +Dump::visit (RangeToInclExpr &expr) +{} + +void +Dump::visit (ReturnExpr &expr) +{} + +void +Dump::visit (UnsafeBlockExpr &expr) +{} + +void +Dump::visit (LoopExpr &expr) +{} + +void +Dump::visit (WhileLoopExpr &expr) +{} + +void +Dump::visit (WhileLetLoopExpr &expr) +{} + +void +Dump::visit (ForLoopExpr &expr) +{} + +void +Dump::visit (IfExpr &expr) +{} + +void +Dump::visit (IfExprConseqElse &expr) +{} + +void +Dump::visit (IfExprConseqIf &expr) +{} + +void +Dump::visit (IfExprConseqIfLet &expr) +{} + +void +Dump::visit (IfLetExpr &expr) +{} + +void +Dump::visit (IfLetExprConseqElse &expr) +{} + +void +Dump::visit (IfLetExprConseqIf &expr) +{} + +void +Dump::visit (IfLetExprConseqIfLet &expr) +{} + +void +Dump::visit (MatchExpr &expr) +{} + +void +Dump::visit (AwaitExpr &expr) +{} + +void +Dump::visit (AsyncBlockExpr &expr) +{} + +// rust-item.h +void +Dump::visit (TypeParam ¶m) +{ + stream << param.get_type_representation (); + if (param.has_type ()) + { + stream << " = "; + param.get_type ()->accept_vis (*this); + } +} + +void +Dump::visit (LifetimeWhereClauseItem &item) +{} + +void +Dump::visit (TypeBoundWhereClauseItem &item) +{} + +void +Dump::visit (Method &method) +{ + stream << indentation << "fn " << method.get_method_name () << '('; + + auto &self = method.get_self_param (); + stream << self.as_string (); + + auto ¶ms = method.get_function_params (); + for (auto ¶m : params) + { + stream << ", "; + format_function_param (param); + } + + stream << ") "; + + if (method.has_return_type ()) + { + stream << "-> "; + method.get_return_type ()->accept_vis (*this); + stream << " "; + } + + auto &block = method.get_definition (); + if (!block) + stream << ';'; + else + block->accept_vis (*this); + + stream << '\n'; +} + +void +Dump::visit (Module &module) +{} + +void +Dump::visit (ExternCrate &crate) +{} + +void +Dump::visit (UseTreeGlob &use_tree) +{} + +void +Dump::visit (UseTreeList &use_tree) +{} + +void +Dump::visit (UseTreeRebind &use_tree) +{} + +void +Dump::visit (UseDeclaration &use_decl) +{} + +void +Dump::visit (Function &function) +{ + stream << "fn " << function.get_function_name (); + + if (function.has_generics ()) + { + stream << "<"; + for (size_t i = 0; i < function.get_generic_params ().size (); i++) + { + auto ¶m = function.get_generic_params ().at (i); + param->accept_vis (*this); + + bool has_next = (i + 1) < function.get_generic_params ().size (); + if (has_next) + stream << ", "; + } + stream << ">"; + } + + stream << '('; + auto ¶ms = function.get_function_params (); + if (params.size () >= 1) + { + format_function_param (params[0]); + for (size_t i = 1; i < params.size (); i++) + { + stream << ", "; + format_function_param (params[i]); + } + } + + stream << ") "; + + if (function.has_return_type ()) + { + stream << "-> "; + function.get_return_type ()->accept_vis (*this); + stream << " "; + } + + auto &block = function.get_definition (); + if (!block) + stream << ';'; + else + block->accept_vis (*this); + + stream << '\n'; +} + +void +Dump::visit (TypeAlias &type_alias) +{} + +void +Dump::visit (StructStruct &struct_item) +{} + +void +Dump::visit (TupleStruct &tuple_struct) +{} + +void +Dump::visit (EnumItem &item) +{} + +void +Dump::visit (EnumItemTuple &item) +{} + +void +Dump::visit (EnumItemStruct &item) +{} + +void +Dump::visit (EnumItemDiscriminant &item) +{} + +void +Dump::visit (Enum &enum_item) +{} + +void +Dump::visit (Union &union_item) +{} + +void +Dump::visit (ConstantItem &const_item) +{} + +void +Dump::visit (StaticItem &static_item) +{} + +void +Dump::format_function_common (std::unique_ptr &return_type, + std::unique_ptr &block) +{ + if (return_type) + { + stream << "-> "; + return_type->accept_vis (*this); + } + + if (block) + { + if (return_type) + stream << ' '; + block->accept_vis (*this); + } + else + stream << ";\n"; +} + +void +Dump::visit (TraitItemFunc &item) +{ + auto func = item.get_trait_function_decl (); + stream << indentation << "fn " << func.get_identifier () << '('; + + auto ¶ms = func.get_function_params (); + for (auto ¶m : params) + { + stream << ", "; + format_function_param (param); + } + + stream << ") "; + + format_function_common (func.get_return_type (), item.get_definition ()); +} + +void +Dump::visit (TraitItemMethod &item) +{ + auto method = item.get_trait_method_decl (); + stream << indentation << "fn " << method.get_identifier () << '('; + + auto &self = method.get_self_param (); + stream << self.as_string (); + + auto ¶ms = method.get_function_params (); + for (auto ¶m : params) + { + stream << ", "; + format_function_param (param); + } + + stream << ") "; + + format_function_common (method.get_return_type (), item.get_definition ()); +} + +void +Dump::visit (TraitItemConst &item) +{ + stream << indentation << "const " << item.get_identifier () << ": "; + item.get_type ()->accept_vis (*this); + stream << ";\n"; +} + +void +Dump::visit (TraitItemType &item) +{ + stream << indentation << "type " << item.get_identifier () << ";\n"; +} + +void +Dump::visit (Trait &trait) +{ + for (const auto &attr : trait.get_outer_attrs ()) + { + emit_attrib (attr); + stream << "\n" << indentation; + } + + stream << "trait " << trait.get_identifier (); + + // Traits actually have an implicit Self thrown at the start so we must expect + // the number of generic params to be > 1 + if (trait.get_generic_params ().size () > 1) + { + stream << "<"; + for (size_t i = 1; i < trait.get_generic_params ().size (); i++) + { + auto ¶m = trait.get_generic_params ().at (i); + param->accept_vis (*this); + + bool has_next = (i + 1) < trait.get_generic_params ().size (); + if (has_next) + stream << ", "; + } + stream << ">"; + } + + stream << " {\n"; + + indentation.increment (); + + for (auto &item : trait.get_trait_items ()) + item->accept_vis (*this); + + indentation.decrement (); + stream << "\n}\n"; +} + +void +Dump::visit (InherentImpl &impl) +{ + stream << "impl "; + + // FIXME: Handle generics + + impl.get_type ()->accept_vis (*this); + + // FIXME: Handle where-clause + // FIXME: Handle inner attributes + + stream << " {\n"; + indentation.increment (); + + for (auto &item : impl.get_impl_items ()) + item->accept_vis (*this); + + indentation.decrement (); + stream << "\n}\n"; +} + +void +Dump::visit (TraitImpl &impl) +{ + stream << "impl "; + impl.get_trait_path ().accept_vis (*this); + stream << " for "; + impl.get_type ()->accept_vis (*this); + + stream << " {\n"; + indentation.increment (); + + for (auto &item : impl.get_impl_items ()) + item->accept_vis (*this); + + indentation.decrement (); + stream << "\n}\n"; +} + +void +Dump::visit (ExternalStaticItem &item) +{} + +void +Dump::visit (ExternalFunctionItem &function) +{ + stream << "fn " << function.get_identifier () << '('; + + for (size_t i = 0; i < function.get_function_params ().size (); i++) + { + auto ¶m = function.get_function_params ().at (i); + bool has_next = (i + 1) < function.get_function_params ().size (); + + stream << param.get_name () << ": "; + param.get_type ()->accept_vis (*this); + + if (has_next) + stream << ", "; + } + + stream << ')'; + if (function.has_return_type ()) + { + stream << "-> "; + function.get_return_type ()->accept_vis (*this); + } +} + +void +Dump::visit (ExternBlock &block) +{ + stream << "extern "; + + if (block.has_abi ()) + { + stream << "\""; + stream << block.get_abi (); + stream << "\" "; + } + + stream << "{\n"; + indentation.increment (); + + for (auto &item : block.get_extern_items ()) + { + stream << indentation; + item->accept_vis (*this); + stream << ";\n"; + } + + indentation.decrement (); + stream << "\n" << indentation << "}\n"; +} + +// rust-macro.h +void +Dump::visit (MacroMatchFragment &match) +{} + +void +Dump::visit (MacroMatchRepetition &match) +{} + +void +Dump::visit (MacroMatcher &matcher) +{} + +void +Dump::visit (MacroRulesDefinition &rules_def) +{} + +void +Dump::visit (MacroInvocation ¯o_invoc) +{} + +void +Dump::visit (MetaItemPath &meta_item) +{} + +void +Dump::visit (MetaItemSeq &meta_item) +{} + +void +Dump::visit (MetaWord &meta_item) +{} + +void +Dump::visit (MetaNameValueStr &meta_item) +{} + +void +Dump::visit (MetaListPaths &meta_item) +{} + +void +Dump::visit (MetaListNameValueStr &meta_item) +{} + +// rust-pattern.h +void +Dump::visit (LiteralPattern &pattern) +{} + +void +Dump::visit (IdentifierPattern &pattern) +{ + stream << pattern.get_ident (); +} + +void +Dump::visit (WildcardPattern &pattern) +{} + +// void Dump::visit(RangePatternBound& bound){} + +void +Dump::visit (RangePatternBoundLiteral &bound) +{} + +void +Dump::visit (RangePatternBoundPath &bound) +{} + +void +Dump::visit (RangePatternBoundQualPath &bound) +{} + +void +Dump::visit (RangePattern &pattern) +{} + +void +Dump::visit (ReferencePattern &pattern) +{} + +// void Dump::visit(StructPatternField& field){} + +void +Dump::visit (StructPatternFieldTuplePat &field) +{} + +void +Dump::visit (StructPatternFieldIdentPat &field) +{} + +void +Dump::visit (StructPatternFieldIdent &field) +{} + +void +Dump::visit (StructPattern &pattern) +{} + +// void Dump::visit(TupleStructItems& tuple_items){} + +void +Dump::visit (TupleStructItemsNoRange &tuple_items) +{} + +void +Dump::visit (TupleStructItemsRange &tuple_items) +{} + +void +Dump::visit (TupleStructPattern &pattern) +{} + +// void Dump::visit(TuplePatternItems& tuple_items){} + +void +Dump::visit (TuplePatternItemsMultiple &tuple_items) +{} + +void +Dump::visit (TuplePatternItemsRanged &tuple_items) +{} + +void +Dump::visit (TuplePattern &pattern) +{} + +void +Dump::visit (GroupedPattern &pattern) +{} + +void +Dump::visit (SlicePattern &pattern) +{} + +// rust-stmt.h +void +Dump::visit (EmptyStmt &stmt) +{} + +void +Dump::visit (LetStmt &stmt) +{ + stream << "let "; + auto &pattern = stmt.get_pattern (); + if (pattern) + pattern->accept_vis (*this); + + if (stmt.has_type ()) + { + stream << ": "; + stmt.get_type ()->accept_vis (*this); + } + + if (stmt.has_init_expr ()) + { + stream << " = "; + stmt.get_init_expr ()->accept_vis (*this); + } +} + +void +Dump::visit (ExprStmtWithoutBlock &stmt) +{} + +void +Dump::visit (ExprStmtWithBlock &stmt) +{} + +// rust-type.h +void +Dump::visit (TraitBound &bound) +{} + +void +Dump::visit (ImplTraitType &type) +{} + +void +Dump::visit (TraitObjectType &type) +{} + +void +Dump::visit (ParenthesisedType &type) +{} + +void +Dump::visit (ImplTraitTypeOneBound &type) +{} + +void +Dump::visit (TraitObjectTypeOneBound &type) +{} + +void +Dump::visit (TupleType &type) +{} + +void +Dump::visit (NeverType &type) +{} + +void +Dump::visit (RawPointerType &type) +{} + +void +Dump::visit (ReferenceType &type) +{ + type.get_type_referenced ()->accept_vis (*this); +} + +void +Dump::visit (ArrayType &type) +{ + type.get_elem_type ()->accept_vis (*this); +} + +void +Dump::visit (SliceType &type) +{ + type.get_elem_type ()->accept_vis (*this); +} + +void +Dump::visit (InferredType &type) +{ + stream << "_"; +} + +void +Dump::visit (BareFunctionType &type) +{} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-ast-dump.h b/gcc/rust/ast/rust-ast-dump.h new file mode 100644 index 00000000000..c3854e8287d --- /dev/null +++ b/gcc/rust/ast/rust-ast-dump.h @@ -0,0 +1,246 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-ast-visitor.h" +#include "rust-ast.h" +#include "rust-ast-full.h" + +#ifndef RUST_AST_DUMP_H +#define RUST_AST_DUMP_H + +namespace Rust { +namespace AST { + +// TODO: We might want to reuse this class somewhere else +class Indent +{ +public: + Indent (); + + friend std::ostream &operator<< (std::ostream &stream, const Indent &indent); + + void increment (); + void decrement (); + +private: + size_t tabs; +}; + +class Dump : public ASTVisitor +{ +public: + Dump (std::ostream &stream); + + /** + * Run the visitor on an entire crate and its items + */ + void go (AST::Crate &crate); + void go (AST::Item &item); + +private: + std::ostream &stream; + Indent indentation; + + // Format together common items of functions: Parameters, return type, block + void format_function_common (std::unique_ptr &return_type, + std::unique_ptr &block); + + /** + * Format a function's definition parameter + */ + void format_function_param (FunctionParam ¶m); + void emit_attrib (const Attribute &attrib); + + // rust-ast.h + void visit (Token &tok); + void visit (DelimTokenTree &delim_tok_tree); + void visit (AttrInputMetaItemContainer &input); + void visit (IdentifierExpr &ident_expr); + void visit (Lifetime &lifetime); + void visit (LifetimeParam &lifetime_param); + void visit (ConstGenericParam &const_param); + + // rust-path.h + void visit (PathInExpression &path); + void visit (TypePathSegment &segment); + void visit (TypePathSegmentGeneric &segment); + void visit (TypePathSegmentFunction &segment); + void visit (TypePath &path); + void visit (QualifiedPathInExpression &path); + void visit (QualifiedPathInType &path); + + // rust-expr.h + void visit (LiteralExpr &expr); + void visit (AttrInputLiteral &attr_input); + void visit (MetaItemLitExpr &meta_item); + void visit (MetaItemPathLit &meta_item); + void visit (BorrowExpr &expr); + void visit (DereferenceExpr &expr); + void visit (ErrorPropagationExpr &expr); + void visit (NegationExpr &expr); + void visit (ArithmeticOrLogicalExpr &expr); + void visit (ComparisonExpr &expr); + void visit (LazyBooleanExpr &expr); + void visit (TypeCastExpr &expr); + void visit (AssignmentExpr &expr); + void visit (CompoundAssignmentExpr &expr); + void visit (GroupedExpr &expr); + void visit (ArrayElemsValues &elems); + void visit (ArrayElemsCopied &elems); + void visit (ArrayExpr &expr); + void visit (ArrayIndexExpr &expr); + void visit (TupleExpr &expr); + void visit (TupleIndexExpr &expr); + void visit (StructExprStruct &expr); + void visit (StructExprFieldIdentifier &field); + void visit (StructExprFieldIdentifierValue &field); + void visit (StructExprFieldIndexValue &field); + void visit (StructExprStructFields &expr); + void visit (StructExprStructBase &expr); + void visit (CallExpr &expr); + void visit (MethodCallExpr &expr); + void visit (FieldAccessExpr &expr); + void visit (ClosureExprInner &expr); + void visit (BlockExpr &expr); + void visit (ClosureExprInnerTyped &expr); + void visit (ContinueExpr &expr); + void visit (BreakExpr &expr); + void visit (RangeFromToExpr &expr); + void visit (RangeFromExpr &expr); + void visit (RangeToExpr &expr); + void visit (RangeFullExpr &expr); + void visit (RangeFromToInclExpr &expr); + void visit (RangeToInclExpr &expr); + void visit (ReturnExpr &expr); + void visit (UnsafeBlockExpr &expr); + void visit (LoopExpr &expr); + void visit (WhileLoopExpr &expr); + void visit (WhileLetLoopExpr &expr); + void visit (ForLoopExpr &expr); + void visit (IfExpr &expr); + void visit (IfExprConseqElse &expr); + void visit (IfExprConseqIf &expr); + void visit (IfExprConseqIfLet &expr); + void visit (IfLetExpr &expr); + void visit (IfLetExprConseqElse &expr); + void visit (IfLetExprConseqIf &expr); + void visit (IfLetExprConseqIfLet &expr); + void visit (MatchExpr &expr); + void visit (AwaitExpr &expr); + void visit (AsyncBlockExpr &expr); + + // rust-item.h + void visit (TypeParam ¶m); + void visit (LifetimeWhereClauseItem &item); + void visit (TypeBoundWhereClauseItem &item); + void visit (Method &method); + void visit (Module &module); + void visit (ExternCrate &crate); + void visit (UseTreeGlob &use_tree); + void visit (UseTreeList &use_tree); + void visit (UseTreeRebind &use_tree); + void visit (UseDeclaration &use_decl); + void visit (Function &function); + void visit (TypeAlias &type_alias); + void visit (StructStruct &struct_item); + void visit (TupleStruct &tuple_struct); + void visit (EnumItem &item); + void visit (EnumItemTuple &item); + void visit (EnumItemStruct &item); + void visit (EnumItemDiscriminant &item); + void visit (Enum &enum_item); + void visit (Union &union_item); + void visit (ConstantItem &const_item); + void visit (StaticItem &static_item); + void visit (TraitItemFunc &item); + void visit (TraitItemMethod &item); + void visit (TraitItemConst &item); + void visit (TraitItemType &item); + void visit (Trait &trait); + void visit (InherentImpl &impl); + void visit (TraitImpl &impl); + void visit (ExternalStaticItem &item); + void visit (ExternalFunctionItem &item); + void visit (ExternBlock &block); + + // rust-macro.h + void visit (MacroMatchFragment &match); + void visit (MacroMatchRepetition &match); + void visit (MacroMatcher &matcher); + void visit (MacroRulesDefinition &rules_def); + void visit (MacroInvocation ¯o_invoc); + void visit (MetaItemPath &meta_item); + void visit (MetaItemSeq &meta_item); + void visit (MetaWord &meta_item); + void visit (MetaNameValueStr &meta_item); + void visit (MetaListPaths &meta_item); + void visit (MetaListNameValueStr &meta_item); + + // rust-pattern.h + void visit (LiteralPattern &pattern); + void visit (IdentifierPattern &pattern); + void visit (WildcardPattern &pattern); + // void visit(RangePatternBound& bound); + void visit (RangePatternBoundLiteral &bound); + void visit (RangePatternBoundPath &bound); + void visit (RangePatternBoundQualPath &bound); + void visit (RangePattern &pattern); + void visit (ReferencePattern &pattern); + // void visit(StructPatternField& field); + void visit (StructPatternFieldTuplePat &field); + void visit (StructPatternFieldIdentPat &field); + void visit (StructPatternFieldIdent &field); + void visit (StructPattern &pattern); + // void visit(TupleStructItems& tuple_items); + void visit (TupleStructItemsNoRange &tuple_items); + void visit (TupleStructItemsRange &tuple_items); + void visit (TupleStructPattern &pattern); + // void visit(TuplePatternItems& tuple_items); + void visit (TuplePatternItemsMultiple &tuple_items); + void visit (TuplePatternItemsRanged &tuple_items); + void visit (TuplePattern &pattern); + void visit (GroupedPattern &pattern); + void visit (SlicePattern &pattern); + + // rust-stmt.h + void visit (EmptyStmt &stmt); + void visit (LetStmt &stmt); + void visit (ExprStmtWithoutBlock &stmt); + void visit (ExprStmtWithBlock &stmt); + + // rust-type.h + void visit (TraitBound &bound); + void visit (ImplTraitType &type); + void visit (TraitObjectType &type); + void visit (ParenthesisedType &type); + void visit (ImplTraitTypeOneBound &type); + void visit (TraitObjectTypeOneBound &type); + void visit (TupleType &type); + void visit (NeverType &type); + void visit (RawPointerType &type); + void visit (ReferenceType &type); + void visit (ArrayType &type); + void visit (SliceType &type); + void visit (InferredType &type); + void visit (BareFunctionType &type); +}; + +} // namespace AST +} // namespace Rust + +#endif // !RUST_AST_DUMP_H diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h new file mode 100644 index 00000000000..bbb04771fea --- /dev/null +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -0,0 +1,234 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_AST_VISITOR_H +#define RUST_AST_VISITOR_H +// Visitor base for AST + +// full include not required - only forward decls +#include "rust-ast-full-decls.h" + +namespace Rust { +namespace AST { +/* Pure abstract class that provides an interface for accessing different + * classes of the AST. */ +class ASTVisitor +{ +public: + // only concrete class overloads are required + + // rust-ast.h + // virtual void visit(AttrInput& attr_input) = 0; + // virtual void visit(TokenTree& token_tree) = 0; + // virtual void visit(MacroMatch& macro_match) = 0; + virtual void visit (Token &tok) = 0; + virtual void visit (DelimTokenTree &delim_tok_tree) = 0; + virtual void visit (AttrInputMetaItemContainer &input) = 0; + // virtual void visit(MetaItem& meta_item) = 0; + // virtual void visit(Stmt& stmt) = 0; + // virtual void visit(Expr& expr) = 0; + virtual void visit (IdentifierExpr &ident_expr) = 0; + // virtual void visit(Pattern& pattern) = 0; + // virtual void visit(Type& type) = 0; + // virtual void visit(TypeParamBound& type_param_bound) = 0; + virtual void visit (Lifetime &lifetime) = 0; + // virtual void visit(GenericParam& generic_param) = 0; + virtual void visit (LifetimeParam &lifetime_param) = 0; + virtual void visit (ConstGenericParam &const_param) = 0; + // virtual void visit(TraitItem& trait_item) = 0; + // virtual void visit(InherentImplItem& inherent_impl_item) = 0; + // virtual void visit(TraitImplItem& trait_impl_item) = 0; + + // rust-path.h + virtual void visit (PathInExpression &path) = 0; + virtual void visit (TypePathSegment &segment) = 0; + virtual void visit (TypePathSegmentGeneric &segment) = 0; + virtual void visit (TypePathSegmentFunction &segment) = 0; + virtual void visit (TypePath &path) = 0; + virtual void visit (QualifiedPathInExpression &path) = 0; + virtual void visit (QualifiedPathInType &path) = 0; + + // rust-expr.h + virtual void visit (LiteralExpr &expr) = 0; + virtual void visit (AttrInputLiteral &attr_input) = 0; + virtual void visit (MetaItemLitExpr &meta_item) = 0; + virtual void visit (MetaItemPathLit &meta_item) = 0; + virtual void visit (BorrowExpr &expr) = 0; + virtual void visit (DereferenceExpr &expr) = 0; + virtual void visit (ErrorPropagationExpr &expr) = 0; + virtual void visit (NegationExpr &expr) = 0; + virtual void visit (ArithmeticOrLogicalExpr &expr) = 0; + virtual void visit (ComparisonExpr &expr) = 0; + virtual void visit (LazyBooleanExpr &expr) = 0; + virtual void visit (TypeCastExpr &expr) = 0; + virtual void visit (AssignmentExpr &expr) = 0; + virtual void visit (CompoundAssignmentExpr &expr) = 0; + virtual void visit (GroupedExpr &expr) = 0; + // virtual void visit(ArrayElems& elems) = 0; + virtual void visit (ArrayElemsValues &elems) = 0; + virtual void visit (ArrayElemsCopied &elems) = 0; + virtual void visit (ArrayExpr &expr) = 0; + virtual void visit (ArrayIndexExpr &expr) = 0; + virtual void visit (TupleExpr &expr) = 0; + virtual void visit (TupleIndexExpr &expr) = 0; + virtual void visit (StructExprStruct &expr) = 0; + // virtual void visit(StructExprField& field) = 0; + virtual void visit (StructExprFieldIdentifier &field) = 0; + virtual void visit (StructExprFieldIdentifierValue &field) = 0; + virtual void visit (StructExprFieldIndexValue &field) = 0; + virtual void visit (StructExprStructFields &expr) = 0; + virtual void visit (StructExprStructBase &expr) = 0; + virtual void visit (CallExpr &expr) = 0; + virtual void visit (MethodCallExpr &expr) = 0; + virtual void visit (FieldAccessExpr &expr) = 0; + virtual void visit (ClosureExprInner &expr) = 0; + virtual void visit (BlockExpr &expr) = 0; + virtual void visit (ClosureExprInnerTyped &expr) = 0; + virtual void visit (ContinueExpr &expr) = 0; + virtual void visit (BreakExpr &expr) = 0; + virtual void visit (RangeFromToExpr &expr) = 0; + virtual void visit (RangeFromExpr &expr) = 0; + virtual void visit (RangeToExpr &expr) = 0; + virtual void visit (RangeFullExpr &expr) = 0; + virtual void visit (RangeFromToInclExpr &expr) = 0; + virtual void visit (RangeToInclExpr &expr) = 0; + virtual void visit (ReturnExpr &expr) = 0; + virtual void visit (UnsafeBlockExpr &expr) = 0; + virtual void visit (LoopExpr &expr) = 0; + virtual void visit (WhileLoopExpr &expr) = 0; + virtual void visit (WhileLetLoopExpr &expr) = 0; + virtual void visit (ForLoopExpr &expr) = 0; + virtual void visit (IfExpr &expr) = 0; + virtual void visit (IfExprConseqElse &expr) = 0; + virtual void visit (IfExprConseqIf &expr) = 0; + virtual void visit (IfExprConseqIfLet &expr) = 0; + virtual void visit (IfLetExpr &expr) = 0; + virtual void visit (IfLetExprConseqElse &expr) = 0; + virtual void visit (IfLetExprConseqIf &expr) = 0; + virtual void visit (IfLetExprConseqIfLet &expr) = 0; + // virtual void visit(MatchCase& match_case) = 0; + // virtual void visit (MatchCaseBlockExpr &match_case) = 0; + // virtual void visit (MatchCaseExpr &match_case) = 0; + virtual void visit (MatchExpr &expr) = 0; + virtual void visit (AwaitExpr &expr) = 0; + virtual void visit (AsyncBlockExpr &expr) = 0; + + // rust-item.h + virtual void visit (TypeParam ¶m) = 0; + // virtual void visit(WhereClauseItem& item) = 0; + virtual void visit (LifetimeWhereClauseItem &item) = 0; + virtual void visit (TypeBoundWhereClauseItem &item) = 0; + virtual void visit (Method &method) = 0; + virtual void visit (Module &module) = 0; + virtual void visit (ExternCrate &crate) = 0; + // virtual void visit(UseTree& use_tree) = 0; + virtual void visit (UseTreeGlob &use_tree) = 0; + virtual void visit (UseTreeList &use_tree) = 0; + virtual void visit (UseTreeRebind &use_tree) = 0; + virtual void visit (UseDeclaration &use_decl) = 0; + virtual void visit (Function &function) = 0; + virtual void visit (TypeAlias &type_alias) = 0; + virtual void visit (StructStruct &struct_item) = 0; + virtual void visit (TupleStruct &tuple_struct) = 0; + virtual void visit (EnumItem &item) = 0; + virtual void visit (EnumItemTuple &item) = 0; + virtual void visit (EnumItemStruct &item) = 0; + virtual void visit (EnumItemDiscriminant &item) = 0; + virtual void visit (Enum &enum_item) = 0; + virtual void visit (Union &union_item) = 0; + virtual void visit (ConstantItem &const_item) = 0; + virtual void visit (StaticItem &static_item) = 0; + virtual void visit (TraitItemFunc &item) = 0; + virtual void visit (TraitItemMethod &item) = 0; + virtual void visit (TraitItemConst &item) = 0; + virtual void visit (TraitItemType &item) = 0; + virtual void visit (Trait &trait) = 0; + virtual void visit (InherentImpl &impl) = 0; + virtual void visit (TraitImpl &impl) = 0; + // virtual void visit(ExternalItem& item) = 0; + virtual void visit (ExternalStaticItem &item) = 0; + virtual void visit (ExternalFunctionItem &item) = 0; + virtual void visit (ExternBlock &block) = 0; + + // rust-macro.h + virtual void visit (MacroMatchFragment &match) = 0; + virtual void visit (MacroMatchRepetition &match) = 0; + virtual void visit (MacroMatcher &matcher) = 0; + virtual void visit (MacroRulesDefinition &rules_def) = 0; + virtual void visit (MacroInvocation ¯o_invoc) = 0; + virtual void visit (MetaItemPath &meta_item) = 0; + virtual void visit (MetaItemSeq &meta_item) = 0; + virtual void visit (MetaWord &meta_item) = 0; + virtual void visit (MetaNameValueStr &meta_item) = 0; + virtual void visit (MetaListPaths &meta_item) = 0; + virtual void visit (MetaListNameValueStr &meta_item) = 0; + + // rust-pattern.h + virtual void visit (LiteralPattern &pattern) = 0; + virtual void visit (IdentifierPattern &pattern) = 0; + virtual void visit (WildcardPattern &pattern) = 0; + // virtual void visit(RangePatternBound& bound) = 0; + virtual void visit (RangePatternBoundLiteral &bound) = 0; + virtual void visit (RangePatternBoundPath &bound) = 0; + virtual void visit (RangePatternBoundQualPath &bound) = 0; + virtual void visit (RangePattern &pattern) = 0; + virtual void visit (ReferencePattern &pattern) = 0; + // virtual void visit(StructPatternField& field) = 0; + virtual void visit (StructPatternFieldTuplePat &field) = 0; + virtual void visit (StructPatternFieldIdentPat &field) = 0; + virtual void visit (StructPatternFieldIdent &field) = 0; + virtual void visit (StructPattern &pattern) = 0; + // virtual void visit(TupleStructItems& tuple_items) = 0; + virtual void visit (TupleStructItemsNoRange &tuple_items) = 0; + virtual void visit (TupleStructItemsRange &tuple_items) = 0; + virtual void visit (TupleStructPattern &pattern) = 0; + // virtual void visit(TuplePatternItems& tuple_items) = 0; + virtual void visit (TuplePatternItemsMultiple &tuple_items) = 0; + virtual void visit (TuplePatternItemsRanged &tuple_items) = 0; + virtual void visit (TuplePattern &pattern) = 0; + virtual void visit (GroupedPattern &pattern) = 0; + virtual void visit (SlicePattern &pattern) = 0; + + // rust-stmt.h + virtual void visit (EmptyStmt &stmt) = 0; + virtual void visit (LetStmt &stmt) = 0; + virtual void visit (ExprStmtWithoutBlock &stmt) = 0; + virtual void visit (ExprStmtWithBlock &stmt) = 0; + + // rust-type.h + virtual void visit (TraitBound &bound) = 0; + virtual void visit (ImplTraitType &type) = 0; + virtual void visit (TraitObjectType &type) = 0; + virtual void visit (ParenthesisedType &type) = 0; + virtual void visit (ImplTraitTypeOneBound &type) = 0; + virtual void visit (TraitObjectTypeOneBound &type) = 0; + virtual void visit (TupleType &type) = 0; + virtual void visit (NeverType &type) = 0; + virtual void visit (RawPointerType &type) = 0; + virtual void visit (ReferenceType &type) = 0; + virtual void visit (ArrayType &type) = 0; + virtual void visit (SliceType &type) = 0; + virtual void visit (InferredType &type) = 0; + virtual void visit (BareFunctionType &type) = 0; + + // TODO: rust-cond-compilation.h visiting? not currently used +}; +} // namespace AST +} // namespace Rust + +#endif diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h new file mode 100644 index 00000000000..71188ef3b4b --- /dev/null +++ b/gcc/rust/ast/rust-cond-compilation.h @@ -0,0 +1,249 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_AST_CONDCOMPILATION +#define RUST_AST_CONDCOMPILATION +// Conditional compilation-related AST stuff + +#include "rust-ast.h" + +namespace Rust { +namespace AST { +// Base conditional compilation configuration predicate thing - abstract +class ConfigurationPredicate +{ +public: + virtual ~ConfigurationPredicate () {} + + // Unique pointer custom clone function + std::unique_ptr clone_configuration_predicate () const + { + return std::unique_ptr ( + clone_configuration_predicate_impl ()); + } + + // not sure if I'll use this but here anyway + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // Clone function impl to be overriden in base classes + virtual ConfigurationPredicate * + clone_configuration_predicate_impl () const = 0; +}; + +// A configuration option - true if option is set, false if option is not set. +class ConfigurationOption : public ConfigurationPredicate +{ + Identifier option_name; + + // bool has_string_literal_option_body; + std::string option_value; // technically a string or raw string literal + +public: + /* Returns whether the configuration option has a "value" part of the + * key-value pair. */ + bool has_option_value () const { return !option_value.empty (); } + + // Key-value pair constructor + ConfigurationOption (Identifier option_name, std::string option_value) + : option_name (option_name), option_value (option_value) + {} + + // Name-only constructor + ConfigurationOption (Identifier option_name) : option_name (option_name) {} + + void accept_vis (ASTVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ConfigurationOption *clone_configuration_predicate_impl () const override + { + return new ConfigurationOption (*this); + } +}; + +// TODO: inline +struct ConfigurationPredicateList +{ + std::vector> predicate_list; +}; + +// Predicate that returns true if all of the supplied predicates return true. +class ConfigurationAll : public ConfigurationPredicate +{ + std::vector> + predicate_list; // inlined form + +public: + ConfigurationAll ( + std::vector> predicate_list) + : predicate_list (predicate_list) + {} + + void accept_vis (ASTVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ConfigurationAll *clone_configuration_predicate_impl () const override + { + return new ConfigurationAll (*this); + } +}; + +// Predicate that returns true if any of the supplied predicates are true. +class ConfigurationAny : public ConfigurationPredicate +{ + std::vector> + predicate_list; // inlined form + +public: + ConfigurationAny ( + std::vector> predicate_list) + : predicate_list (predicate_list) + {} + + void accept_vis (ASTVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ConfigurationAny *clone_configuration_predicate_impl () const override + { + return new ConfigurationAny (*this); + } +}; + +/* Predicate that produces the negation of a supplied other configuration + * predicate. */ +class ConfigurationNot : public ConfigurationPredicate +{ + std::unique_ptr config_to_negate; + +public: + ConfigurationNot (ConfigurationPredicate *config_to_negate) + : config_to_negate (config_to_negate) + {} + + // Copy constructor with clone + ConfigurationNot (ConfigurationNot const &other) + : config_to_negate ( + other.config_to_negate->clone_configuration_predicate ()) + {} + + // Overloaded assignment operator to clone + ConfigurationNot &operator= (ConfigurationNot const &other) + { + config_to_negate = other.config_to_negate->clone_configuration_predicate (); + + return *this; + } + + // move constructors + ConfigurationNot (ConfigurationNot &&other) = default; + ConfigurationNot &operator= (ConfigurationNot &&other) = default; + + void accept_vis (ASTVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ConfigurationNot *clone_configuration_predicate_impl () const override + { + return new ConfigurationNot (*this); + } +}; + +// TODO: relationship to other attributes? +class CfgAttribute +{ + std::unique_ptr config_to_include; + +public: + CfgAttribute (ConfigurationPredicate *config_to_include) + : config_to_include (config_to_include) + {} + + // Copy constructor with clone + CfgAttribute (CfgAttribute const &other) + : config_to_include ( + other.config_to_include->clone_configuration_predicate ()) + {} + + // Overloaded assignment operator to clone + CfgAttribute &operator= (CfgAttribute const &other) + { + config_to_include + = other.config_to_include->clone_configuration_predicate (); + + return *this; + } + + // move constructors + CfgAttribute (CfgAttribute &&other) = default; + CfgAttribute &operator= (CfgAttribute &&other) = default; +}; +/* TODO: ok, best thing to do would be eliminating this class, making Attribute + * has a "is_cfg()" method, and having attribute path as "cfg" and AttrInput as + * ConfigurationPredicate (so make ConfigurationPredicate a subclass of + * AttrInput?). Would need special handling in parser, however. */ + +// TODO: inline +struct CfgAttrs +{ + std::vector cfg_attrs; +}; + +// TODO: relationship to other attributes? +class CfgAttrAttribute +{ + std::unique_ptr config_to_include; + std::vector cfg_attrs; + +public: + CfgAttrAttribute (ConfigurationPredicate *config_to_include, + std::vector cfg_attrs) + : config_to_include (config_to_include), cfg_attrs (cfg_attrs) + {} + + // Copy constructor with clone + CfgAttrAttribute (CfgAttrAttribute const &other) + : config_to_include ( + other.config_to_include->clone_configuration_predicate ()), + cfg_attrs (cfg_attrs) + {} + + // Overloaded assignment operator to clone + CfgAttrAttribute &operator= (CfgAttrAttribute const &other) + { + config_to_include + = other.config_to_include->clone_configuration_predicate (); + cfg_attrs = other.cfg_attrs; + + return *this; + } + + // move constructors + CfgAttrAttribute (CfgAttrAttribute &&other) = default; + CfgAttrAttribute &operator= (CfgAttrAttribute &&other) = default; +}; +} // namespace AST +} // namespace Rust + +#endif