// 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-fragment.h" namespace Rust { namespace AST { Fragment::Fragment (FragmentKind kind, std::vector nodes) : kind (kind), nodes (std::move (nodes)) {} Fragment::Fragment (Fragment const &other) : kind (other.get_kind ()) { *this = other; } Fragment & Fragment::operator= (Fragment const &other) { nodes.clear (); nodes.reserve (other.nodes.size ()); kind = other.get_kind (); for (auto &n : other.nodes) { nodes.push_back (n); } return *this; } Fragment Fragment::create_error () { return Fragment (FragmentKind::Error, {}); } Fragment Fragment::complete (std::vector nodes) { return Fragment (FragmentKind::Complete, std::move (nodes)); } Fragment Fragment::unexpanded () { return Fragment (FragmentKind::Unexpanded, {}); } std::vector & Fragment::get_nodes () { return nodes; } 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::IMPL, "impl"}, {SingleASTNode::NodeType::ITEM, "item"}, {SingleASTNode::NodeType::TYPE, "type"}, {SingleASTNode::NodeType::EXPRESSION, "expr"}, {SingleASTNode::NodeType::STMT, "stmt"}, {SingleASTNode::NodeType::EXTERN, "extern"}, {SingleASTNode::NodeType::TRAIT, "trait"}, {SingleASTNode::NodeType::TRAIT_IMPL, "trait impl"}, }; auto actual = nodes[0].get_kind (); auto fail = false; if (!is_single_fragment ()) { rust_error_at (Location (), "fragment is not single"); fail = true; } if (actual != expected) { rust_error_at ( 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