From patchwork Tue Dec 6 10:13:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arthur Cohen X-Patchwork-Id: 61502 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 899273AA940A for ; Tue, 6 Dec 2022 10:13:25 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by sourceware.org (Postfix) with ESMTPS id 88016396D818 for ; Tue, 6 Dec 2022 10:12:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 88016396D818 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com Received: by mail-wr1-x42b.google.com with SMTP id o5so22764286wrm.1 for ; Tue, 06 Dec 2022 02:12:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to; bh=4XOX4It/XgvV982RlGmecvcsZ2PruBBXGww/dQzmjiM=; b=Ohg84p6Pz+TbF1ieaD/fWqCrzukhSnmyUZNYurDi/uc9+NUyVWAzuCBHawr3aup+oM NqvTp7Vz/K3WzTsQw3gSF8/ULCpkLLXTAOlsNWBOyWUfZKqmLrcT1LPOVhJAWmrzH1S+ X5YRnJK4qbxoKC82T7DupONEcbjzl5HeIoEaL+ErGgLziexvtBwBMJXzW0k2aLw1W8Ck RWReZ1DDEmde43/jdoWCbpjiY9BJMqpGhuSabT/+Z6CpymMNPZO6gEwPcA6uzib/xNsX zTstWyAjzCSOJPi0lnIvuvTFS9aUoPM7ZhLhemGeqcAkLAg18KejJZmo0a4wGS9UKUrX zIkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=4XOX4It/XgvV982RlGmecvcsZ2PruBBXGww/dQzmjiM=; b=dlhT8GAzsJn6iStKh2ibTAUwEMHzRENYYYHZsF8ZLO8QO0K7+mRKMrHrTtTUtOnOOZ RyyZAc5vx1eRSnyyvTAy/Ad7qtsLqSazZueXdlSRIXP6hp9SPGKLlTTJc9KH366axjWT ywkPFP2uom5w+mGXXKWS6QMQddkPQbhejL1LXkYYUdEiBIb8R3yiyQOtdnSz9XGKqwpg zekJXDZBb64EmjiDdNXYNuDKFPZSOuE0hmFyBtft3IFZSW5Z7FBAsM1TB9qW3XUnaBGa ayAuaYN+MsXsMvU0bwNs5FyTYyl27Yz8HZW7kBCI73ORVLhVobSXKTaP/4oDzKDUCrmM AEcA== X-Gm-Message-State: ANoB5pnO9DPO79zlwgUXq/Hc6j9UYyWI/vNR2mcxXMQiv5g4K5hq3N5i f4eUvITGgL0PvLCxB1hoTsVHhCpY3+ss1kkZ6Q== X-Google-Smtp-Source: AA0mqf7qsowriI5vZXtn/EnnJ3Y58ZVMPH6HRWxAOueCFrO0sNfHnJPS7znGYBB74bha0AAkwBLzPA== X-Received: by 2002:adf:dcc5:0:b0:242:55e6:dc5 with SMTP id x5-20020adfdcc5000000b0024255e60dc5mr7409064wrm.192.1670321523617; Tue, 06 Dec 2022 02:12:03 -0800 (PST) Received: from platypus.lan ([2001:861:5e4c:3bb0:6424:328a:1734:3249]) by smtp.googlemail.com with ESMTPSA id r10-20020a05600c458a00b003cfd4a50d5asm27052699wmo.34.2022.12.06.02.12.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Dec 2022 02:12:03 -0800 (PST) From: arthur.cohen@embecosm.com To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org, The Other , Philip Herron , Arthur Cohen Subject: [PATCH Rust front-end v4 11/46] gccrs: Add Rust AST visitors Date: Tue, 6 Dec 2022 11:13:43 +0100 Message-Id: <20221206101417.778807-12-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221206101417.778807-1-arthur.cohen@embecosm.com> References: <20221206101417.778807-1-arthur.cohen@embecosm.com> MIME-Version: 1.0 X-Spam-Status: No, score=-25.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: arthur.cohen@embecosm.com Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" From: The Other This patch contains the basic framework of our AST visitors, as well as one aimed at pretty-printing and exporting these AST nodes. Co-authored-by: Philip Herron Co-authored-by: Arthur Cohen --- 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(+) create mode 100644 gcc/rust/ast/rust-ast-dump.cc create mode 100644 gcc/rust/ast/rust-ast-dump.h create mode 100644 gcc/rust/ast/rust-ast-visitor.h create mode 100644 gcc/rust/ast/rust-cond-compilation.h 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