// Copyright (C) 2020-2024 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-fragment.h" namespace Rust { namespace AST { Fragment::Fragment (FragmentKind kind, std::vector nodes, std::vector> tokens) : kind (kind), nodes (std::move (nodes)), tokens (std::move (tokens)) {} Fragment::Fragment (Fragment const &other) : kind (other.get_kind ()) { *this = other; } Fragment & Fragment::operator= (Fragment const &other) { kind = other.get_kind (); nodes.clear (); nodes.reserve (other.nodes.size ()); for (auto &n : other.nodes) nodes.push_back (n); tokens.clear (); tokens.reserve (other.tokens.size ()); for (auto &t : other.tokens) tokens.emplace_back (t->clone_token ()); return *this; } Fragment Fragment::create_error () { return Fragment (FragmentKind::Error, {}, {}); } Fragment Fragment::create_empty () { return Fragment (FragmentKind::Complete, {}, {}); } Fragment::Fragment (std::vector nodes, std::vector> tokens) : kind (FragmentKind::Complete), nodes (std::move (nodes)), tokens (std::move (tokens)) {} Fragment::Fragment (std::vector nodes, std::unique_ptr token) : kind (FragmentKind::Complete), nodes (std::move (nodes)) { tokens.emplace_back (std::move (token)); } std::vector & Fragment::get_nodes () { return nodes; } std::vector> & Fragment::get_tokens () { return tokens; } FragmentKind Fragment::get_kind () const { return kind; } bool Fragment::is_error () const { return get_kind () == FragmentKind::Error; } bool Fragment::should_expand () const { return !is_error (); } bool Fragment::is_expression_fragment () const { return is_single_fragment_of_kind (SingleASTNode::NodeType::EXPRESSION); } bool Fragment::is_type_fragment () const { return is_single_fragment_of_kind (SingleASTNode::NodeType::TYPE); } std::unique_ptr Fragment::take_expression_fragment () { assert_single_fragment (SingleASTNode::NodeType::EXPRESSION); return nodes[0].take_expr (); } std::unique_ptr Fragment::take_type_fragment () { assert_single_fragment (SingleASTNode::NodeType::TYPE); return nodes[0].take_type (); } void Fragment::accept_vis (ASTVisitor &vis) { for (auto &node : nodes) node.accept_vis (vis); } bool Fragment::is_single_fragment () const { return nodes.size () == 1; } bool Fragment::is_single_fragment_of_kind (SingleASTNode::NodeType expected) const { return is_single_fragment () && nodes[0].get_kind () == expected; } void Fragment::assert_single_fragment (SingleASTNode::NodeType expected) const { static const std::map str_map = { {SingleASTNode::NodeType::ASSOC_ITEM, "associated item"}, {SingleASTNode::NodeType::ITEM, "item"}, {SingleASTNode::NodeType::TYPE, "type"}, {SingleASTNode::NodeType::EXPRESSION, "expr"}, {SingleASTNode::NodeType::STMT, "stmt"}, {SingleASTNode::NodeType::EXTERN, "extern"}, }; auto actual = nodes[0].get_kind (); auto fail = false; if (!is_single_fragment ()) { rust_error_at (UNDEF_LOCATION, "fragment is not single"); fail = true; } if (actual != expected) { rust_error_at ( UNDEF_LOCATION, "invalid fragment operation: expected %qs node, got %qs node", str_map.find (expected)->second, str_map.find (nodes[0].get_kind ())->second); fail = true; } rust_assert (!fail); } } // namespace AST } // namespace Rust