From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com [IPv6:2a00:1450:4864:20::42f]) by sourceware.org (Postfix) with ESMTPS id 878C63884523 for ; Wed, 26 Oct 2022 08:15:47 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 878C63884523 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-x42f.google.com with SMTP id j15so14515013wrq.3 for ; Wed, 26 Oct 2022 01:15:47 -0700 (PDT) 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=VucN5CT04VP2OSclq9SCZJ7XbiUrj8NHD1u2wmc9RQc=; b=LHyVKfeut0L9SvIsKlQQ5pCDUuR3Cx1u6qFzWz4T56yBSfsjAlO+owAK+NnpZiAPkM 8kYpZXQRhvBJQjEuy7BEowuNX7uce7vPiD6GC2vUqnjac+EOeb0+ZcyVXGzw1Llc9cP7 6bR3TL9xAfuWE9nv2FO2kONLfBstKaYm6yFzaodpSrjziazv4ZgUidaKIRmQ0ktDAJqW saX97ThXVMHR96XlapjlNgP79Wxg9AEOz/MpUCg0CWP5feAt8ir/7qt5IFUootNE8WdT i1/fYDNbTQRZ0cOQKKjui9Slf35OxAljQ00igzUtmoSvZk80IJS1FG36xyEtVkRlTtaX Wi3A== 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=VucN5CT04VP2OSclq9SCZJ7XbiUrj8NHD1u2wmc9RQc=; b=qkdLF9WiOjF+t8bfF3Gt4Od8Bsu/ZMWkZJRh23lwZXBDbDwaXnSLDZRhCfex+YUZSm by63lGeLt+NXpUqFD38guAaaG7q8fYjlqCNtyVUP1fTEWx9JsnkywM1LThdOgmUVbxpJ KPT3n0pQeUXLDSKVroat5OmOzdO9qygFpkq1RQtFubMegYBg/1JReZJBaV9jq6ySrg3I 2L8eadaagzZBe8jUibljD1ZA4QZT8mdIl4YKIQ36IAnz5FPk0ukN+39x9ITIySUZAkY0 7n8MI2tHvS8tDdB4d5xw1vOPSch3aZTavnJ/fB17sy8tpralwdcE7E++DLX2tJrSVS1S l4lw== X-Gm-Message-State: ACrzQf2dkb/FVfWQ3l3pSHqAHtgQV/j/NxskvNiMD8nwFfNCKvmkLCdM ZM3MocQpw/2raUDKIOlgFKx8YLZaEd/84YeyRQ== X-Google-Smtp-Source: AMsMyM6risFKfbZuKovbo+0t+9Xyw8Wnj4rOsYEeFuENahbLsfXxQerIwc2nbPhKHu7taqOuFTBK1w== X-Received: by 2002:adf:e3cc:0:b0:235:95b1:2124 with SMTP id k12-20020adfe3cc000000b0023595b12124mr22390195wrm.693.1666772145874; Wed, 26 Oct 2022 01:15:45 -0700 (PDT) Received: from platypus.lan ([2001:861:5e4c:3bb0:6424:328a:1734:3249]) by smtp.googlemail.com with ESMTPSA id q16-20020a05600c46d000b003c6f426467fsm1134310wmo.40.2022.10.26.01.15.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Oct 2022 01:15:45 -0700 (PDT) From: arthur.cohen@embecosm.com To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org Subject: [PATCH Rust front-end v3 17/46] gccrs: Add declarations for Rust HIR Date: Wed, 26 Oct 2022 10:17:42 +0200 Message-Id: <20221026081811.602573-18-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20221026081811.602573-1-arthur.cohen@embecosm.com> References: <20221026081811.602573-1-arthur.cohen@embecosm.com> Reply-To: arthur.cohen@embecosm.com MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-12.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=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Philip Herron This patch contains the declarations needed for our second intermediate representation, which we will refer to as an HIR. This gives the front-end a chance to desugar alot of the AST such as: - Remove distinction between functions and methods - Remove Macros - Remove IdentifierExpr's - Remove duplicate attribute structures --- gcc/rust/hir/tree/rust-hir-expr.h | 4194 ++++++++++++++++++++++++++ gcc/rust/hir/tree/rust-hir-item.h | 3207 ++++++++++++++++++++ gcc/rust/hir/tree/rust-hir-path.h | 1013 +++++++ gcc/rust/hir/tree/rust-hir-pattern.h | 1356 +++++++++ gcc/rust/hir/tree/rust-hir-stmt.h | 273 ++ gcc/rust/hir/tree/rust-hir-type.h | 860 ++++++ 6 files changed, 10903 insertions(+) create mode 100644 gcc/rust/hir/tree/rust-hir-expr.h create mode 100644 gcc/rust/hir/tree/rust-hir-item.h create mode 100644 gcc/rust/hir/tree/rust-hir-path.h create mode 100644 gcc/rust/hir/tree/rust-hir-pattern.h create mode 100644 gcc/rust/hir/tree/rust-hir-stmt.h create mode 100644 gcc/rust/hir/tree/rust-hir-type.h diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h new file mode 100644 index 00000000000..83278529646 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -0,0 +1,4194 @@ +// 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_HIR_EXPR_H +#define RUST_HIR_EXPR_H + +#include "rust-common.h" +#include "rust-ast-full-decls.h" +#include "rust-hir.h" +#include "rust-hir-path.h" +#include "operator.h" + +namespace Rust { +namespace HIR { + +// HIR node for an expression with an accompanying block - abstract +class ExprWithBlock : public Expr +{ + // TODO: should this mean that a BlockExpr should be a member variable? +protected: + ExprWithBlock (Analysis::NodeMapping mappings, + AST::AttrVec outer_attrs = AST::AttrVec ()) + : Expr (std::move (mappings), std::move (outer_attrs)) + {} + + // pure virtual clone implementation + virtual ExprWithBlock *clone_expr_with_block_impl () const = 0; + + // prevent having to define multiple clone expressions + ExprWithBlock *clone_expr_impl () const override + { + return clone_expr_with_block_impl (); + } + +public: + // Unique pointer custom clone function + std::unique_ptr clone_expr_with_block () const + { + return std::unique_ptr (clone_expr_with_block_impl ()); + } + + BlockType get_block_expr_type () const final override + { + return BlockType::WITH_BLOCK; + }; +}; + +// Literals? Or literal base? +class LiteralExpr : public ExprWithoutBlock +{ + Literal literal; + Location locus; + +public: + std::string as_string () const override + { + return "( " + literal.as_string () + " (" + get_mappings ().as_string () + + "))"; + } + + Literal::LitType get_lit_type () const { return literal.get_lit_type (); } + + LiteralExpr (Analysis::NodeMapping mappings, std::string value_as_string, + Literal::LitType type, PrimitiveCoreType type_hint, + Location locus, AST::AttrVec outer_attrs) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)), + literal (std::move (value_as_string), type, type_hint), locus (locus) + {} + + LiteralExpr (Analysis::NodeMapping mappings, Literal literal, Location locus, + AST::AttrVec outer_attrs) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)), + literal (std::move (literal)), locus (locus) + {} + + // Unique pointer custom clone function + std::unique_ptr clone_literal_expr () const + { + return std::unique_ptr (clone_literal_expr_impl ()); + } + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + Literal &get_literal () { return literal; } + const Literal &get_literal () const { return literal; } + + ExprType get_expression_type () const override final { return ExprType::Lit; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + LiteralExpr *clone_expr_impl () const override + { + return new LiteralExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + LiteralExpr *clone_expr_without_block_impl () const override + { + return new LiteralExpr (*this); + } + + /* not virtual as currently no subclasses of LiteralExpr, but could be in + * future */ + /*virtual*/ LiteralExpr *clone_literal_expr_impl () const + { + return new LiteralExpr (*this); + } +}; + +/* Represents an expression using unary or binary operators as HIR node. Can be + * overloaded. */ +class OperatorExpr : public ExprWithoutBlock +{ + // TODO: create binary and unary operator subclasses? +public: + Location locus; + +protected: + /* Variable must be protected to allow derived classes to use it as a first + * class citizen */ + std::unique_ptr main_or_left_expr; + + // Constructor (only for initialisation of expr purposes) + OperatorExpr (Analysis::NodeMapping mappings, + std::unique_ptr main_or_left_expr, + AST::AttrVec outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + locus (locus), main_or_left_expr (std::move (main_or_left_expr)) + {} + + // Copy constructor (only for initialisation of expr purposes) + OperatorExpr (OperatorExpr const &other) + : ExprWithoutBlock (other), locus (other.locus), + main_or_left_expr (other.main_or_left_expr->clone_expr ()) + {} + + // Overload assignment operator to deep copy expr + OperatorExpr &operator= (OperatorExpr const &other) + { + ExprWithoutBlock::operator= (other); + main_or_left_expr = other.main_or_left_expr->clone_expr (); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + OperatorExpr (OperatorExpr &&other) = default; + OperatorExpr &operator= (OperatorExpr &&other) = default; + +public: + Location get_locus () const override final { return locus; } + + std::unique_ptr &get_expr () { return main_or_left_expr; } + + ExprType get_expression_type () const override final + { + return ExprType::Operator; + } +}; + +/* Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be + * overloaded. */ +class BorrowExpr : public OperatorExpr +{ + Mutability mut; + bool double_borrow; + +public: + std::string as_string () const override; + + BorrowExpr (Analysis::NodeMapping mappings, + std::unique_ptr borrow_lvalue, Mutability mut, + bool is_double_borrow, AST::AttrVec outer_attribs, Location locus) + : OperatorExpr (std::move (mappings), std::move (borrow_lvalue), + std::move (outer_attribs), locus), + mut (mut), double_borrow (is_double_borrow) + {} + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + Mutability get_mut () const { return mut; } + bool is_mut () const { return mut == Mutability::Mut; } + bool get_is_double_borrow () const { return double_borrow; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + BorrowExpr *clone_expr_impl () const override + { + return new BorrowExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + BorrowExpr *clone_expr_without_block_impl () const override + { + return new BorrowExpr (*this); + } +}; + +// Unary prefix * deference operator +class DereferenceExpr : public OperatorExpr +{ +public: + std::string as_string () const override; + + // Constructor calls OperatorExpr's protected constructor + DereferenceExpr (Analysis::NodeMapping mappings, + std::unique_ptr deref_lvalue, + AST::AttrVec outer_attribs, Location locus) + : OperatorExpr (std::move (mappings), std::move (deref_lvalue), + std::move (outer_attribs), locus) + {} + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + DereferenceExpr *clone_expr_impl () const override + { + return new DereferenceExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + DereferenceExpr *clone_expr_without_block_impl () const override + { + return new DereferenceExpr (*this); + } +}; + +// Unary postfix ? error propogation operator. Cannot be overloaded. +class ErrorPropagationExpr : public OperatorExpr +{ +public: + std::string as_string () const override; + + // Constructor calls OperatorExpr's protected constructor + ErrorPropagationExpr (Analysis::NodeMapping mappings, + std::unique_ptr potential_error_value, + AST::AttrVec outer_attribs, Location locus) + : OperatorExpr (std::move (mappings), std::move (potential_error_value), + std::move (outer_attribs), locus) + {} + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ErrorPropagationExpr *clone_expr_impl () const override + { + return new ErrorPropagationExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ErrorPropagationExpr *clone_expr_without_block_impl () const override + { + return new ErrorPropagationExpr (*this); + } +}; + +// Unary prefix - or ! negation or NOT operators. +class NegationExpr : public OperatorExpr +{ +public: + using ExprType = NegationOperator; + +private: + /* Note: overload negation via std::ops::Neg and not via std::ops::Not + * Negation only works for signed integer and floating-point types, NOT only + * works for boolean and integer types (via bitwise NOT) */ + ExprType expr_type; + +public: + std::string as_string () const override; + + ExprType get_expr_type () const { return expr_type; } + + // Constructor calls OperatorExpr's protected constructor + NegationExpr (Analysis::NodeMapping mappings, + std::unique_ptr negated_value, ExprType expr_kind, + AST::AttrVec outer_attribs, Location locus) + : OperatorExpr (std::move (mappings), std::move (negated_value), + std::move (outer_attribs), locus), + expr_type (expr_kind) + {} + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + NegationExpr *clone_expr_impl () const override + { + return new NegationExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + NegationExpr *clone_expr_without_block_impl () const override + { + return new NegationExpr (*this); + } +}; + +// Infix binary operators. +, -, *, /, %, &, |, ^, <<, >> +class ArithmeticOrLogicalExpr : public OperatorExpr +{ +public: + using ExprType = ArithmeticOrLogicalOperator; + +private: + // Note: overloading trait specified in comments + ExprType expr_type; + + std::unique_ptr right_expr; + +public: + std::string as_string () const override; + + ExprType get_expr_type () const { return expr_type; } + + // Constructor calls OperatorExpr's protected constructor + ArithmeticOrLogicalExpr (Analysis::NodeMapping mappings, + std::unique_ptr left_value, + std::unique_ptr right_value, + ExprType expr_kind, Location locus) + : OperatorExpr (std::move (mappings), std::move (left_value), + AST::AttrVec (), locus), + expr_type (expr_kind), right_expr (std::move (right_value)) + {} + // outer attributes not allowed + + // Copy constructor - probably required due to unique pointer + ArithmeticOrLogicalExpr (ArithmeticOrLogicalExpr const &other) + : OperatorExpr (other), expr_type (other.expr_type), + right_expr (other.right_expr->clone_expr ()) + {} + + // Overload assignment operator + ArithmeticOrLogicalExpr &operator= (ArithmeticOrLogicalExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr (); + expr_type = other.expr_type; + + return *this; + } + + // move constructors + ArithmeticOrLogicalExpr (ArithmeticOrLogicalExpr &&other) = default; + ArithmeticOrLogicalExpr &operator= (ArithmeticOrLogicalExpr &&other) + = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + void visit_lhs (HIRFullVisitor &vis) { main_or_left_expr->accept_vis (vis); } + void visit_rhs (HIRFullVisitor &vis) { right_expr->accept_vis (vis); } + + Expr *get_lhs () { return main_or_left_expr.get (); } + Expr *get_rhs () { return right_expr.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArithmeticOrLogicalExpr *clone_expr_impl () const override + { + return new ArithmeticOrLogicalExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArithmeticOrLogicalExpr *clone_expr_without_block_impl () const override + { + return new ArithmeticOrLogicalExpr (*this); + } +}; + +// Infix binary comparison operators. ==, !=, <, <=, >, >= +class ComparisonExpr : public OperatorExpr +{ +public: + using ExprType = ComparisonOperator; + +private: + // Note: overloading trait specified in comments + ExprType expr_type; + + std::unique_ptr right_expr; + +public: + std::string as_string () const override; + + ExprType get_expr_type () const { return expr_type; } + + // Constructor requires pointers for polymorphism + ComparisonExpr (Analysis::NodeMapping mappings, + std::unique_ptr left_value, + std::unique_ptr right_value, ExprType comparison_kind, + Location locus) + : OperatorExpr (std::move (mappings), std::move (left_value), + AST::AttrVec (), locus), + expr_type (comparison_kind), right_expr (std::move (right_value)) + {} + // outer attributes not allowed + + // Copy constructor also calls OperatorExpr's protected constructor + ComparisonExpr (ComparisonExpr const &other) + : OperatorExpr (other), expr_type (other.expr_type), + right_expr (other.right_expr->clone_expr ()) + {} + + // Overload assignment operator to deep copy + ComparisonExpr &operator= (ComparisonExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr (); + expr_type = other.expr_type; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ComparisonExpr (ComparisonExpr &&other) = default; + ComparisonExpr &operator= (ComparisonExpr &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + Expr *get_lhs () { return main_or_left_expr.get (); } + Expr *get_rhs () { return right_expr.get (); } + + ExprType get_kind () { return expr_type; } + + /* TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2) + * maybe? */ +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ComparisonExpr *clone_expr_impl () const override + { + return new ComparisonExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ComparisonExpr *clone_expr_without_block_impl () const override + { + return new ComparisonExpr (*this); + } +}; + +// Infix binary lazy boolean logical operators && and ||. +class LazyBooleanExpr : public OperatorExpr +{ +public: + using ExprType = LazyBooleanOperator; + +private: + ExprType expr_type; + + std::unique_ptr right_expr; + +public: + // Constructor calls OperatorExpr's protected constructor + LazyBooleanExpr (Analysis::NodeMapping mappings, + std::unique_ptr left_bool_expr, + std::unique_ptr right_bool_expr, ExprType expr_kind, + Location locus) + : OperatorExpr (std::move (mappings), std::move (left_bool_expr), + AST::AttrVec (), locus), + expr_type (expr_kind), right_expr (std::move (right_bool_expr)) + {} + // outer attributes not allowed + + // Copy constructor also calls OperatorExpr's protected constructor + LazyBooleanExpr (LazyBooleanExpr const &other) + : OperatorExpr (other), expr_type (other.expr_type), + right_expr (other.right_expr->clone_expr ()) + {} + + // Overload assignment operator to deep copy + LazyBooleanExpr &operator= (LazyBooleanExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr (); + expr_type = other.expr_type; + + return *this; + } + + // move constructors + LazyBooleanExpr (LazyBooleanExpr &&other) = default; + LazyBooleanExpr &operator= (LazyBooleanExpr &&other) = default; + + std::string as_string () const override; + + ExprType get_expr_type () const { return expr_type; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + Expr *get_lhs () { return main_or_left_expr.get (); } + + Expr *get_rhs () { return right_expr.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + LazyBooleanExpr *clone_expr_impl () const override + { + return new LazyBooleanExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + LazyBooleanExpr *clone_expr_without_block_impl () const override + { + return new LazyBooleanExpr (*this); + } +}; + +// Binary infix "as" chir expression. +class TypeCastExpr : public OperatorExpr +{ + std::unique_ptr type_to_convert_to; + + // Note: only certain type casts allowed, outlined in reference +public: + std::string as_string () const override; + + // Constructor requires calling protected constructor of OperatorExpr + TypeCastExpr (Analysis::NodeMapping mappings, + std::unique_ptr expr_to_cast, + std::unique_ptr type_to_cast_to, Location locus) + : OperatorExpr (std::move (mappings), std::move (expr_to_cast), + AST::AttrVec (), locus), + type_to_convert_to (std::move (type_to_cast_to)) + {} + // outer attributes not allowed + + // Copy constructor also requires calling protected constructor + TypeCastExpr (TypeCastExpr const &other) + : OperatorExpr (other), + type_to_convert_to (other.type_to_convert_to->clone_type ()) + {} + + // Overload assignment operator to deep copy + TypeCastExpr &operator= (TypeCastExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + type_to_convert_to = other.type_to_convert_to->clone_type (); + + return *this; + } + + // move constructors as not supported in c++03 + TypeCastExpr (TypeCastExpr &&other) = default; + TypeCastExpr &operator= (TypeCastExpr &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_casted_expr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + std::unique_ptr &get_type_to_convert_to () + { + rust_assert (type_to_convert_to != nullptr); + return type_to_convert_to; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TypeCastExpr *clone_expr_impl () const override + { + return new TypeCastExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + TypeCastExpr *clone_expr_without_block_impl () const override + { + return new TypeCastExpr (*this); + } +}; + +// Binary assignment expression. +class AssignmentExpr : public OperatorExpr +{ + std::unique_ptr right_expr; + +public: + std::string as_string () const override; + + // Call OperatorExpr constructor to initialise left_expr + AssignmentExpr (Analysis::NodeMapping mappings, + std::unique_ptr value_to_assign_to, + std::unique_ptr value_to_assign, Location locus) + : OperatorExpr (std::move (mappings), std::move (value_to_assign_to), + AST::AttrVec (), locus), + right_expr (std::move (value_to_assign)) + {} + // outer attributes not allowed + + // Call OperatorExpr constructor in copy constructor, as well as clone + AssignmentExpr (AssignmentExpr const &other) + : OperatorExpr (other), right_expr (other.right_expr->clone_expr ()) + {} + + // Overload assignment operator to clone unique_ptr right_expr + AssignmentExpr &operator= (AssignmentExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr (); + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + AssignmentExpr (AssignmentExpr &&other) = default; + AssignmentExpr &operator= (AssignmentExpr &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + void visit_lhs (HIRFullVisitor &vis) { main_or_left_expr->accept_vis (vis); } + void visit_rhs (HIRFullVisitor &vis) { right_expr->accept_vis (vis); } + + Expr *get_lhs () { return main_or_left_expr.get (); } + Expr *get_rhs () { return right_expr.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + AssignmentExpr *clone_expr_impl () const override + { + return new AssignmentExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + AssignmentExpr *clone_expr_without_block_impl () const override + { + return new AssignmentExpr (*this); + } +}; + +class CompoundAssignmentExpr : public OperatorExpr +{ +public: + using ExprType = ArithmeticOrLogicalOperator; + +private: + // Note: overloading trait specified in comments + ExprType expr_type; + std::unique_ptr right_expr; + +public: + std::string as_string () const override; + + ExprType get_expr_type () const { return expr_type; } + + // Use pointers in constructor to enable polymorphism + CompoundAssignmentExpr (Analysis::NodeMapping mappings, + std::unique_ptr value_to_assign_to, + std::unique_ptr value_to_assign, + ExprType expr_kind, Location locus) + : OperatorExpr (std::move (mappings), std::move (value_to_assign_to), + AST::AttrVec (), locus), + expr_type (expr_kind), right_expr (std::move (value_to_assign)) + {} + // outer attributes not allowed + + // Have clone in copy constructor + CompoundAssignmentExpr (CompoundAssignmentExpr const &other) + : OperatorExpr (other), expr_type (other.expr_type), + right_expr (other.right_expr->clone_expr ()) + {} + + // Overload assignment operator to clone + CompoundAssignmentExpr &operator= (CompoundAssignmentExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr (); + expr_type = other.expr_type; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + CompoundAssignmentExpr (CompoundAssignmentExpr &&other) = default; + CompoundAssignmentExpr &operator= (CompoundAssignmentExpr &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_left_expr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + std::unique_ptr &get_right_expr () + { + rust_assert (right_expr != nullptr); + return right_expr; + } + + void visit_lhs (HIRFullVisitor &vis) { main_or_left_expr->accept_vis (vis); } + void visit_rhs (HIRFullVisitor &vis) { right_expr->accept_vis (vis); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + CompoundAssignmentExpr *clone_expr_without_block_impl () const override + { + return new CompoundAssignmentExpr (*this); + } +}; + +// Expression in parentheses (i.e. like literally just any 3 + (2 * 6)) +class GroupedExpr : public ExprWithoutBlock +{ + AST::AttrVec inner_attrs; + std::unique_ptr expr_in_parens; + + Location locus; + +public: + std::string as_string () const override; + + AST::AttrVec get_inner_attrs () const { return inner_attrs; } + + GroupedExpr (Analysis::NodeMapping mappings, + std::unique_ptr parenthesised_expr, + AST::AttrVec inner_attribs, AST::AttrVec outer_attribs, + Location locus) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + inner_attrs (std::move (inner_attribs)), + expr_in_parens (std::move (parenthesised_expr)), locus (locus) + {} + + // Copy constructor includes clone for expr_in_parens + GroupedExpr (GroupedExpr const &other) + : ExprWithoutBlock (other), inner_attrs (other.inner_attrs), + expr_in_parens (other.expr_in_parens->clone_expr ()), locus (other.locus) + {} + + // Overloaded assignment operator to clone expr_in_parens + GroupedExpr &operator= (GroupedExpr const &other) + { + ExprWithoutBlock::operator= (other); + inner_attrs = other.inner_attrs; + expr_in_parens = other.expr_in_parens->clone_expr (); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + GroupedExpr (GroupedExpr &&other) = default; + GroupedExpr &operator= (GroupedExpr &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_expr_in_parens () + { + rust_assert (expr_in_parens != nullptr); + return expr_in_parens; + } + + ExprType get_expression_type () const override final + { + return ExprType::Grouped; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + GroupedExpr *clone_expr_impl () const override + { + return new GroupedExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + GroupedExpr *clone_expr_without_block_impl () const override + { + return new GroupedExpr (*this); + } +}; + +// Base array initialisation internal element representation thing (abstract) +// aka ArrayElements +class ArrayElems +{ +public: + enum ArrayExprType + { + VALUES, + COPIED, + }; + + ArrayElems (Analysis::NodeMapping mappings) : mappings (mappings){}; + + virtual ~ArrayElems () {} + + // Unique pointer custom clone ArrayElems function + std::unique_ptr clone_array_elems () const + { + return std::unique_ptr (clone_array_elems_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (HIRFullVisitor &vis) = 0; + + virtual ArrayExprType get_array_expr_type () const = 0; + + Analysis::NodeMapping &get_mappings () { return mappings; } + +protected: + // pure virtual clone implementation + virtual ArrayElems *clone_array_elems_impl () const = 0; + + Analysis::NodeMapping mappings; +}; + +// Value array elements +class ArrayElemsValues : public ArrayElems +{ + std::vector > values; + + // TODO: should this store location data? + +public: + ArrayElemsValues (Analysis::NodeMapping mappings, + std::vector > elems) + : ArrayElems (mappings), values (std::move (elems)) + {} + + // copy constructor with vector clone + ArrayElemsValues (ArrayElemsValues const &other) : ArrayElems (other) + { + values.reserve (other.values.size ()); + for (const auto &e : other.values) + values.push_back (e->clone_expr ()); + } + + // overloaded assignment operator with vector clone + ArrayElemsValues &operator= (ArrayElemsValues const &other) + { + values.reserve (other.values.size ()); + for (const auto &e : other.values) + values.push_back (e->clone_expr ()); + + return *this; + } + + // move constructors + ArrayElemsValues (ArrayElemsValues &&other) = default; + ArrayElemsValues &operator= (ArrayElemsValues &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + size_t get_num_elements () const { return values.size (); } + + std::vector > &get_values () { return values; } + + ArrayElems::ArrayExprType get_array_expr_type () const override final + { + return ArrayElems::ArrayExprType::VALUES; + } + +protected: + ArrayElemsValues *clone_array_elems_impl () const override + { + return new ArrayElemsValues (*this); + } +}; + +// Copied array element and number of copies +class ArrayElemsCopied : public ArrayElems +{ + std::unique_ptr elem_to_copy; + std::unique_ptr num_copies; + +public: + // Constructor requires pointers for polymorphism + ArrayElemsCopied (Analysis::NodeMapping mappings, + std::unique_ptr copied_elem, + std::unique_ptr copy_amount) + : ArrayElems (mappings), elem_to_copy (std::move (copied_elem)), + num_copies (std::move (copy_amount)) + {} + + // Copy constructor required due to unique_ptr - uses custom clone + ArrayElemsCopied (ArrayElemsCopied const &other) + : ArrayElems (other), elem_to_copy (other.elem_to_copy->clone_expr ()), + num_copies (other.num_copies->clone_expr ()) + {} + + // Overloaded assignment operator for deep copying + ArrayElemsCopied &operator= (ArrayElemsCopied const &other) + { + elem_to_copy = other.elem_to_copy->clone_expr (); + num_copies = other.num_copies->clone_expr (); + + return *this; + } + + // move constructors + ArrayElemsCopied (ArrayElemsCopied &&other) = default; + ArrayElemsCopied &operator= (ArrayElemsCopied &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + Expr *get_elem_to_copy () { return elem_to_copy.get (); } + + Expr *get_num_copies_expr () { return num_copies.get (); } + + ArrayElems::ArrayExprType get_array_expr_type () const override final + { + return ArrayElems::ArrayExprType::COPIED; + } + +protected: + ArrayElemsCopied *clone_array_elems_impl () const override + { + return new ArrayElemsCopied (*this); + } +}; + +// Array definition-ish expression +class ArrayExpr : public ExprWithoutBlock +{ + AST::AttrVec inner_attrs; + std::unique_ptr internal_elements; + + Location locus; + +public: + std::string as_string () const override; + + AST::AttrVec get_inner_attrs () const { return inner_attrs; } + + // Returns whether array expr has array elems or if it is just empty. + bool has_array_elems () const { return internal_elements != nullptr; } + + // Constructor requires ArrayElems pointer + ArrayExpr (Analysis::NodeMapping mappings, + std::unique_ptr array_elems, + AST::AttrVec inner_attribs, AST::AttrVec outer_attribs, + Location locus) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + inner_attrs (std::move (inner_attribs)), + internal_elements (std::move (array_elems)), locus (locus) + {} + + // Copy constructor requires cloning ArrayElems for polymorphism to hold + ArrayExpr (ArrayExpr const &other) + : ExprWithoutBlock (other), inner_attrs (other.inner_attrs), + locus (other.locus) + { + if (other.has_array_elems ()) + internal_elements = other.internal_elements->clone_array_elems (); + } + + // Overload assignment operator to clone internal_elements + ArrayExpr &operator= (ArrayExpr const &other) + { + ExprWithoutBlock::operator= (other); + inner_attrs = other.inner_attrs; + if (other.has_array_elems ()) + internal_elements = other.internal_elements->clone_array_elems (); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ArrayExpr (ArrayExpr &&other) = default; + ArrayExpr &operator= (ArrayExpr &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + ArrayElems *get_internal_elements () { return internal_elements.get (); }; + + ExprType get_expression_type () const override final + { + return ExprType::Array; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArrayExpr *clone_expr_impl () const override { return new ArrayExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArrayExpr *clone_expr_without_block_impl () const override + { + return new ArrayExpr (*this); + } +}; + +class ArrayIndexExpr : public ExprWithoutBlock +{ + std::unique_ptr array_expr; + std::unique_ptr index_expr; + + Location locus; + +public: + std::string as_string () const override; + + ArrayIndexExpr (Analysis::NodeMapping mappings, + std::unique_ptr array_expr, + std::unique_ptr array_index_expr, + AST::AttrVec outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + array_expr (std::move (array_expr)), + index_expr (std::move (array_index_expr)), locus (locus) + {} + + // Copy constructor requires special cloning due to unique_ptr + ArrayIndexExpr (ArrayIndexExpr const &other) + : ExprWithoutBlock (other), array_expr (other.array_expr->clone_expr ()), + index_expr (other.index_expr->clone_expr ()), locus (other.locus) + {} + + // Overload assignment operator to clone unique_ptrs + ArrayIndexExpr &operator= (ArrayIndexExpr const &other) + { + ExprWithoutBlock::operator= (other); + array_expr = other.array_expr->clone_expr (); + index_expr = other.index_expr->clone_expr (); + // outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + // move constructors + ArrayIndexExpr (ArrayIndexExpr &&other) = default; + ArrayIndexExpr &operator= (ArrayIndexExpr &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + Expr *get_array_expr () { return array_expr.get (); } + Expr *get_index_expr () { return index_expr.get (); } + + ExprType get_expression_type () const override final + { + return ExprType::ArrayIndex; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArrayIndexExpr *clone_expr_impl () const override + { + return new ArrayIndexExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArrayIndexExpr *clone_expr_without_block_impl () const override + { + return new ArrayIndexExpr (*this); + } +}; + +// HIR representation of a tuple +class TupleExpr : public ExprWithoutBlock +{ + AST::AttrVec inner_attrs; + + std::vector > tuple_elems; + // replaces (inlined version of) TupleElements + + Location locus; + +public: + std::string as_string () const override; + + AST::AttrVec get_inner_attrs () const { return inner_attrs; } + + TupleExpr (Analysis::NodeMapping mappings, + std::vector > tuple_elements, + AST::AttrVec inner_attribs, AST::AttrVec outer_attribs, + Location locus) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + inner_attrs (std::move (inner_attribs)), + tuple_elems (std::move (tuple_elements)), locus (locus) + {} + + // copy constructor with vector clone + TupleExpr (TupleExpr const &other) + : ExprWithoutBlock (other), inner_attrs (other.inner_attrs), + locus (other.locus) + { + tuple_elems.reserve (other.tuple_elems.size ()); + for (const auto &e : other.tuple_elems) + tuple_elems.push_back (e->clone_expr ()); + } + + // overloaded assignment operator to vector clone + TupleExpr &operator= (TupleExpr const &other) + { + ExprWithoutBlock::operator= (other); + inner_attrs = other.inner_attrs; + locus = other.locus; + + tuple_elems.reserve (other.tuple_elems.size ()); + for (const auto &e : other.tuple_elems) + tuple_elems.push_back (e->clone_expr ()); + + return *this; + } + + // move constructors + TupleExpr (TupleExpr &&other) = default; + TupleExpr &operator= (TupleExpr &&other) = default; + + /* Note: syntactically, can disambiguate single-element tuple from parens with + * comma, i.e. (0,) rather than (0) */ + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + const std::vector > &get_tuple_elems () const + { + return tuple_elems; + } + std::vector > &get_tuple_elems () + { + return tuple_elems; + } + + bool is_unit () const { return tuple_elems.size () == 0; } + + ExprType get_expression_type () const override final + { + return ExprType::Tuple; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleExpr *clone_expr_impl () const override { return new TupleExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleExpr *clone_expr_without_block_impl () const override + { + return new TupleExpr (*this); + } +}; + +class TupleIndexExpr : public ExprWithoutBlock +{ + std::unique_ptr tuple_expr; + TupleIndex tuple_index; + Location locus; + +public: + std::string as_string () const override; + + TupleIndex get_tuple_index () const { return tuple_index; } + + TupleIndexExpr (Analysis::NodeMapping mappings, + std::unique_ptr tuple_expr, TupleIndex index, + AST::AttrVec outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + tuple_expr (std::move (tuple_expr)), tuple_index (index), locus (locus) + {} + + // Copy constructor requires a clone for tuple_expr + TupleIndexExpr (TupleIndexExpr const &other) + : ExprWithoutBlock (other), tuple_expr (other.tuple_expr->clone_expr ()), + tuple_index (other.tuple_index), locus (other.locus) + {} + + // Overload assignment operator in order to clone + TupleIndexExpr &operator= (TupleIndexExpr const &other) + { + ExprWithoutBlock::operator= (other); + tuple_expr = other.tuple_expr->clone_expr (); + tuple_index = other.tuple_index; + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + TupleIndexExpr (TupleIndexExpr &&other) = default; + TupleIndexExpr &operator= (TupleIndexExpr &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_tuple_expr () + { + rust_assert (tuple_expr != nullptr); + return tuple_expr; + } + + ExprType get_expression_type () const override final + { + return ExprType::TupleIdx; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleIndexExpr *clone_expr_impl () const override + { + return new TupleIndexExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleIndexExpr *clone_expr_without_block_impl () const override + { + return new TupleIndexExpr (*this); + } +}; + +// Base struct/tuple/union value creator HIR node (abstract) +class StructExpr : public ExprWithoutBlock +{ +protected: + PathInExpression struct_name; + + // Protected constructor to allow initialising struct_name + StructExpr (Analysis::NodeMapping mappings, PathInExpression struct_path, + AST::AttrVec outer_attribs) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + struct_name (std::move (struct_path)) + {} + +public: + PathInExpression &get_struct_name () { return struct_name; } + + std::string as_string () const override; + + ExprType get_expression_type () const override final + { + return ExprType::Struct; + } +}; + +// Actual HIR node of the struct creator (with no fields). Not abstract! +class StructExprStruct : public StructExpr +{ + AST::AttrVec inner_attrs; + + Location locus; + +public: + std::string as_string () const override; + + AST::AttrVec get_inner_attrs () const { return inner_attrs; } + + // Constructor has to call protected constructor of base class + StructExprStruct (Analysis::NodeMapping mappings, + PathInExpression struct_path, AST::AttrVec inner_attribs, + AST::AttrVec outer_attribs, Location locus) + : StructExpr (std::move (mappings), std::move (struct_path), + std::move (outer_attribs)), + inner_attrs (std::move (inner_attribs)), locus (locus) + {} + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprStruct *clone_expr_impl () const override + { + return new StructExprStruct (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprStruct *clone_expr_without_block_impl () const override + { + return new StructExprStruct (*this); + } +}; + +/* HIR node representing expression used to fill a struct's fields from another + * struct */ +struct StructBase +{ +public: + std::unique_ptr base_struct; + + // TODO: should this store location data? + StructBase (std::unique_ptr base_struct_ptr) + : base_struct (std::move (base_struct_ptr)) + {} + + // Copy constructor requires clone + StructBase (StructBase const &other) + { + /* HACK: gets around base_struct pointer being null (e.g. if no struct base + * exists) */ + if (other.base_struct != nullptr) + other.base_struct->clone_expr (); + } + + // Destructor + ~StructBase () = default; + + // Overload assignment operator to clone base_struct + StructBase &operator= (StructBase const &other) + { + base_struct = other.base_struct->clone_expr (); + + return *this; + } + + // move constructors + StructBase (StructBase &&other) = default; + StructBase &operator= (StructBase &&other) = default; + + // Returns a null expr-ed StructBase - error state + static StructBase error () { return StructBase (nullptr); } + + // Returns whether StructBase is in error state + bool is_invalid () const { return base_struct == nullptr; } + + std::string as_string () const; + + Expr *get_base () { return base_struct.get (); } +}; + +/* Base HIR node for a single struct expression field (in struct instance + * creation) - abstract */ +class StructExprField +{ +public: + enum StructExprFieldKind + { + IDENTIFIER_VALUE, + IDENTIFIER, + INDEX_VALUE, + }; + + virtual ~StructExprField () {} + + // Unique pointer custom clone function + std::unique_ptr clone_struct_expr_field () const + { + return std::unique_ptr (clone_struct_expr_field_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (HIRFullVisitor &vis) = 0; + virtual void accept_vis (HIRExpressionVisitor &vis) = 0; + + Analysis::NodeMapping &get_mappings () { return mappings; } + + Location get_locus () { return locus; } + + virtual StructExprFieldKind get_kind () const = 0; + +protected: + // pure virtual clone implementation + virtual StructExprField *clone_struct_expr_field_impl () const = 0; + + StructExprField (Analysis::NodeMapping mapping, Location locus) + : mappings (mapping), locus (locus) + {} + + Analysis::NodeMapping mappings; + Location locus; +}; + +// Identifier-only variant of StructExprField HIR node +class StructExprFieldIdentifier : public StructExprField +{ +private: + Identifier field_name; + + // TODO: should this store location data? +public: + StructExprFieldIdentifier (Analysis::NodeMapping mapping, + Identifier field_identifier, Location locus) + : StructExprField (mapping, locus), + field_name (std::move (field_identifier)) + {} + + std::string as_string () const override { return field_name; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + Identifier get_field_name () const { return field_name; } + + StructExprFieldKind get_kind () const override + { + return StructExprFieldKind::IDENTIFIER; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprFieldIdentifier *clone_struct_expr_field_impl () const override + { + return new StructExprFieldIdentifier (*this); + } +}; + +/* Base HIR node for a single struct expression field with an assigned value - + * abstract */ +class StructExprFieldWithVal : public StructExprField +{ + std::unique_ptr value; + +protected: + StructExprFieldWithVal (Analysis::NodeMapping mapping, + std::unique_ptr field_value, Location locus) + : StructExprField (mapping, locus), value (std::move (field_value)) + {} + + // Copy constructor requires clone + StructExprFieldWithVal (StructExprFieldWithVal const &other) + : StructExprField (other.mappings, other.locus), + value (other.value->clone_expr ()) + {} + + // Overload assignment operator to clone unique_ptr + StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other) + { + value = other.value->clone_expr (); + mappings = other.mappings; + locus = other.locus; + + return *this; + } + + // move constructors + StructExprFieldWithVal (StructExprFieldWithVal &&other) = default; + StructExprFieldWithVal &operator= (StructExprFieldWithVal &&other) = default; + +public: + std::string as_string () const override; + + Expr *get_value () { return value.get (); } +}; + +// Identifier and value variant of StructExprField HIR node +class StructExprFieldIdentifierValue : public StructExprFieldWithVal +{ +public: + Identifier field_name; + + // TODO: should this store location data? + + StructExprFieldIdentifierValue (Analysis::NodeMapping mapping, + Identifier field_identifier, + std::unique_ptr field_value, + Location locus) + : StructExprFieldWithVal (mapping, std::move (field_value), locus), + field_name (std::move (field_identifier)) + {} + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + StructExprFieldKind get_kind () const override + { + return StructExprFieldKind::IDENTIFIER_VALUE; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprFieldIdentifierValue *clone_struct_expr_field_impl () const override + { + return new StructExprFieldIdentifierValue (*this); + } +}; + +// Tuple index and value variant of StructExprField HIR node +class StructExprFieldIndexValue : public StructExprFieldWithVal +{ +public: + TupleIndex index; + + // TODO: should this store location data? + + StructExprFieldIndexValue (Analysis::NodeMapping mapping, + TupleIndex tuple_index, + std::unique_ptr field_value, Location locus) + : StructExprFieldWithVal (mapping, std::move (field_value), locus), + index (tuple_index) + {} + + std::string as_string () const override; + + TupleIndex get_tuple_index () const { return index; }; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + StructExprFieldKind get_kind () const override + { + return StructExprFieldKind::INDEX_VALUE; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprFieldIndexValue *clone_struct_expr_field_impl () const override + { + return new StructExprFieldIndexValue (*this); + } +}; + +// HIR node of a struct creator with fields +class StructExprStructFields : public StructExprStruct +{ +public: + // std::vector fields; + std::vector > fields; + + // bool has_struct_base; + // FIXME make unique_ptr + StructBase *struct_base; + + // For unions there is just one field, the index + // is set when type checking + int union_index = -1; + + std::string as_string () const override; + + bool has_struct_base () const { return struct_base != nullptr; } + + // Constructor for StructExprStructFields when no struct base is used + StructExprStructFields ( + Analysis::NodeMapping mappings, PathInExpression struct_path, + std::vector > expr_fields, Location locus, + StructBase *base_struct, AST::AttrVec inner_attribs = AST::AttrVec (), + AST::AttrVec outer_attribs = AST::AttrVec ()) + : StructExprStruct (std::move (mappings), std::move (struct_path), + std::move (inner_attribs), std::move (outer_attribs), + locus), + fields (std::move (expr_fields)), struct_base (base_struct) + {} + + // copy constructor with vector clone + StructExprStructFields (StructExprStructFields const &other) + : StructExprStruct (other), struct_base (other.struct_base), + union_index (other.union_index) + { + fields.reserve (other.fields.size ()); + for (const auto &e : other.fields) + fields.push_back (e->clone_struct_expr_field ()); + } + + // overloaded assignment operator with vector clone + StructExprStructFields &operator= (StructExprStructFields const &other) + { + StructExprStruct::operator= (other); + struct_base = other.struct_base; + union_index = other.union_index; + + fields.reserve (other.fields.size ()); + for (const auto &e : other.fields) + fields.push_back (e->clone_struct_expr_field ()); + + return *this; + } + + // move constructors + StructExprStructFields (StructExprStructFields &&other) = default; + StructExprStructFields &operator= (StructExprStructFields &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::vector > &get_fields () + { + return fields; + }; + + const std::vector > &get_fields () const + { + return fields; + }; + + void set_fields_as_owner ( + std::vector > new_fields) + { + fields = std::move (new_fields); + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprStructFields *clone_expr_impl () const override + { + return new StructExprStructFields (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprStructFields *clone_expr_without_block_impl () const override + { + return new StructExprStructFields (*this); + } +}; + +// HIR node of the functional update struct creator +class StructExprStructBase : public StructExprStruct +{ + StructBase struct_base; + +public: + std::string as_string () const override; + + /*inline StructBase get_struct_base() const { + return struct_base; + }*/ + + StructExprStructBase (Analysis::NodeMapping mappings, + PathInExpression struct_path, StructBase base_struct, + AST::AttrVec inner_attribs, AST::AttrVec outer_attribs, + Location locus) + : StructExprStruct (std::move (mappings), std::move (struct_path), + std::move (inner_attribs), std::move (outer_attribs), + locus), + struct_base (std::move (base_struct)) + {} + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + StructBase *get_struct_base () { return &struct_base; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprStructBase *clone_expr_impl () const override + { + return new StructExprStructBase (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprStructBase *clone_expr_without_block_impl () const override + { + return new StructExprStructBase (*this); + } +}; + +// Function call expression HIR node +class CallExpr : public ExprWithoutBlock +{ + std::unique_ptr function; + std::vector > params; + Location locus; + +public: + std::string as_string () const override; + + CallExpr (Analysis::NodeMapping mappings, std::unique_ptr function_expr, + std::vector > function_params, + AST::AttrVec outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + function (std::move (function_expr)), + params (std::move (function_params)), locus (locus) + {} + + // copy constructor requires clone + CallExpr (CallExpr const &other) + : ExprWithoutBlock (other), function (other.function->clone_expr ()), + locus (other.locus) + /*, params(other.params),*/ { + params.reserve (other.params.size ()); + for (const auto &e : other.params) + params.push_back (e->clone_expr ()); + } + + // Overload assignment operator to clone + CallExpr &operator= (CallExpr const &other) + { + ExprWithoutBlock::operator= (other); + function = other.function->clone_expr (); + locus = other.locus; + // params = other.params; + // outer_attrs = other.outer_attrs; + + params.reserve (other.params.size ()); + for (const auto &e : other.params) + params.push_back (e->clone_expr ()); + + return *this; + } + + // move constructors + CallExpr (CallExpr &&other) = default; + CallExpr &operator= (CallExpr &&other) = default; + + // Returns whether function call has parameters. + bool has_params () const { return !params.empty (); } + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + Expr *get_fnexpr () { return function.get (); } + + size_t num_params () const { return params.size (); } + + std::vector > &get_arguments () { return params; } + + const std::vector > &get_arguments () const + { + return params; + } + + ExprType get_expression_type () const override final + { + return ExprType::Call; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + CallExpr *clone_expr_impl () const override { return new CallExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + CallExpr *clone_expr_without_block_impl () const override + { + return new CallExpr (*this); + } +}; + +// Method call expression HIR node +class MethodCallExpr : public ExprWithoutBlock +{ + std::unique_ptr receiver; + PathExprSegment method_name; + std::vector > params; + Location locus; + +public: + std::string as_string () const override; + + MethodCallExpr (Analysis::NodeMapping mappings, + std::unique_ptr call_receiver, + PathExprSegment method_path, + std::vector > method_params, + AST::AttrVec outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + receiver (std::move (call_receiver)), + method_name (std::move (method_path)), params (std::move (method_params)), + locus (locus) + {} + + // copy constructor required due to cloning + MethodCallExpr (MethodCallExpr const &other) + : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()), + method_name (other.method_name), locus (other.locus) + /*, params(other.params),*/ { + params.reserve (other.params.size ()); + for (const auto &e : other.params) + params.push_back (e->clone_expr ()); + } + + // Overload assignment operator to clone receiver object + MethodCallExpr &operator= (MethodCallExpr const &other) + { + ExprWithoutBlock::operator= (other); + receiver = other.receiver->clone_expr (); + method_name = other.method_name; + locus = other.locus; + // params = other.params; + // outer_attrs = other.outer_attrs; + + params.reserve (other.params.size ()); + for (const auto &e : other.params) + params.push_back (e->clone_expr ()); + + return *this; + } + + // move constructors + MethodCallExpr (MethodCallExpr &&other) = default; + MethodCallExpr &operator= (MethodCallExpr &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_receiver () { return receiver; } + + PathExprSegment get_method_name () const { return method_name; }; + + size_t num_params () const { return params.size (); } + + std::vector > &get_arguments () { return params; } + + const std::vector > &get_arguments () const + { + return params; + } + + ExprType get_expression_type () const override final + { + return ExprType::MethodCall; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + MethodCallExpr *clone_expr_impl () const override + { + return new MethodCallExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + MethodCallExpr *clone_expr_without_block_impl () const override + { + return new MethodCallExpr (*this); + } +}; + +// aka FieldExpression +// Struct or union field access expression HIR node +class FieldAccessExpr : public ExprWithoutBlock +{ + std::unique_ptr receiver; + Identifier field; + + Location locus; + +public: + std::string as_string () const override; + + FieldAccessExpr (Analysis::NodeMapping mappings, + std::unique_ptr field_access_receiver, + Identifier field_name, AST::AttrVec outer_attribs, + Location locus) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + receiver (std::move (field_access_receiver)), + field (std::move (field_name)), locus (locus) + {} + + // Copy constructor required due to unique_ptr cloning + FieldAccessExpr (FieldAccessExpr const &other) + : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()), + field (other.field), locus (other.locus) + {} + + // Overload assignment operator to clone unique_ptr + FieldAccessExpr &operator= (FieldAccessExpr const &other) + { + ExprWithoutBlock::operator= (other); + receiver = other.receiver->clone_expr (); + field = other.field; + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + FieldAccessExpr (FieldAccessExpr &&other) = default; + FieldAccessExpr &operator= (FieldAccessExpr &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_receiver_expr () + { + rust_assert (receiver != nullptr); + return receiver; + } + + Identifier get_field_name () const { return field; } + + ExprType get_expression_type () const override final + { + return ExprType::FieldAccess; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + FieldAccessExpr *clone_expr_impl () const override + { + return new FieldAccessExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + FieldAccessExpr *clone_expr_without_block_impl () const override + { + return new FieldAccessExpr (*this); + } +}; + +// Closure parameter data structure +struct ClosureParam +{ +private: + std::unique_ptr pattern; + + // bool has_type_given; + std::unique_ptr type; + + // TODO: should this store location data? + +public: + // Returns whether the type of the parameter has been given. + bool has_type_given () const { return type != nullptr; } + + // Constructor for closure parameter + ClosureParam (std::unique_ptr param_pattern, + std::unique_ptr param_type = nullptr) + : pattern (std::move (param_pattern)), type (std::move (param_type)) + {} + + // Copy constructor required due to cloning as a result of unique_ptrs + ClosureParam (ClosureParam const &other) + : pattern (other.pattern->clone_pattern ()) + { + // guard to protect from null pointer dereference + if (other.type != nullptr) + type = other.type->clone_type (); + } + + ~ClosureParam () = default; + + // Assignment operator must be overloaded to clone as well + ClosureParam &operator= (ClosureParam const &other) + { + pattern = other.pattern->clone_pattern (); + type = other.type->clone_type (); + + return *this; + } + + // move constructors + ClosureParam (ClosureParam &&other) = default; + ClosureParam &operator= (ClosureParam &&other) = default; + + // Returns whether closure parameter is in an error state. + bool is_error () const { return pattern == nullptr; } + + // Creates an error state closure parameter. + static ClosureParam create_error () { return ClosureParam (nullptr); } + + std::string as_string () const; +}; + +// Base closure definition expression HIR node - abstract +class ClosureExpr : public ExprWithoutBlock +{ + bool has_move; + std::vector params; + Location locus; + +protected: + ClosureExpr (Analysis::NodeMapping mappings, + std::vector closure_params, bool has_move, + AST::AttrVec outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + has_move (has_move), params (std::move (closure_params)), locus (locus) + {} + +public: + std::string as_string () const override; + + Location get_locus () const override final { return locus; } + + ExprType get_expression_type () const override final + { + return ExprType::Closure; + } +}; + +// Represents a non-type-specified closure expression HIR node +class ClosureExprInner : public ClosureExpr +{ + std::unique_ptr closure_inner; + +public: + std::string as_string () const override; + + // Constructor for a ClosureExprInner + ClosureExprInner (Analysis::NodeMapping mappings, + std::unique_ptr closure_inner_expr, + std::vector closure_params, Location locus, + bool is_move = false, + AST::AttrVec outer_attribs = AST::AttrVec ()) + : ClosureExpr (std::move (mappings), std::move (closure_params), is_move, + std::move (outer_attribs), locus), + closure_inner (std::move (closure_inner_expr)) + {} + + // Copy constructor must be defined to allow copying via cloning of unique_ptr + ClosureExprInner (ClosureExprInner const &other) + : ClosureExpr (other), closure_inner (other.closure_inner->clone_expr ()) + {} + + // Overload assignment operator to clone closure_inner + ClosureExprInner &operator= (ClosureExprInner const &other) + { + ClosureExpr::operator= (other); + closure_inner = other.closure_inner->clone_expr (); + // params = other.params; + // has_move = other.has_move; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ClosureExprInner (ClosureExprInner &&other) = default; + ClosureExprInner &operator= (ClosureExprInner &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ClosureExprInner *clone_expr_impl () const override + { + return new ClosureExprInner (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ClosureExprInner *clone_expr_without_block_impl () const override + { + return new ClosureExprInner (*this); + } +}; + +// A block HIR node +class BlockExpr : public ExprWithBlock +{ +public: + AST::AttrVec inner_attrs; + std::vector > statements; + std::unique_ptr expr; + bool tail_reachable; + Location start_locus; + Location end_locus; + + std::string as_string () const override; + + // Returns whether the block contains statements. + bool has_statements () const { return !statements.empty (); } + + // Returns whether the block contains an expression + bool has_expr () const { return expr != nullptr; } + + bool is_tail_reachable () const { return tail_reachable; } + + BlockExpr (Analysis::NodeMapping mappings, + std::vector > block_statements, + std::unique_ptr block_expr, bool tail_reachable, + AST::AttrVec inner_attribs, AST::AttrVec outer_attribs, + Location start_locus, Location end_locus) + : ExprWithBlock (std::move (mappings), std::move (outer_attribs)), + inner_attrs (std::move (inner_attribs)), + statements (std::move (block_statements)), expr (std::move (block_expr)), + tail_reachable (tail_reachable), start_locus (start_locus), + end_locus (end_locus) + {} + + // Copy constructor with clone + BlockExpr (BlockExpr const &other) + : ExprWithBlock (other), /*statements(other.statements),*/ + inner_attrs (other.inner_attrs), start_locus (other.start_locus), + end_locus (other.end_locus) + { + // guard to protect from null pointer dereference + if (other.expr != nullptr) + expr = other.expr->clone_expr (); + + statements.reserve (other.statements.size ()); + for (const auto &e : other.statements) + statements.push_back (e->clone_stmt ()); + } + + // Overloaded assignment operator to clone pointer + BlockExpr &operator= (BlockExpr const &other) + { + ExprWithBlock::operator= (other); + // statements = other.statements; + expr = other.expr->clone_expr (); + inner_attrs = other.inner_attrs; + start_locus = other.end_locus; + end_locus = other.end_locus; + // outer_attrs = other.outer_attrs; + + statements.reserve (other.statements.size ()); + for (const auto &e : other.statements) + statements.push_back (e->clone_stmt ()); + + return *this; + } + + // move constructors + BlockExpr (BlockExpr &&other) = default; + BlockExpr &operator= (BlockExpr &&other) = default; + + // Unique pointer custom clone function + std::unique_ptr clone_block_expr () const + { + return std::unique_ptr (clone_block_expr_impl ()); + } + + Location get_locus () const override final { return start_locus; } + + Location get_start_locus () const { return start_locus; } + + Location get_end_locus () const { return end_locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + bool is_final_stmt (Stmt *stmt) { return statements.back ().get () == stmt; } + + std::unique_ptr &get_final_expr () { return expr; } + + std::vector > &get_statements () { return statements; } + + ExprType get_expression_type () const final override + { + return ExprType::Block; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + BlockExpr *clone_expr_impl () const override + { + return clone_block_expr_impl (); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + BlockExpr *clone_expr_with_block_impl () const override + { + return clone_block_expr_impl (); + } + + /* This is the base method as not an abstract class - not virtual but could be + * in future if required. */ + /*virtual*/ BlockExpr *clone_block_expr_impl () const + { + return new BlockExpr (*this); + } +}; + +// Represents a type-specified closure expression HIR node +class ClosureExprInnerTyped : public ClosureExpr +{ + std::unique_ptr return_type; + std::unique_ptr + expr; // only used because may be polymorphic in future + +public: + std::string as_string () const override; + + // Constructor potentially with a move + ClosureExprInnerTyped (Analysis::NodeMapping mappings, + std::unique_ptr closure_return_type, + std::unique_ptr closure_expr, + std::vector closure_params, + Location locus, bool is_move = false, + AST::AttrVec outer_attribs = AST::AttrVec ()) + : ClosureExpr (std::move (mappings), std::move (closure_params), is_move, + std::move (outer_attribs), locus), + return_type (std::move (closure_return_type)), + expr (std::move (closure_expr)) + {} + + // Copy constructor requires cloning + ClosureExprInnerTyped (ClosureExprInnerTyped const &other) + : ClosureExpr (other), return_type (other.return_type->clone_type ()), + expr (other.expr->clone_block_expr ()) + {} + + // Overload assignment operator to clone unique_ptrs + ClosureExprInnerTyped &operator= (ClosureExprInnerTyped const &other) + { + ClosureExpr::operator= (other); + return_type = other.return_type->clone_type (); + expr = other.expr->clone_block_expr (); + // params = other.params; + // has_move = other.has_move; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ClosureExprInnerTyped (ClosureExprInnerTyped &&other) = default; + ClosureExprInnerTyped &operator= (ClosureExprInnerTyped &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ClosureExprInnerTyped *clone_expr_impl () const override + { + return new ClosureExprInnerTyped (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ClosureExprInnerTyped *clone_expr_without_block_impl () const override + { + return new ClosureExprInnerTyped (*this); + } +}; + +// HIR node representing continue expression within loops +class ContinueExpr : public ExprWithoutBlock +{ + Lifetime label; + Location locus; + +public: + std::string as_string () const override; + + // Returns true if the continue expr has a label. + bool has_label () const { return !label.is_error (); } + + // Constructor for a ContinueExpr with a label. + ContinueExpr (Analysis::NodeMapping mappings, Location locus, Lifetime label, + AST::AttrVec outer_attribs = AST::AttrVec ()) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + label (std::move (label)), locus (locus) + {} + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + Lifetime &get_label () { return label; } + + ExprType get_expression_type () const final override + { + return ExprType::Continue; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ContinueExpr *clone_expr_impl () const override + { + return new ContinueExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ContinueExpr *clone_expr_without_block_impl () const override + { + return new ContinueExpr (*this); + } +}; + +// HIR node representing break expression within loops +class BreakExpr : public ExprWithoutBlock +{ + // bool has_label; + Lifetime label; + + // bool has_break_expr; + std::unique_ptr break_expr; + + Location locus; + +public: + std::string as_string () const override; + + // Returns whether the break expression has a label or not. + bool has_label () const { return !label.is_error (); } + + /* Returns whether the break expression has an expression used in the break or + * not. */ + bool has_break_expr () const { return break_expr != nullptr; } + + // Constructor for a break expression + BreakExpr (Analysis::NodeMapping mappings, Location locus, + Lifetime break_label, + std::unique_ptr expr_in_break = nullptr, + AST::AttrVec outer_attribs = AST::AttrVec ()) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + label (std::move (break_label)), break_expr (std::move (expr_in_break)), + locus (locus) + {} + + // Copy constructor defined to use clone for unique pointer + BreakExpr (BreakExpr const &other) + : ExprWithoutBlock (other), label (other.label), locus (other.locus) + { + // guard to protect from null pointer dereference + if (other.break_expr != nullptr) + break_expr = other.break_expr->clone_expr (); + } + + // Overload assignment operator to clone unique pointer + BreakExpr &operator= (BreakExpr const &other) + { + ExprWithoutBlock::operator= (other); + label = other.label; + break_expr = other.break_expr->clone_expr (); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + BreakExpr (BreakExpr &&other) = default; + BreakExpr &operator= (BreakExpr &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + Lifetime &get_label () { return label; } + + std::unique_ptr &get_expr () { return break_expr; } + + ExprType get_expression_type () const override final + { + return ExprType::Break; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + BreakExpr *clone_expr_impl () const override { return new BreakExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + BreakExpr *clone_expr_without_block_impl () const override + { + return new BreakExpr (*this); + } +}; + +// Base range expression HIR node object - abstract +class RangeExpr : public ExprWithoutBlock +{ + Location locus; + +protected: + // outer attributes not allowed before range expressions + RangeExpr (Analysis::NodeMapping mappings, Location locus) + : ExprWithoutBlock (std::move (mappings), AST::AttrVec ()), locus (locus) + {} + +public: + Location get_locus () const override final { return locus; } + + ExprType get_expression_type () const override final + { + return ExprType::Range; + } +}; + +// Range from (inclusive) and to (exclusive) expression HIR node object +// aka RangeExpr; constructs a std::ops::Range object +class RangeFromToExpr : public RangeExpr +{ + std::unique_ptr from; + std::unique_ptr to; + +public: + std::string as_string () const override; + + RangeFromToExpr (Analysis::NodeMapping mappings, + std::unique_ptr range_from, + std::unique_ptr range_to, Location locus) + : RangeExpr (std::move (mappings), locus), from (std::move (range_from)), + to (std::move (range_to)) + {} + + // Copy constructor with cloning + RangeFromToExpr (RangeFromToExpr const &other) + : RangeExpr (other), from (other.from->clone_expr ()), + to (other.to->clone_expr ()) + {} + + // Overload assignment operator to clone unique pointers + RangeFromToExpr &operator= (RangeFromToExpr const &other) + { + RangeExpr::operator= (other); + from = other.from->clone_expr (); + to = other.to->clone_expr (); + + return *this; + } + + // move constructors + RangeFromToExpr (RangeFromToExpr &&other) = default; + RangeFromToExpr &operator= (RangeFromToExpr &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_from_expr () { return from; } + std::unique_ptr &get_to_expr () { return to; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFromToExpr *clone_expr_impl () const override + { + return new RangeFromToExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFromToExpr *clone_expr_without_block_impl () const override + { + return new RangeFromToExpr (*this); + } +}; + +// Range from (inclusive) expression HIR node object +// constructs a std::ops::RangeFrom object +class RangeFromExpr : public RangeExpr +{ + std::unique_ptr from; + +public: + std::string as_string () const override; + + RangeFromExpr (Analysis::NodeMapping mappings, + std::unique_ptr range_from, Location locus) + : RangeExpr (std::move (mappings), locus), from (std::move (range_from)) + {} + + // Copy constructor with clone + RangeFromExpr (RangeFromExpr const &other) + : RangeExpr (other), from (other.from->clone_expr ()) + {} + + // Overload assignment operator to clone unique_ptr + RangeFromExpr &operator= (RangeFromExpr const &other) + { + RangeExpr::operator= (other); + from = other.from->clone_expr (); + + return *this; + } + + // move constructors + RangeFromExpr (RangeFromExpr &&other) = default; + RangeFromExpr &operator= (RangeFromExpr &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_from_expr () { return from; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFromExpr *clone_expr_impl () const override + { + return new RangeFromExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFromExpr *clone_expr_without_block_impl () const override + { + return new RangeFromExpr (*this); + } +}; + +// Range to (exclusive) expression HIR node object +// constructs a std::ops::RangeTo object +class RangeToExpr : public RangeExpr +{ + std::unique_ptr to; + +public: + std::string as_string () const override; + + // outer attributes not allowed + RangeToExpr (Analysis::NodeMapping mappings, std::unique_ptr range_to, + Location locus) + : RangeExpr (std::move (mappings), locus), to (std::move (range_to)) + {} + + // Copy constructor with clone + RangeToExpr (RangeToExpr const &other) + : RangeExpr (other), to (other.to->clone_expr ()) + {} + + // Overload assignment operator to clone unique_ptr + RangeToExpr &operator= (RangeToExpr const &other) + { + RangeExpr::operator= (other); + to = other.to->clone_expr (); + + return *this; + } + + // move constructors + RangeToExpr (RangeToExpr &&other) = default; + RangeToExpr &operator= (RangeToExpr &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_to_expr () { return to; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeToExpr *clone_expr_impl () const override + { + return new RangeToExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeToExpr *clone_expr_without_block_impl () const override + { + return new RangeToExpr (*this); + } +}; + +// Full range expression HIR node object +// constructs a std::ops::RangeFull object +class RangeFullExpr : public RangeExpr +{ +public: + std::string as_string () const override; + + RangeFullExpr (Analysis::NodeMapping mappings, Location locus) + : RangeExpr (std::move (mappings), locus) + {} + // outer attributes not allowed + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFullExpr *clone_expr_impl () const override + { + return new RangeFullExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFullExpr *clone_expr_without_block_impl () const override + { + return new RangeFullExpr (*this); + } +}; + +// Range from (inclusive) and to (inclusive) expression HIR node object +// aka RangeInclusiveExpr; constructs a std::ops::RangeInclusive object +class RangeFromToInclExpr : public RangeExpr +{ + std::unique_ptr from; + std::unique_ptr to; + +public: + std::string as_string () const override; + + RangeFromToInclExpr (Analysis::NodeMapping mappings, + std::unique_ptr range_from, + std::unique_ptr range_to, Location locus) + : RangeExpr (std::move (mappings), locus), from (std::move (range_from)), + to (std::move (range_to)) + {} + // outer attributes not allowed + + // Copy constructor with clone + RangeFromToInclExpr (RangeFromToInclExpr const &other) + : RangeExpr (other), from (other.from->clone_expr ()), + to (other.to->clone_expr ()) + {} + + // Overload assignment operator to use clone + RangeFromToInclExpr &operator= (RangeFromToInclExpr const &other) + { + RangeExpr::operator= (other); + from = other.from->clone_expr (); + to = other.to->clone_expr (); + + return *this; + } + + // move constructors + RangeFromToInclExpr (RangeFromToInclExpr &&other) = default; + RangeFromToInclExpr &operator= (RangeFromToInclExpr &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_from_expr () { return from; } + std::unique_ptr &get_to_expr () { return to; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFromToInclExpr *clone_expr_impl () const override + { + return new RangeFromToInclExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFromToInclExpr *clone_expr_without_block_impl () const override + { + return new RangeFromToInclExpr (*this); + } +}; + +// Range to (inclusive) expression HIR node object +// aka RangeToInclusiveExpr; constructs a std::ops::RangeToInclusive object +class RangeToInclExpr : public RangeExpr +{ + std::unique_ptr to; + +public: + std::string as_string () const override; + + RangeToInclExpr (Analysis::NodeMapping mappings, + std::unique_ptr range_to, Location locus) + : RangeExpr (std::move (mappings), locus), to (std::move (range_to)) + {} + // outer attributes not allowed + + // Copy constructor with clone + RangeToInclExpr (RangeToInclExpr const &other) + : RangeExpr (other), to (other.to->clone_expr ()) + {} + + // Overload assignment operator to clone pointer + RangeToInclExpr &operator= (RangeToInclExpr const &other) + { + RangeExpr::operator= (other); + to = other.to->clone_expr (); + + return *this; + } + + // move constructors + RangeToInclExpr (RangeToInclExpr &&other) = default; + RangeToInclExpr &operator= (RangeToInclExpr &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_to_expr () { return to; }; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeToInclExpr *clone_expr_impl () const override + { + return new RangeToInclExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeToInclExpr *clone_expr_without_block_impl () const override + { + return new RangeToInclExpr (*this); + } +}; + +// Return expression HIR node representation +class ReturnExpr : public ExprWithoutBlock +{ +public: + std::unique_ptr return_expr; + + Location locus; + + std::string as_string () const override; + + /* Returns whether the object has an expression returned (i.e. not void return + * type). */ + bool has_return_expr () const { return return_expr != nullptr; } + + // Constructor for ReturnExpr. + ReturnExpr (Analysis::NodeMapping mappings, Location locus, + std::unique_ptr returned_expr = nullptr, + AST::AttrVec outer_attribs = AST::AttrVec ()) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + return_expr (std::move (returned_expr)), locus (locus) + {} + + // Copy constructor with clone + ReturnExpr (ReturnExpr const &other) + : ExprWithoutBlock (other), locus (other.locus) + { + // guard to protect from null pointer dereference + if (other.return_expr != nullptr) + return_expr = other.return_expr->clone_expr (); + } + + // Overloaded assignment operator to clone return_expr pointer + ReturnExpr &operator= (ReturnExpr const &other) + { + ExprWithoutBlock::operator= (other); + return_expr = other.return_expr->clone_expr (); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ReturnExpr (ReturnExpr &&other) = default; + ReturnExpr &operator= (ReturnExpr &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + Expr *get_expr () { return return_expr.get (); } + + ExprType get_expression_type () const override final + { + return ExprType::Return; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ReturnExpr *clone_expr_impl () const override + { + return new ReturnExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ReturnExpr *clone_expr_without_block_impl () const override + { + return new ReturnExpr (*this); + } +}; + +// An unsafe block HIR node +class UnsafeBlockExpr : public ExprWithBlock +{ + // Or just have it extend BlockExpr + std::unique_ptr expr; + Location locus; + +public: + std::string as_string () const override; + + UnsafeBlockExpr (Analysis::NodeMapping mappings, + std::unique_ptr block_expr, + AST::AttrVec outer_attribs, Location locus) + : ExprWithBlock (std::move (mappings), std::move (outer_attribs)), + expr (std::move (block_expr)), locus (locus) + {} + + // Copy constructor with clone + UnsafeBlockExpr (UnsafeBlockExpr const &other) + : ExprWithBlock (other), expr (other.expr->clone_block_expr ()), + locus (other.locus) + {} + + // Overloaded assignment operator to clone + UnsafeBlockExpr &operator= (UnsafeBlockExpr const &other) + { + ExprWithBlock::operator= (other); + expr = other.expr->clone_block_expr (); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + UnsafeBlockExpr (UnsafeBlockExpr &&other) = default; + UnsafeBlockExpr &operator= (UnsafeBlockExpr &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_block_expr () { return expr; } + + ExprType get_expression_type () const override final + { + return ExprType::UnsafeBlock; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + UnsafeBlockExpr *clone_expr_impl () const override + { + return new UnsafeBlockExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + UnsafeBlockExpr *clone_expr_with_block_impl () const override + { + return new UnsafeBlockExpr (*this); + } +}; + +// Loop label expression HIR node used with break and continue expressions +// TODO: inline? +class LoopLabel /*: public Node*/ +{ + Lifetime label; // or type LIFETIME_OR_LABEL + + Location locus; + + Analysis::NodeMapping mappings; + +public: + std::string as_string () const; + + LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label, Location locus) + : label (std::move (loop_label)), locus (locus), mappings (mapping) + {} + + // Returns whether the LoopLabel is in an error state. + bool is_error () const { return label.is_error (); } + + Location get_locus () const { return locus; } + + Analysis::NodeMapping &get_mappings () { return mappings; } + + Lifetime &get_lifetime () { return label; } +}; + +// Base loop expression HIR node - aka LoopExpr +class BaseLoopExpr : public ExprWithBlock +{ +protected: + LoopLabel loop_label; + std::unique_ptr loop_block; + +private: + Location locus; + +protected: + // Constructor for BaseLoopExpr + BaseLoopExpr (Analysis::NodeMapping mappings, + std::unique_ptr loop_block, Location locus, + LoopLabel loop_label, + AST::AttrVec outer_attribs = AST::AttrVec ()) + : ExprWithBlock (std::move (mappings), std::move (outer_attribs)), + loop_label (std::move (loop_label)), loop_block (std::move (loop_block)), + locus (locus) + {} + + // Copy constructor for BaseLoopExpr with clone + BaseLoopExpr (BaseLoopExpr const &other) + : ExprWithBlock (other), loop_label (other.loop_label), + loop_block (other.loop_block->clone_block_expr ()), locus (other.locus) + {} + + // Overloaded assignment operator to clone + BaseLoopExpr &operator= (BaseLoopExpr const &other) + { + ExprWithBlock::operator= (other); + loop_block = other.loop_block->clone_block_expr (); + loop_label = other.loop_label; + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + BaseLoopExpr (BaseLoopExpr &&other) = default; + BaseLoopExpr &operator= (BaseLoopExpr &&other) = default; + + ExprType get_expression_type () const final override + { + return ExprType::BaseLoop; + } + +public: + bool has_loop_label () const { return !loop_label.is_error (); } + + Location get_locus () const override final { return locus; } + + std::unique_ptr &get_loop_block () { return loop_block; }; + + LoopLabel &get_loop_label () { return loop_label; } +}; + +// 'Loop' expression (i.e. the infinite loop) HIR node +class LoopExpr : public BaseLoopExpr +{ +public: + std::string as_string () const override; + + // Constructor for LoopExpr + LoopExpr (Analysis::NodeMapping mappings, + std::unique_ptr loop_block, Location locus, + LoopLabel loop_label, AST::AttrVec outer_attribs = AST::AttrVec ()) + : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, + std::move (loop_label), std::move (outer_attribs)) + {} + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + LoopExpr *clone_expr_impl () const override { return new LoopExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + LoopExpr *clone_expr_with_block_impl () const override + { + return new LoopExpr (*this); + } +}; + +// While loop expression HIR node (predicate loop) +class WhileLoopExpr : public BaseLoopExpr +{ + std::unique_ptr condition; + +public: + std::string as_string () const override; + + // Constructor for while loop with loop label + WhileLoopExpr (Analysis::NodeMapping mappings, + std::unique_ptr loop_condition, + std::unique_ptr loop_block, Location locus, + LoopLabel loop_label, + AST::AttrVec outer_attribs = AST::AttrVec ()) + : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, + std::move (loop_label), std::move (outer_attribs)), + condition (std::move (loop_condition)) + {} + + // Copy constructor with clone + WhileLoopExpr (WhileLoopExpr const &other) + : BaseLoopExpr (other), condition (other.condition->clone_expr ()) + {} + + // Overloaded assignment operator to clone + WhileLoopExpr &operator= (WhileLoopExpr const &other) + { + BaseLoopExpr::operator= (other); + condition = other.condition->clone_expr (); + // loop_block = other.loop_block->clone_block_expr(); + // loop_label = other.loop_label; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + WhileLoopExpr (WhileLoopExpr &&other) = default; + WhileLoopExpr &operator= (WhileLoopExpr &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_predicate_expr () { return condition; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + WhileLoopExpr *clone_expr_impl () const override + { + return new WhileLoopExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + WhileLoopExpr *clone_expr_with_block_impl () const override + { + return new WhileLoopExpr (*this); + } +}; + +// While let loop expression HIR node (predicate pattern loop) +class WhileLetLoopExpr : public BaseLoopExpr +{ + // MatchArmPatterns patterns; + std::vector > match_arm_patterns; // inlined + std::unique_ptr condition; + +public: + std::string as_string () const override; + + // Constructor with a loop label + WhileLetLoopExpr (Analysis::NodeMapping mappings, + std::vector > match_arm_patterns, + std::unique_ptr condition, + std::unique_ptr loop_block, Location locus, + LoopLabel loop_label, + AST::AttrVec outer_attribs = AST::AttrVec ()) + : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, + std::move (loop_label), std::move (outer_attribs)), + match_arm_patterns (std::move (match_arm_patterns)), + condition (std::move (condition)) + {} + + // Copy constructor with clone + WhileLetLoopExpr (WhileLetLoopExpr const &other) + : BaseLoopExpr (other), + /*match_arm_patterns(other.match_arm_patterns),*/ condition ( + other.condition->clone_expr ()) + { + match_arm_patterns.reserve (other.match_arm_patterns.size ()); + for (const auto &e : other.match_arm_patterns) + match_arm_patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to clone pointers + WhileLetLoopExpr &operator= (WhileLetLoopExpr const &other) + { + BaseLoopExpr::operator= (other); + // match_arm_patterns = other.match_arm_patterns; + condition = other.condition->clone_expr (); + // loop_block = other.loop_block->clone_block_expr(); + // loop_label = other.loop_label; + // outer_attrs = other.outer_attrs; + + match_arm_patterns.reserve (other.match_arm_patterns.size ()); + for (const auto &e : other.match_arm_patterns) + match_arm_patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + WhileLetLoopExpr (WhileLetLoopExpr &&other) = default; + WhileLetLoopExpr &operator= (WhileLetLoopExpr &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_cond () { return condition; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + WhileLetLoopExpr *clone_expr_impl () const override + { + return new WhileLetLoopExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + WhileLetLoopExpr *clone_expr_with_block_impl () const override + { + return new WhileLetLoopExpr (*this); + } +}; + +// For loop expression HIR node (iterator loop) +class ForLoopExpr : public BaseLoopExpr +{ + std::unique_ptr pattern; + std::unique_ptr iterator_expr; + +public: + std::string as_string () const override; + + // Constructor with loop label + ForLoopExpr (Analysis::NodeMapping mappings, + std::unique_ptr loop_pattern, + std::unique_ptr iterator_expr, + std::unique_ptr loop_body, Location locus, + LoopLabel loop_label, + AST::AttrVec outer_attribs = AST::AttrVec ()) + : BaseLoopExpr (std::move (mappings), std::move (loop_body), locus, + std::move (loop_label), std::move (outer_attribs)), + pattern (std::move (loop_pattern)), + iterator_expr (std::move (iterator_expr)) + {} + + // Copy constructor with clone + ForLoopExpr (ForLoopExpr const &other) + : BaseLoopExpr (other), pattern (other.pattern->clone_pattern ()), + iterator_expr (other.iterator_expr->clone_expr ()) + {} + + // Overloaded assignment operator to clone + ForLoopExpr &operator= (ForLoopExpr const &other) + { + BaseLoopExpr::operator= (other); + pattern = other.pattern->clone_pattern (); + iterator_expr = other.iterator_expr->clone_expr (); + /*loop_block = other.loop_block->clone_block_expr(); + loop_label = other.loop_label; + outer_attrs = other.outer_attrs;*/ + + return *this; + } + + // move constructors + ForLoopExpr (ForLoopExpr &&other) = default; + ForLoopExpr &operator= (ForLoopExpr &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_iterator_expr () { return iterator_expr; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ForLoopExpr *clone_expr_impl () const override + { + return new ForLoopExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ForLoopExpr *clone_expr_with_block_impl () const override + { + return new ForLoopExpr (*this); + } +}; + +// forward decl for IfExpr +class IfLetExpr; + +// Base if expression with no "else" or "if let" HIR node +class IfExpr : public ExprWithBlock +{ + std::unique_ptr condition; + std::unique_ptr if_block; + + Location locus; + +public: + std::string as_string () const override; + + IfExpr (Analysis::NodeMapping mappings, std::unique_ptr condition, + std::unique_ptr if_block, Location locus) + : ExprWithBlock (std::move (mappings), AST::AttrVec ()), + condition (std::move (condition)), if_block (std::move (if_block)), + locus (locus) + {} + // outer attributes are never allowed on IfExprs + + // Copy constructor with clone + IfExpr (IfExpr const &other) + : ExprWithBlock (other), condition (other.condition->clone_expr ()), + if_block (other.if_block->clone_block_expr ()), locus (other.locus) + {} + + // Overloaded assignment operator to clone expressions + IfExpr &operator= (IfExpr const &other) + { + ExprWithBlock::operator= (other); + condition = other.condition->clone_expr (); + if_block = other.if_block->clone_block_expr (); + locus = other.locus; + + return *this; + } + + // move constructors + IfExpr (IfExpr &&other) = default; + IfExpr &operator= (IfExpr &&other) = default; + + // Unique pointer custom clone function + std::unique_ptr clone_if_expr () const + { + return std::unique_ptr (clone_if_expr_impl ()); + } + + /* Note that multiple "else if"s are handled via nested HIRs rather than a + * vector of else ifs - i.e. not like a switch statement. TODO - is this a + * better approach? or does it not parse correctly and have downsides? */ + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + void vis_if_condition (HIRFullVisitor &vis) { condition->accept_vis (vis); } + void vis_if_block (HIRFullVisitor &vis) { if_block->accept_vis (vis); } + + Expr *get_if_condition () { return condition.get (); } + BlockExpr *get_if_block () { return if_block.get (); } + + ExprType get_expression_type () const final override { return ExprType::If; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExpr *clone_expr_impl () const override { return new IfExpr (*this); } + + // Base clone function but still concrete as concrete base class + virtual IfExpr *clone_if_expr_impl () const { return new IfExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExpr *clone_expr_with_block_impl () const override + { + return new IfExpr (*this); + } +}; + +// If expression with an ending "else" expression HIR node (trailing) +class IfExprConseqElse : public IfExpr +{ + std::unique_ptr else_block; + +public: + std::string as_string () const override; + + IfExprConseqElse (Analysis::NodeMapping mappings, + std::unique_ptr condition, + std::unique_ptr if_block, + std::unique_ptr else_block, Location locus) + : IfExpr (std::move (mappings), std::move (condition), std::move (if_block), + locus), + else_block (std::move (else_block)) + {} + // again, outer attributes not allowed + + // Copy constructor with clone + IfExprConseqElse (IfExprConseqElse const &other) + : IfExpr (other), else_block (other.else_block->clone_block_expr ()) + {} + + // Overloaded assignment operator with cloning + IfExprConseqElse &operator= (IfExprConseqElse const &other) + { + IfExpr::operator= (other); + // condition = other.condition->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + else_block = other.else_block->clone_block_expr (); + + return *this; + } + + // move constructors + IfExprConseqElse (IfExprConseqElse &&other) = default; + IfExprConseqElse &operator= (IfExprConseqElse &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + void vis_else_block (HIRFullVisitor &vis) { else_block->accept_vis (vis); } + + BlockExpr *get_else_block () { return else_block.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExprConseqElse *clone_expr_impl () const override + { + return new IfExprConseqElse (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExprConseqElse *clone_expr_with_block_impl () const override + { + return new IfExprConseqElse (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExprConseqElse *clone_if_expr_impl () const override + { + return new IfExprConseqElse (*this); + } +}; + +// If expression with an ending "else if" expression HIR node +class IfExprConseqIf : public IfExpr +{ + std::unique_ptr conseq_if_expr; + +public: + std::string as_string () const override; + + IfExprConseqIf (Analysis::NodeMapping mappings, + std::unique_ptr condition, + std::unique_ptr if_block, + std::unique_ptr conseq_if_expr, Location locus) + : IfExpr (std::move (mappings), std::move (condition), std::move (if_block), + locus), + conseq_if_expr (std::move (conseq_if_expr)) + {} + // outer attributes not allowed + + // Copy constructor with clone + IfExprConseqIf (IfExprConseqIf const &other) + : IfExpr (other), conseq_if_expr (other.conseq_if_expr->clone_if_expr ()) + {} + + // Overloaded assignment operator to use clone + IfExprConseqIf &operator= (IfExprConseqIf const &other) + { + IfExpr::operator= (other); + // condition = other.condition->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + conseq_if_expr = other.conseq_if_expr->clone_if_expr (); + + return *this; + } + + // move constructors + IfExprConseqIf (IfExprConseqIf &&other) = default; + IfExprConseqIf &operator= (IfExprConseqIf &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + void vis_conseq_if_expr (HIRFullVisitor &vis) + { + conseq_if_expr->accept_vis (vis); + } + + IfExpr *get_conseq_if_expr () { return conseq_if_expr.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExprConseqIf *clone_expr_impl () const override + { + return new IfExprConseqIf (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExprConseqIf *clone_expr_with_block_impl () const override + { + return new IfExprConseqIf (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExprConseqIf *clone_if_expr_impl () const override + { + return new IfExprConseqIf (*this); + } +}; + +// Basic "if let" expression HIR node with no else +class IfLetExpr : public ExprWithBlock +{ + // MatchArmPatterns patterns; + std::vector > match_arm_patterns; // inlined + std::unique_ptr value; + std::unique_ptr if_block; + + Location locus; + +public: + std::string as_string () const override; + + IfLetExpr (Analysis::NodeMapping mappings, + std::vector > match_arm_patterns, + std::unique_ptr value, std::unique_ptr if_block, + Location locus) + : ExprWithBlock (std::move (mappings), AST::AttrVec ()), + match_arm_patterns (std::move (match_arm_patterns)), + value (std::move (value)), if_block (std::move (if_block)), locus (locus) + {} + // outer attributes not allowed on if let exprs either + + // copy constructor with clone + IfLetExpr (IfLetExpr const &other) + : ExprWithBlock (other), + /*match_arm_patterns(other.match_arm_patterns),*/ value ( + other.value->clone_expr ()), + if_block (other.if_block->clone_block_expr ()), locus (other.locus) + { + match_arm_patterns.reserve (other.match_arm_patterns.size ()); + for (const auto &e : other.match_arm_patterns) + match_arm_patterns.push_back (e->clone_pattern ()); + } + + // overload assignment operator to clone + IfLetExpr &operator= (IfLetExpr const &other) + { + ExprWithBlock::operator= (other); + // match_arm_patterns = other.match_arm_patterns; + value = other.value->clone_expr (); + if_block = other.if_block->clone_block_expr (); + locus = other.locus; + + match_arm_patterns.reserve (other.match_arm_patterns.size ()); + for (const auto &e : other.match_arm_patterns) + match_arm_patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + IfLetExpr (IfLetExpr &&other) = default; + IfLetExpr &operator= (IfLetExpr &&other) = default; + + // Unique pointer custom clone function + std::unique_ptr clone_if_let_expr () const + { + return std::unique_ptr (clone_if_let_expr_impl ()); + } + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_scrutinee_expr () + { + rust_assert (value != nullptr); + return value; + } + + std::vector > &get_patterns () + { + return match_arm_patterns; + } + + BlockExpr *get_if_block () { return if_block.get (); } + + ExprType get_expression_type () const final override + { + return ExprType::IfLet; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExpr *clone_expr_impl () const override { return new IfLetExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExpr *clone_expr_with_block_impl () const override + { + return new IfLetExpr (*this); + } + + // Base clone function but still concrete as concrete base class + virtual IfLetExpr *clone_if_let_expr_impl () const + { + return new IfLetExpr (*this); + } +}; + +// If expression with an ending "else if let" expression HIR node +class IfExprConseqIfLet : public IfExpr +{ + std::unique_ptr if_let_expr; + +public: + std::string as_string () const override; + + IfExprConseqIfLet (Analysis::NodeMapping mappings, + std::unique_ptr condition, + std::unique_ptr if_block, + std::unique_ptr conseq_if_let_expr, + Location locus) + : IfExpr (std::move (mappings), std::move (condition), std::move (if_block), + locus), + if_let_expr (std::move (conseq_if_let_expr)) + {} + // outer attributes not allowed + + // Copy constructor with clone + IfExprConseqIfLet (IfExprConseqIfLet const &other) + : IfExpr (other), if_let_expr (other.if_let_expr->clone_if_let_expr ()) + {} + + // Overloaded assignment operator to use clone + IfExprConseqIfLet &operator= (IfExprConseqIfLet const &other) + { + IfExpr::operator= (other); + // condition = other.condition->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + if_let_expr = other.if_let_expr->clone_if_let_expr (); + + return *this; + } + + // move constructors + IfExprConseqIfLet (IfExprConseqIfLet &&other) = default; + IfExprConseqIfLet &operator= (IfExprConseqIfLet &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExprConseqIfLet *clone_expr_impl () const override + { + return new IfExprConseqIfLet (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExprConseqIfLet *clone_expr_with_block_impl () const override + { + return new IfExprConseqIfLet (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExprConseqIfLet *clone_if_expr_impl () const override + { + return new IfExprConseqIfLet (*this); + } +}; + +/* HIR node representing "if let" expression with an "else" expression at the + * end */ +class IfLetExprConseqElse : public IfLetExpr +{ + std::unique_ptr else_block; + +public: + std::string as_string () const override; + + IfLetExprConseqElse ( + Analysis::NodeMapping mappings, + std::vector > match_arm_patterns, + std::unique_ptr value, std::unique_ptr if_block, + std::unique_ptr else_block, Location locus) + : IfLetExpr (std::move (mappings), std::move (match_arm_patterns), + std::move (value), std::move (if_block), locus), + else_block (std::move (else_block)) + {} + // outer attributes not allowed + + // copy constructor with clone + IfLetExprConseqElse (IfLetExprConseqElse const &other) + : IfLetExpr (other), else_block (other.else_block->clone_block_expr ()) + {} + + // overload assignment operator to clone + IfLetExprConseqElse &operator= (IfLetExprConseqElse const &other) + { + IfLetExpr::operator= (other); + // match_arm_patterns = other.match_arm_patterns; + // value = other.value->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + else_block = other.else_block->clone_block_expr (); + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + IfLetExprConseqElse (IfLetExprConseqElse &&other) = default; + IfLetExprConseqElse &operator= (IfLetExprConseqElse &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExprConseqElse *clone_expr_impl () const override + { + return new IfLetExprConseqElse (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExprConseqElse *clone_expr_with_block_impl () const override + { + return new IfLetExprConseqElse (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExprConseqElse *clone_if_let_expr_impl () const override + { + return new IfLetExprConseqElse (*this); + } +}; + +/* HIR node representing "if let" expression with an "else if" expression at the + * end */ +class IfLetExprConseqIf : public IfLetExpr +{ + std::unique_ptr if_expr; + +public: + std::string as_string () const override; + + IfLetExprConseqIf (Analysis::NodeMapping mappings, + std::vector > match_arm_patterns, + std::unique_ptr value, + std::unique_ptr if_block, + std::unique_ptr if_expr, Location locus) + : IfLetExpr (std::move (mappings), std::move (match_arm_patterns), + std::move (value), std::move (if_block), locus), + if_expr (std::move (if_expr)) + {} + // again, outer attributes not allowed + + // copy constructor with clone + IfLetExprConseqIf (IfLetExprConseqIf const &other) + : IfLetExpr (other), if_expr (other.if_expr->clone_if_expr ()) + {} + + // overload assignment operator to clone + IfLetExprConseqIf &operator= (IfLetExprConseqIf const &other) + { + IfLetExpr::operator= (other); + // match_arm_patterns = other.match_arm_patterns; + // value = other.value->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + if_expr = other.if_expr->clone_if_expr (); + + return *this; + } + + // move constructors + IfLetExprConseqIf (IfLetExprConseqIf &&other) = default; + IfLetExprConseqIf &operator= (IfLetExprConseqIf &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExprConseqIf *clone_expr_impl () const override + { + return new IfLetExprConseqIf (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExprConseqIf *clone_expr_with_block_impl () const override + { + return new IfLetExprConseqIf (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExprConseqIf *clone_if_let_expr_impl () const override + { + return new IfLetExprConseqIf (*this); + } +}; + +/* HIR node representing "if let" expression with an "else if let" expression at + * the end */ +class IfLetExprConseqIfLet : public IfLetExpr +{ + std::unique_ptr if_let_expr; + +public: + std::string as_string () const override; + + IfLetExprConseqIfLet ( + Analysis::NodeMapping mappings, + std::vector > match_arm_patterns, + std::unique_ptr value, std::unique_ptr if_block, + std::unique_ptr if_let_expr, Location locus) + : IfLetExpr (std::move (mappings), std::move (match_arm_patterns), + std::move (value), std::move (if_block), locus), + if_let_expr (std::move (if_let_expr)) + {} + // outer attributes not allowed + + // copy constructor with clone + IfLetExprConseqIfLet (IfLetExprConseqIfLet const &other) + : IfLetExpr (other), if_let_expr (other.if_let_expr->clone_if_let_expr ()) + {} + + // overload assignment operator to clone + IfLetExprConseqIfLet &operator= (IfLetExprConseqIfLet const &other) + { + IfLetExpr::operator= (other); + // match_arm_patterns = other.match_arm_patterns; + // value = other.value->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + if_let_expr = other.if_let_expr->clone_if_let_expr (); + + return *this; + } + + // move constructors + IfLetExprConseqIfLet (IfLetExprConseqIfLet &&other) = default; + IfLetExprConseqIfLet &operator= (IfLetExprConseqIfLet &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExprConseqIfLet *clone_expr_impl () const override + { + return new IfLetExprConseqIfLet (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExprConseqIfLet *clone_expr_with_block_impl () const override + { + return new IfLetExprConseqIfLet (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExprConseqIfLet *clone_if_let_expr_impl () const override + { + return new IfLetExprConseqIfLet (*this); + } +}; + +// Match arm expression +struct MatchArm +{ +private: + AST::AttrVec outer_attrs; + std::vector > match_arm_patterns; + std::unique_ptr guard_expr; + Location locus; + +public: + // Returns whether the MatchArm has a match arm guard expression + bool has_match_arm_guard () const { return guard_expr != nullptr; } + + // Constructor for match arm with a guard expression + MatchArm (std::vector > match_arm_patterns, + Location locus, std::unique_ptr guard_expr = nullptr, + AST::AttrVec outer_attrs = AST::AttrVec ()) + : outer_attrs (std::move (outer_attrs)), + match_arm_patterns (std::move (match_arm_patterns)), + guard_expr (std::move (guard_expr)), locus (locus) + {} + + // Copy constructor with clone + MatchArm (MatchArm const &other) : outer_attrs (other.outer_attrs) + { + // guard to protect from null pointer dereference + if (other.guard_expr != nullptr) + guard_expr = other.guard_expr->clone_expr (); + + match_arm_patterns.reserve (other.match_arm_patterns.size ()); + for (const auto &e : other.match_arm_patterns) + match_arm_patterns.push_back (e->clone_pattern ()); + + locus = other.locus; + } + + ~MatchArm () = default; + + // Overload assignment operator to clone + MatchArm &operator= (MatchArm const &other) + { + outer_attrs = other.outer_attrs; + + if (other.guard_expr != nullptr) + guard_expr = other.guard_expr->clone_expr (); + + match_arm_patterns.clear (); + match_arm_patterns.reserve (other.match_arm_patterns.size ()); + for (const auto &e : other.match_arm_patterns) + match_arm_patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + MatchArm (MatchArm &&other) = default; + MatchArm &operator= (MatchArm &&other) = default; + + // Returns whether match arm is in an error state. + bool is_error () const { return match_arm_patterns.empty (); } + + // Creates a match arm in an error state. + static MatchArm create_error () + { + Location locus = Location (); + return MatchArm (std::vector > (), locus); + } + + std::string as_string () const; + + std::vector > &get_patterns () + { + return match_arm_patterns; + } + + std::unique_ptr &get_guard_expr () + { + rust_assert (has_match_arm_guard ()); + return guard_expr; + } + + Location get_locus () const { return locus; } +}; + +/* A "match case" - a correlated match arm and resulting expression. Not + * abstract. */ +struct MatchCase +{ +private: + Analysis::NodeMapping mappings; + MatchArm arm; + std::unique_ptr expr; + +public: + MatchCase (Analysis::NodeMapping mappings, MatchArm arm, + std::unique_ptr expr) + : mappings (mappings), arm (std::move (arm)), expr (std::move (expr)) + {} + + MatchCase (const MatchCase &other) + : mappings (other.mappings), arm (other.arm), + expr (other.expr->clone_expr ()) + {} + + MatchCase &operator= (const MatchCase &other) + { + mappings = other.mappings; + arm = other.arm; + expr = other.expr->clone_expr (); + + return *this; + } + + MatchCase (MatchCase &&other) = default; + MatchCase &operator= (MatchCase &&other) = default; + + ~MatchCase () = default; + + std::string as_string () const; + + Analysis::NodeMapping get_mappings () const { return mappings; } + + MatchArm &get_arm () { return arm; } + std::unique_ptr &get_expr () { return expr; } +}; + +// Match expression HIR node +class MatchExpr : public ExprWithBlock +{ + std::unique_ptr branch_value; + AST::AttrVec inner_attrs; + std::vector match_arms; + Location locus; + +public: + std::string as_string () const override; + + bool has_match_arms () const { return !match_arms.empty (); } + + MatchExpr (Analysis::NodeMapping mappings, std::unique_ptr branch_value, + std::vector match_arms, AST::AttrVec inner_attrs, + AST::AttrVec outer_attrs, Location locus) + : ExprWithBlock (std::move (mappings), std::move (outer_attrs)), + branch_value (std::move (branch_value)), + inner_attrs (std::move (inner_attrs)), + match_arms (std::move (match_arms)), locus (locus) + {} + + // Copy constructor requires clone due to unique_ptr + MatchExpr (MatchExpr const &other) + : ExprWithBlock (other), branch_value (other.branch_value->clone_expr ()), + inner_attrs (other.inner_attrs), match_arms (other.match_arms), + locus (other.locus) + { + /*match_arms.reserve (other.match_arms.size ()); + for (const auto &e : other.match_arms) + match_arms.push_back (e->clone_match_case ());*/ + } + + // Overloaded assignment operator to clone due to unique_ptr + MatchExpr &operator= (MatchExpr const &other) + { + ExprWithBlock::operator= (other); + branch_value = other.branch_value->clone_expr (); + inner_attrs = other.inner_attrs; + match_arms = other.match_arms; + // outer_attrs = other.outer_attrs; + locus = other.locus; + + /*match_arms.reserve (other.match_arms.size ()); + for (const auto &e : other.match_arms) + match_arms.push_back (e->clone_match_case ());*/ + + return *this; + } + + // move constructors + MatchExpr (MatchExpr &&other) = default; + MatchExpr &operator= (MatchExpr &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::unique_ptr &get_scrutinee_expr () + { + rust_assert (branch_value != nullptr); + return branch_value; + } + + const std::vector &get_match_cases () const { return match_arms; } + std::vector &get_match_cases () { return match_arms; } + + ExprType get_expression_type () const final override + { + return ExprType::Match; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + MatchExpr *clone_expr_impl () const override { return new MatchExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + MatchExpr *clone_expr_with_block_impl () const override + { + return new MatchExpr (*this); + } +}; + +// Await expression HIR node (pseudo-member variable access) +class AwaitExpr : public ExprWithoutBlock +{ + std::unique_ptr awaited_expr; + Location locus; + +public: + // TODO: ensure outer attributes are actually allowed + AwaitExpr (Analysis::NodeMapping mappings, std::unique_ptr awaited_expr, + AST::AttrVec outer_attrs, Location locus) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)), + awaited_expr (std::move (awaited_expr)), locus (locus) + {} + + // copy constructor with clone + AwaitExpr (AwaitExpr const &other) + : ExprWithoutBlock (other), + awaited_expr (other.awaited_expr->clone_expr ()), locus (other.locus) + {} + + // overloaded assignment operator with clone + AwaitExpr &operator= (AwaitExpr const &other) + { + ExprWithoutBlock::operator= (other); + awaited_expr = other.awaited_expr->clone_expr (); + locus = other.locus; + + return *this; + } + + // move constructors + AwaitExpr (AwaitExpr &&other) = default; + AwaitExpr &operator= (AwaitExpr &&other) = default; + + std::string as_string () const override; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + ExprType get_expression_type () const final override + { + return ExprType::Await; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + AwaitExpr *clone_expr_without_block_impl () const override + { + return new AwaitExpr (*this); + } +}; + +// Async block expression HIR node (block expr that evaluates to a future) +class AsyncBlockExpr : public ExprWithBlock +{ + bool has_move; + std::unique_ptr block_expr; + Location locus; + +public: + AsyncBlockExpr (Analysis::NodeMapping mappings, + std::unique_ptr block_expr, bool has_move, + AST::AttrVec outer_attrs, Location locus) + : ExprWithBlock (std::move (mappings), std::move (outer_attrs)), + has_move (has_move), block_expr (std::move (block_expr)), locus (locus) + {} + + // copy constructor with clone + AsyncBlockExpr (AsyncBlockExpr const &other) + : ExprWithBlock (other), has_move (other.has_move), + block_expr (other.block_expr->clone_block_expr ()), locus (other.locus) + {} + + // overloaded assignment operator to clone + AsyncBlockExpr &operator= (AsyncBlockExpr const &other) + { + ExprWithBlock::operator= (other); + has_move = other.has_move; + block_expr = other.block_expr->clone_block_expr (); + locus = other.locus; + + return *this; + } + + // move constructors + AsyncBlockExpr (AsyncBlockExpr &&other) = default; + AsyncBlockExpr &operator= (AsyncBlockExpr &&other) = default; + + std::string as_string () const override; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + ExprType get_expression_type () const final override + { + return ExprType::AsyncBlock; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + AsyncBlockExpr *clone_expr_with_block_impl () const override + { + return new AsyncBlockExpr (*this); + } +}; + +// this is a utility helper class for type-checking and code-generation +class OperatorExprMeta +{ +public: + OperatorExprMeta (HIR::CompoundAssignmentExpr &expr) + : node_mappings (expr.get_mappings ()), + lvalue_mappings (expr.get_expr ()->get_mappings ()), + locus (expr.get_locus ()) + {} + + OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr) + : node_mappings (expr.get_mappings ()), + lvalue_mappings (expr.get_expr ()->get_mappings ()), + locus (expr.get_locus ()) + {} + + OperatorExprMeta (HIR::NegationExpr &expr) + : node_mappings (expr.get_mappings ()), + lvalue_mappings (expr.get_expr ()->get_mappings ()), + locus (expr.get_locus ()) + {} + + OperatorExprMeta (HIR::DereferenceExpr &expr) + : node_mappings (expr.get_mappings ()), + lvalue_mappings (expr.get_expr ()->get_mappings ()), + locus (expr.get_locus ()) + {} + + OperatorExprMeta (HIR::ArrayIndexExpr &expr) + : node_mappings (expr.get_mappings ()), + lvalue_mappings (expr.get_array_expr ()->get_mappings ()), + locus (expr.get_locus ()) + {} + + const Analysis::NodeMapping &get_mappings () const { return node_mappings; } + + const Analysis::NodeMapping &get_lvalue_mappings () const + { + return lvalue_mappings; + } + + Location get_locus () const { return locus; } + +private: + const Analysis::NodeMapping node_mappings; + const Analysis::NodeMapping lvalue_mappings; + Location locus; +}; + +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h new file mode 100644 index 00000000000..394b04f6c7f --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -0,0 +1,3207 @@ +// 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_HIR_ITEM_H +#define RUST_HIR_ITEM_H + +#include "rust-abi.h" +#include "rust-ast-full-decls.h" +#include "rust-common.h" +#include "rust-hir.h" +#include "rust-hir-path.h" + +namespace Rust { +namespace HIR { +// forward decls +class BlockExpr; +class TypePath; + +// A type generic parameter (as opposed to a lifetime generic parameter) +class TypeParam : public GenericParam +{ + // bool has_outer_attribute; + // std::unique_ptr outer_attr; + AST::Attribute outer_attr; + + Identifier type_representation; + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + std::vector> + type_param_bounds; // inlined form + + // bool has_type; + std::unique_ptr type; + + Location locus; + +public: + // Returns whether the type of the type param has been specified. + bool has_type () const { return type != nullptr; } + + // Returns whether the type param has type param bounds. + bool has_type_param_bounds () const { return !type_param_bounds.empty (); } + + // Returns whether the type param has an outer attribute. + bool has_outer_attribute () const { return !outer_attr.is_empty (); } + + TypeParam (Analysis::NodeMapping mappings, Identifier type_representation, + Location locus = Location (), + std::vector> type_param_bounds + = std::vector> (), + std::unique_ptr type = nullptr, + AST::Attribute outer_attr = AST::Attribute::create_empty ()) + : GenericParam (mappings), outer_attr (std::move (outer_attr)), + type_representation (std::move (type_representation)), + type_param_bounds (std::move (type_param_bounds)), + type (std::move (type)), locus (locus) + {} + + // Copy constructor uses clone + TypeParam (TypeParam const &other) + : GenericParam (other.mappings), outer_attr (other.outer_attr), + type_representation (other.type_representation), locus (other.locus) + { + // guard to prevent null pointer dereference + if (other.type != nullptr) + type = other.type->clone_type (); + + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + } + + // Overloaded assignment operator to clone + TypeParam &operator= (TypeParam const &other) + { + type_representation = other.type_representation; + outer_attr = other.outer_attr; + locus = other.locus; + mappings = other.mappings; + + // guard to prevent null pointer dereference + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + + return *this; + } + // move constructors + TypeParam (TypeParam &&other) = default; + TypeParam &operator= (TypeParam &&other) = default; + + std::string as_string () const override; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + + Identifier get_type_representation () const { return type_representation; } + + std::unique_ptr &get_type () + { + rust_assert (type != nullptr); + return type; + } + + Analysis::NodeMapping get_type_mappings () const + { + rust_assert (type != nullptr); + return type->get_mappings (); + } + + std::vector> &get_type_param_bounds () + { + return type_param_bounds; + } + +protected: + // Clone function implementation as (not pure) virtual method + TypeParam *clone_generic_param_impl () const override + { + return new TypeParam (*this); + } +}; + +/* "where" clause item base. Abstract - use LifetimeWhereClauseItem, + * TypeBoundWhereClauseItem */ +class WhereClauseItem +{ +public: + enum ItemType + { + LIFETIME, + TYPE_BOUND, + }; + + virtual ~WhereClauseItem () {} + + // Unique pointer custom clone function + std::unique_ptr clone_where_clause_item () const + { + return std::unique_ptr (clone_where_clause_item_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (HIRFullVisitor &vis) = 0; + + virtual Analysis::NodeMapping get_mappings () const = 0; + + virtual ItemType get_item_type () const = 0; + +protected: + // Clone function implementation as pure virtual method + virtual WhereClauseItem *clone_where_clause_item_impl () const = 0; +}; + +// A lifetime where clause item +class LifetimeWhereClauseItem : public WhereClauseItem +{ + Lifetime lifetime; + std::vector lifetime_bounds; + Location locus; + Analysis::NodeMapping mappings; + +public: + LifetimeWhereClauseItem (Analysis::NodeMapping mappings, Lifetime lifetime, + std::vector lifetime_bounds, + Location locus) + : lifetime (std::move (lifetime)), + lifetime_bounds (std::move (lifetime_bounds)), locus (locus), + mappings (std::move (mappings)) + {} + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + Lifetime &get_lifetime () { return lifetime; } + + std::vector &get_lifetime_bounds () { return lifetime_bounds; } + + Analysis::NodeMapping get_mappings () const override final + { + return mappings; + }; + + ItemType get_item_type () const override final + { + return WhereClauseItem::ItemType::LIFETIME; + } + +protected: + // Clone function implementation as (not pure) virtual method + LifetimeWhereClauseItem *clone_where_clause_item_impl () const override + { + return new LifetimeWhereClauseItem (*this); + } +}; + +// A type bound where clause item +class TypeBoundWhereClauseItem : public WhereClauseItem +{ + std::vector for_lifetimes; + std::unique_ptr bound_type; + std::vector> type_param_bounds; + Analysis::NodeMapping mappings; + Location locus; + +public: + // Returns whether the item has ForLifetimes + bool has_for_lifetimes () const { return !for_lifetimes.empty (); } + + // Returns whether the item has type param bounds + bool has_type_param_bounds () const { return !type_param_bounds.empty (); } + + TypeBoundWhereClauseItem ( + Analysis::NodeMapping mappings, std::vector for_lifetimes, + std::unique_ptr bound_type, + std::vector> type_param_bounds, + Location locus) + : for_lifetimes (std::move (for_lifetimes)), + bound_type (std::move (bound_type)), + type_param_bounds (std::move (type_param_bounds)), + mappings (std::move (mappings)), locus (locus) + {} + + // Copy constructor requires clone + TypeBoundWhereClauseItem (TypeBoundWhereClauseItem const &other) + : for_lifetimes (other.for_lifetimes), + bound_type (other.bound_type->clone_type ()), mappings (other.mappings) + { + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + } + + // Overload assignment operator to clone + TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem const &other) + { + mappings = other.mappings; + for_lifetimes = other.for_lifetimes; + bound_type = other.bound_type->clone_type (); + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + + return *this; + } + + // move constructors + TypeBoundWhereClauseItem (TypeBoundWhereClauseItem &&other) = default; + TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem &&other) + = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + std::vector &get_for_lifetimes () { return for_lifetimes; } + + std::unique_ptr &get_bound_type () { return bound_type; } + + std::vector> &get_type_param_bounds () + { + return type_param_bounds; + } + + Analysis::NodeMapping get_mappings () const override final + { + return mappings; + }; + + ItemType get_item_type () const override final + { + return WhereClauseItem::ItemType::TYPE_BOUND; + } + +protected: + // Clone function implementation as (not pure) virtual method + TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override + { + return new TypeBoundWhereClauseItem (*this); + } +}; + +// A where clause +struct WhereClause +{ +private: + std::vector> where_clause_items; + + // should this store location info? + +public: + WhereClause (std::vector> where_clause_items) + : where_clause_items (std::move (where_clause_items)) + {} + + // copy constructor with vector clone + WhereClause (WhereClause const &other) + { + where_clause_items.reserve (other.where_clause_items.size ()); + for (const auto &e : other.where_clause_items) + where_clause_items.push_back (e->clone_where_clause_item ()); + } + + // overloaded assignment operator with vector clone + WhereClause &operator= (WhereClause const &other) + { + where_clause_items.reserve (other.where_clause_items.size ()); + for (const auto &e : other.where_clause_items) + where_clause_items.push_back (e->clone_where_clause_item ()); + + return *this; + } + + // move constructors + WhereClause (WhereClause &&other) = default; + WhereClause &operator= (WhereClause &&other) = default; + + // Creates a WhereClause with no items. + static WhereClause create_empty () + { + return WhereClause (std::vector> ()); + } + + // Returns whether the WhereClause has no items. + bool is_empty () const { return where_clause_items.empty (); } + + std::string as_string () const; + + std::vector> &get_items () + { + return where_clause_items; + } + const std::vector> &get_items () const + { + return where_clause_items; + } +}; + +// A self parameter in a method +struct SelfParam +{ +public: + enum ImplicitSelfKind + { + IMM, // self + MUT, // mut self + IMM_REF, // &self + MUT_REF, // &mut self + NONE + }; + +private: + ImplicitSelfKind self_kind; + Lifetime lifetime; + std::unique_ptr type; + Location locus; + Analysis::NodeMapping mappings; + + SelfParam (Analysis::NodeMapping mappings, ImplicitSelfKind self_kind, + Lifetime lifetime, Type *type) + : self_kind (self_kind), lifetime (std::move (lifetime)), type (type), + mappings (mappings) + {} + +public: + // Type-based self parameter (not ref, no lifetime) + SelfParam (Analysis::NodeMapping mappings, std::unique_ptr type, + bool is_mut, Location locus) + : self_kind (is_mut ? ImplicitSelfKind::MUT : ImplicitSelfKind::IMM), + lifetime ( + Lifetime (mappings, AST::Lifetime::LifetimeType::NAMED, "", locus)), + type (std::move (type)), locus (locus), mappings (mappings) + {} + + // Lifetime-based self parameter (is ref, no type) + SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime, bool is_mut, + Location locus) + : self_kind (is_mut ? ImplicitSelfKind::MUT_REF + : ImplicitSelfKind::IMM_REF), + lifetime (std::move (lifetime)), locus (locus), mappings (mappings) + {} + + // Copy constructor requires clone + SelfParam (SelfParam const &other) + : self_kind (other.self_kind), lifetime (other.lifetime), + locus (other.locus), mappings (other.mappings) + { + if (other.type != nullptr) + type = other.type->clone_type (); + } + + // Overload assignment operator to use clone + SelfParam &operator= (SelfParam const &other) + { + if (other.type != nullptr) + type = other.type->clone_type (); + + self_kind = other.self_kind; + lifetime = other.lifetime; + locus = other.locus; + mappings = other.mappings; + + return *this; + } + + // move constructors + SelfParam (SelfParam &&other) = default; + SelfParam &operator= (SelfParam &&other) = default; + + static SelfParam error () + { + return SelfParam (Analysis::NodeMapping::get_error (), + ImplicitSelfKind::NONE, Lifetime::error (), nullptr); + } + + // Returns whether the self-param has a type field. + bool has_type () const { return type != nullptr; } + + // Returns whether the self-param has a valid lifetime. + bool has_lifetime () const { return !lifetime.is_error (); } + + // Returns whether the self-param is in an error state. + bool is_error () const { return self_kind == ImplicitSelfKind::NONE; } + + std::string as_string () const; + + Location get_locus () const { return locus; } + + ImplicitSelfKind get_self_kind () const { return self_kind; } + + std::unique_ptr &get_type () + { + rust_assert (has_type ()); + return type; + } + + Analysis::NodeMapping get_mappings () { return mappings; } + + Mutability get_mut () const + { + return (self_kind == ImplicitSelfKind::MUT + || self_kind == ImplicitSelfKind::MUT_REF) + ? Mutability::Mut + : Mutability::Imm; + } + + bool is_mut () const + { + return self_kind == ImplicitSelfKind::MUT + || self_kind == ImplicitSelfKind::MUT_REF; + } + + bool is_ref () const + { + return self_kind == ImplicitSelfKind::IMM_REF + || self_kind == ImplicitSelfKind::MUT_REF; + } +}; + +// Qualifiers for function, i.e. const, unsafe, extern etc. +struct FunctionQualifiers +{ +private: + AsyncConstStatus const_status; + Unsafety unsafety; + bool has_extern; + ABI abi; + +public: + FunctionQualifiers (AsyncConstStatus const_status, Unsafety unsafety, + bool has_extern, ABI abi) + : const_status (const_status), unsafety (unsafety), has_extern (has_extern), + abi (abi) + {} + + std::string as_string () const; + + AsyncConstStatus get_status () const { return const_status; } + + bool is_const () const { return const_status == AsyncConstStatus::CONST_FN; } + bool is_unsafe () const { return unsafety == Unsafety::Unsafe; } + + ABI get_abi () const { return abi; } +}; + +// A function parameter +struct FunctionParam +{ + std::unique_ptr param_name; + std::unique_ptr type; + Location locus; + Analysis::NodeMapping mappings; + +public: + FunctionParam (Analysis::NodeMapping mappings, + std::unique_ptr param_name, + std::unique_ptr param_type, Location locus) + : param_name (std::move (param_name)), type (std::move (param_type)), + locus (locus), mappings (mappings) + {} + + // Copy constructor uses clone + FunctionParam (FunctionParam const &other) + : param_name (other.param_name->clone_pattern ()), + type (other.type->clone_type ()), locus (other.locus), + mappings (other.mappings) + {} + + // Overload assignment operator to use clone + FunctionParam &operator= (FunctionParam const &other) + { + param_name = other.param_name->clone_pattern (); + type = other.type->clone_type (); + locus = other.locus; + mappings = other.mappings; + + return *this; + } + + // move constructors + FunctionParam (FunctionParam &&other) = default; + FunctionParam &operator= (FunctionParam &&other) = default; + + std::string as_string () const; + + Location get_locus () const { return locus; } + + Pattern *get_param_name () { return param_name.get (); } + + Type *get_type () { return type.get (); } + + const Analysis::NodeMapping &get_mappings () const { return mappings; } +}; + +// Visibility of an item +struct Visibility +{ +public: + enum VisType + { + PRIVATE, + PUBLIC, + RESTRICTED, + ERROR, + }; + +private: + VisType vis_type; + HIR::SimplePath path; + + // should this store location info? + +public: + Visibility (VisType vis_type, + HIR::SimplePath path = HIR::SimplePath::create_empty ()) + : vis_type (vis_type), path (std::move (path)) + {} + + // Returns whether visibility is in an error state. + bool is_error () const { return vis_type == ERROR; } + + // Does the current visibility refer to a simple `pub ` entirely public + bool is_public () const { return vis_type == PUBLIC; } + + // Is the current visibility public restricted to a certain path + bool is_restricted () const { return vis_type == RESTRICTED; } + + // Creates an error visibility. + static Visibility create_error () + { + return Visibility (ERROR, HIR::SimplePath::create_empty ()); + } + + VisType get_vis_type () const { return vis_type; } + + const HIR::SimplePath &get_path () const + { + rust_assert (!is_error ()); + return path; + } + + std::string as_string () const; +}; + +// Item that supports visibility - abstract base class +class VisItem : public Item +{ + Visibility visibility; + +protected: + // Visibility constructor + VisItem (Analysis::NodeMapping mappings, Visibility visibility, + AST::AttrVec outer_attrs = AST::AttrVec ()) + : Item (std::move (mappings), std::move (outer_attrs)), + visibility (std::move (visibility)) + {} + + // Visibility copy constructor + VisItem (VisItem const &other) : Item (other), visibility (other.visibility) + {} + + // Overload assignment operator to clone + VisItem &operator= (VisItem const &other) + { + Item::operator= (other); + visibility = other.visibility; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + VisItem (VisItem &&other) = default; + VisItem &operator= (VisItem &&other) = default; + +public: + using HIR::Stmt::accept_vis; + + BaseKind get_hir_kind () override final { return VIS_ITEM; } + + /* Does the item have some kind of public visibility (non-default + * visibility)? */ + bool has_visibility () const { return !visibility.is_error (); } + + virtual void accept_vis (HIRVisItemVisitor &vis) = 0; + + Visibility &get_visibility () { return visibility; } + const Visibility &get_visibility () const { return visibility; } + + std::string as_string () const override; +}; + +// Rust module item - abstract base class +class Module : public VisItem +{ + Identifier module_name; + Location locus; + // bool has_inner_attrs; + AST::AttrVec inner_attrs; + // bool has_items; + std::vector> items; + +public: + std::string as_string () const override; + + // Returns whether the module has items in its body. + bool has_items () const { return !items.empty (); } + + // Returns whether the module has any inner attributes. + bool has_inner_attrs () const { return !inner_attrs.empty (); } + + // Full constructor + Module (Analysis::NodeMapping mappings, Identifier module_name, + Location locus, std::vector> items, + Visibility visibility = Visibility::create_error (), + AST::AttrVec inner_attrs = AST::AttrVec (), + AST::AttrVec outer_attrs = AST::AttrVec ()) + : VisItem (std::move (mappings), std::move (visibility), + std::move (outer_attrs)), + module_name (module_name), locus (locus), + inner_attrs (std::move (inner_attrs)), items (std::move (items)) + {} + + // Copy constructor with vector clone + Module (Module const &other) + : VisItem (other), inner_attrs (other.inner_attrs) + { + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_item ()); + } + + // Overloaded assignment operator with vector clone + Module &operator= (Module const &other) + { + VisItem::operator= (other); + inner_attrs = other.inner_attrs; + + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_item ()); + + return *this; + } + + // move constructors + Module (Module &&other) = default; + Module &operator= (Module &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + std::vector> &get_items () { return items; }; + + /* Override that runs the function recursively on all items contained within + * the module. */ + void add_crate_name (std::vector &names) const override; + + Location get_locus () const override final { return locus; } + + ItemKind get_item_kind () const override { return ItemKind::Module; } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + Module *clone_item_impl () const override { return new Module (*this); } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual Module* clone_statement_impl() const override { + return new Module(*this); + }*/ +}; + +// Rust extern crate declaration HIR node +class ExternCrate : public VisItem +{ + // this is either an identifier or "self", with self parsed to string + std::string referenced_crate; + // bool has_as_clause; + // AsClause as_clause; + // this is either an identifier or "_", with _ parsed to string + std::string as_clause_name; + + Location locus; + + /* e.g. + "extern crate foo as _" + "extern crate foo" + "extern crate std as cool_std" */ +public: + std::string as_string () const override; + + // Returns whether extern crate declaration has an as clause. + bool has_as_clause () const { return !as_clause_name.empty (); } + + /* Returns whether extern crate declaration references the current crate + * (i.e. self). */ + bool references_self () const { return referenced_crate == "self"; } + + // Constructor + ExternCrate (Analysis::NodeMapping mappings, std::string referenced_crate, + Visibility visibility, AST::AttrVec outer_attrs, Location locus, + std::string as_clause_name = std::string ()) + : VisItem (std::move (mappings), std::move (visibility), + std::move (outer_attrs)), + referenced_crate (std::move (referenced_crate)), + as_clause_name (std::move (as_clause_name)), locus (locus) + {} + + Location get_locus () const override final { return locus; } + + ItemKind get_item_kind () const override { return ItemKind::ExternCrate; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + // Override that adds extern crate name in decl to passed list of names. + void add_crate_name (std::vector &names) const override + { + names.push_back (referenced_crate); + } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + ExternCrate *clone_item_impl () const override + { + return new ExternCrate (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual ExternCrate* clone_statement_impl() const override { + return new ExternCrate(*this); + }*/ +}; + +// The path-ish thing referred to in a use declaration - abstract base class +class UseTree +{ + Location locus; + +public: + virtual ~UseTree () {} + + // Unique pointer custom clone function + std::unique_ptr clone_use_tree () const + { + return std::unique_ptr (clone_use_tree_impl ()); + } + + virtual std::string as_string () const = 0; + + Location get_locus () const { return locus; } + + virtual void accept_vis (HIRFullVisitor &vis) = 0; + +protected: + // Clone function implementation as pure virtual method + virtual UseTree *clone_use_tree_impl () const = 0; + + UseTree (Location locus) : locus (locus) {} +}; + +// Use tree with a glob (wildcard) operator +class UseTreeGlob : public UseTree +{ +public: + enum PathType + { + NO_PATH, + GLOBAL, + PATH_PREFIXED + }; + +private: + PathType glob_type; + AST::SimplePath path; + +public: + UseTreeGlob (PathType glob_type, AST::SimplePath path, Location locus) + : UseTree (locus), glob_type (glob_type), path (std::move (path)) + { + if (this->glob_type != PATH_PREFIXED) + { + // compiler implementation error if there is a path with a + // non-path-prefixed use tree glob + gcc_assert (!has_path ()); + } + // TODO: do path-prefixed paths also have to have a path? If so, have an + // assert for that too. + } + + /* Returns whether has path. Should be made redundant by PathType + * PATH_PREFIXED. */ + bool has_path () const { return !path.is_empty (); } + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + /* TODO: find way to ensure only PATH_PREFIXED glob_type has path - factory + * methods? */ +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + UseTreeGlob *clone_use_tree_impl () const override + { + return new UseTreeGlob (*this); + } +}; + +// Use tree with a list of paths with a common prefix +class UseTreeList : public UseTree +{ +public: + enum PathType + { + NO_PATH, + GLOBAL, + PATH_PREFIXED + }; + +private: + PathType path_type; + AST::SimplePath path; + + std::vector> trees; + +public: + UseTreeList (PathType path_type, AST::SimplePath path, + std::vector> trees, Location locus) + : UseTree (locus), path_type (path_type), path (std::move (path)), + trees (std::move (trees)) + { + if (this->path_type != PATH_PREFIXED) + { + // compiler implementation error if there is a path with a + // non-path-prefixed use tree glob + gcc_assert (!has_path ()); + } + // TODO: do path-prefixed paths also have to have a path? If so, have an + // assert for that too. + } + + // copy constructor with vector clone + UseTreeList (UseTreeList const &other) + : UseTree (other), path_type (other.path_type), path (other.path) + { + trees.reserve (other.trees.size ()); + for (const auto &e : other.trees) + trees.push_back (e->clone_use_tree ()); + } + + // overloaded assignment operator with vector clone + UseTreeList &operator= (UseTreeList const &other) + { + UseTree::operator= (other); + path_type = other.path_type; + path = other.path; + + trees.reserve (other.trees.size ()); + for (const auto &e : other.trees) + trees.push_back (e->clone_use_tree ()); + + return *this; + } + + // move constructors + UseTreeList (UseTreeList &&other) = default; + UseTreeList &operator= (UseTreeList &&other) = default; + + // Returns whether has path. Should be made redundant by path_type. + bool has_path () const { return !path.is_empty (); } + + // Returns whether has inner tree elements. + bool has_trees () const { return !trees.empty (); } + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory + // methods? +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + UseTreeList *clone_use_tree_impl () const override + { + return new UseTreeList (*this); + } +}; + +// Use tree where it rebinds the module name as something else +class UseTreeRebind : public UseTree +{ +public: + enum NewBindType + { + NONE, + IDENTIFIER, + WILDCARD + }; + +private: + AST::SimplePath path; + + NewBindType bind_type; + Identifier identifier; // only if NewBindType is IDENTIFIER + +public: + UseTreeRebind (NewBindType bind_type, AST::SimplePath path, Location locus, + Identifier identifier = std::string ()) + : UseTree (locus), path (std::move (path)), bind_type (bind_type), + identifier (std::move (identifier)) + {} + + // Returns whether has path (this should always be true). + bool has_path () const { return !path.is_empty (); } + + // Returns whether has identifier (or, rather, is allowed to). + bool has_identifier () const { return bind_type == IDENTIFIER; } + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory + // methods? +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + virtual UseTreeRebind *clone_use_tree_impl () const override + { + return new UseTreeRebind (*this); + } +}; + +// Rust use declaration (i.e. for modules) HIR node +class UseDeclaration : public VisItem +{ + std::unique_ptr use_tree; + Location locus; + +public: + std::string as_string () const override; + + UseDeclaration (Analysis::NodeMapping mappings, + std::unique_ptr use_tree, Visibility visibility, + AST::AttrVec outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (visibility), + std::move (outer_attrs)), + use_tree (std::move (use_tree)), locus (locus) + {} + + // Copy constructor with clone + UseDeclaration (UseDeclaration const &other) + : VisItem (other), use_tree (other.use_tree->clone_use_tree ()), + locus (other.locus) + {} + + // Overloaded assignment operator to clone + UseDeclaration &operator= (UseDeclaration const &other) + { + VisItem::operator= (other); + use_tree = other.use_tree->clone_use_tree (); + // visibility = other.visibility->clone_visibility(); + // outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + // move constructors + UseDeclaration (UseDeclaration &&other) = default; + UseDeclaration &operator= (UseDeclaration &&other) = default; + + Location get_locus () const override final { return locus; } + ItemKind get_item_kind () const override { return ItemKind::UseDeclaration; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + UseDeclaration *clone_item_impl () const override + { + return new UseDeclaration (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual UseDeclaration* clone_statement_impl() const override { + return new UseDeclaration(*this); + }*/ +}; + +class LetStmt; + +// Rust function declaration HIR node +class Function : public VisItem, public ImplItem +{ + FunctionQualifiers qualifiers; + Identifier function_name; + std::vector> generic_params; + std::vector function_params; + std::unique_ptr return_type; + WhereClause where_clause; + std::unique_ptr function_body; + SelfParam self; + Location locus; + +public: + std::string as_string () const override; + + // Returns whether function has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether function has regular parameters. + bool has_function_params () const { return !function_params.empty (); } + + // Returns whether function has return type - if not, it is void. + bool has_function_return_type () const { return return_type != nullptr; } + + // Returns whether function has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + ImplItemType get_impl_item_type () const override final + { + return ImplItem::ImplItemType::FUNCTION; + } + + ItemKind get_item_kind () const override { return ItemKind::Function; } + + // Mega-constructor with all possible fields + Function (Analysis::NodeMapping mappings, Identifier function_name, + FunctionQualifiers qualifiers, + std::vector> generic_params, + std::vector function_params, + std::unique_ptr return_type, WhereClause where_clause, + std::unique_ptr function_body, Visibility vis, + AST::AttrVec outer_attrs, SelfParam self, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + qualifiers (std::move (qualifiers)), + function_name (std::move (function_name)), + generic_params (std::move (generic_params)), + function_params (std::move (function_params)), + return_type (std::move (return_type)), + where_clause (std::move (where_clause)), + function_body (std::move (function_body)), self (std::move (self)), + locus (locus) + {} + + // Copy constructor with clone + Function (Function const &other) + : VisItem (other), qualifiers (other.qualifiers), + function_name (other.function_name), + function_params (other.function_params), + where_clause (other.where_clause), + function_body (other.function_body->clone_block_expr ()), + self (other.self), locus (other.locus) + { + // guard to prevent null dereference (always required) + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + // Overloaded assignment operator to clone + Function &operator= (Function const &other) + { + VisItem::operator= (other); + function_name = other.function_name; + qualifiers = other.qualifiers; + function_params = other.function_params; + + // guard to prevent null dereference (always required) + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; + + where_clause = other.where_clause; + function_body = other.function_body->clone_block_expr (); + locus = other.locus; + self = other.self; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + Function (Function &&other) = default; + Function &operator= (Function &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRImplVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + Analysis::NodeMapping get_impl_mappings () const override + { + return get_mappings (); + }; + + std::vector &get_function_params () { return function_params; } + const std::vector &get_function_params () const + { + return function_params; + } + + std::vector> &get_generic_params () + { + return generic_params; + } + const std::vector> &get_generic_params () const + { + return generic_params; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_definition () + { + rust_assert (function_body != nullptr); + return function_body; + } + + const FunctionQualifiers &get_qualifiers () const { return qualifiers; } + + Identifier get_function_name () const { return function_name; } + + // TODO: is this better? Or is a "vis_block" better? + WhereClause &get_where_clause () { return where_clause; } + + bool has_return_type () const { return return_type != nullptr; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_return_type () + { + rust_assert (has_return_type ()); + return return_type; + } + + bool is_method () const { return !self.is_error (); } + + SelfParam &get_self_param () { return self; } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + Function *clone_item_impl () const override { return new Function (*this); } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + Function *clone_inherent_impl_item_impl () const override + { + return new Function (*this); + } +}; + +// Rust type alias (i.e. typedef) HIR node +class TypeAlias : public VisItem, public ImplItem +{ + Identifier new_type_name; + + // bool has_generics; + // Generics generic_params; + std::vector> generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::unique_ptr existing_type; + + Location locus; + +public: + std::string as_string () const override; + + // Returns whether type alias has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether type alias has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + ImplItemType get_impl_item_type () const override final + { + return ImplItem::ImplItemType::TYPE_ALIAS; + } + + // Mega-constructor with all possible fields + TypeAlias (Analysis::NodeMapping mappings, Identifier new_type_name, + std::vector> generic_params, + WhereClause where_clause, std::unique_ptr existing_type, + Visibility vis, AST::AttrVec outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + new_type_name (std::move (new_type_name)), + generic_params (std::move (generic_params)), + where_clause (std::move (where_clause)), + existing_type (std::move (existing_type)), locus (locus) + {} + + // Copy constructor + TypeAlias (TypeAlias const &other) + : VisItem (other), new_type_name (other.new_type_name), + where_clause (other.where_clause), + existing_type (other.existing_type->clone_type ()), locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + // Overloaded assignment operator to clone + TypeAlias &operator= (TypeAlias const &other) + { + VisItem::operator= (other); + new_type_name = other.new_type_name; + where_clause = other.where_clause; + existing_type = other.existing_type->clone_type (); + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + TypeAlias (TypeAlias &&other) = default; + TypeAlias &operator= (TypeAlias &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRImplVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + std::vector> &get_generic_params () + { + return generic_params; + } + const std::vector> &get_generic_params () const + { + return generic_params; + } + + WhereClause &get_where_clause () { return where_clause; } + + std::unique_ptr &get_type_aliased () + { + rust_assert (existing_type != nullptr); + return existing_type; + } + + Identifier get_new_type_name () const { return new_type_name; } + + ItemKind get_item_kind () const override { return ItemKind::TypeAlias; } + + Analysis::NodeMapping get_impl_mappings () const override + { + return get_mappings (); + }; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + TypeAlias *clone_item_impl () const override { return new TypeAlias (*this); } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + TypeAlias *clone_inherent_impl_item_impl () const override + { + return new TypeAlias (*this); + } +}; + +// Rust base struct declaration HIR node - abstract base class +class Struct : public VisItem +{ +protected: + // protected to enable access by derived classes - allows better as_string + Identifier struct_name; + + // bool has_generics; + // Generics generic_params; + std::vector> generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + Location locus; + +public: + Identifier get_identifier () const { return struct_name; } + + // Returns whether struct has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether struct has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + Location get_locus () const override final { return locus; } + ItemKind get_item_kind () const override { return ItemKind::Struct; } + + std::vector> &get_generic_params () + { + return generic_params; + } + + WhereClause &get_where_clause () { return where_clause; } + +protected: + Struct (Analysis::NodeMapping mappings, Identifier struct_name, + std::vector> generic_params, + WhereClause where_clause, Visibility vis, Location locus, + AST::AttrVec outer_attrs = AST::AttrVec ()) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + struct_name (std::move (struct_name)), + generic_params (std::move (generic_params)), + where_clause (std::move (where_clause)), locus (locus) + {} + + // Copy constructor with vector clone + Struct (Struct const &other) + : VisItem (other), struct_name (other.struct_name), + where_clause (other.where_clause), locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + // Overloaded assignment operator with vector clone + Struct &operator= (Struct const &other) + { + VisItem::operator= (other); + struct_name = other.struct_name; + where_clause = other.where_clause; + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + Struct (Struct &&other) = default; + Struct &operator= (Struct &&other) = default; +}; + +// A single field in a struct +struct StructField +{ +public: + // bool has_outer_attributes; + AST::AttrVec outer_attrs; + + // bool has_visibility; + Visibility visibility; + + Identifier field_name; + std::unique_ptr field_type; + + Analysis::NodeMapping mappings; + + Location locus; + + // Returns whether struct field has any outer attributes. + bool has_outer_attributes () const { return !outer_attrs.empty (); } + + // Returns whether struct field has a non-private (non-default) visibility. + bool has_visibility () const { return !visibility.is_error (); } + + StructField (Analysis::NodeMapping mappings, Identifier field_name, + std::unique_ptr field_type, Visibility vis, Location locus, + AST::AttrVec outer_attrs = AST::AttrVec ()) + : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), + field_name (std::move (field_name)), field_type (std::move (field_type)), + mappings (mappings), locus (locus) + {} + + // Copy constructor + StructField (StructField const &other) + : outer_attrs (other.outer_attrs), visibility (other.visibility), + field_name (other.field_name), + field_type (other.field_type->clone_type ()), mappings (other.mappings) + {} + + ~StructField () = default; + + // Overloaded assignment operator to clone + StructField &operator= (StructField const &other) + { + field_name = other.field_name; + field_type = other.field_type->clone_type (); + visibility = other.visibility; + outer_attrs = other.outer_attrs; + mappings = other.mappings; + + return *this; + } + + // move constructors + StructField (StructField &&other) = default; + StructField &operator= (StructField &&other) = default; + + std::string as_string () const; + + Identifier get_field_name () const { return field_name; } + + std::unique_ptr &get_field_type () + { + rust_assert (field_type != nullptr); + return field_type; + } + + Analysis::NodeMapping get_mappings () const { return mappings; } + + Location get_locus () { return locus; } + + Visibility &get_visibility () { return visibility; } +}; + +// Rust struct declaration with true struct type HIR node +class StructStruct : public Struct +{ +public: + std::vector fields; + bool is_unit; + + std::string as_string () const override; + + // Mega-constructor with all possible fields + StructStruct (Analysis::NodeMapping mappings, std::vector fields, + Identifier struct_name, + std::vector> generic_params, + WhereClause where_clause, bool is_unit, Visibility vis, + AST::AttrVec outer_attrs, Location locus) + : Struct (std::move (mappings), std::move (struct_name), + std::move (generic_params), std::move (where_clause), + std::move (vis), locus, std::move (outer_attrs)), + fields (std::move (fields)), is_unit (is_unit) + {} + + // Unit struct constructor + StructStruct (Analysis::NodeMapping mappings, Identifier struct_name, + std::vector> generic_params, + WhereClause where_clause, Visibility vis, + AST::AttrVec outer_attrs, Location locus) + : Struct (std::move (mappings), std::move (struct_name), + std::move (generic_params), std::move (where_clause), + std::move (vis), locus, std::move (outer_attrs)), + is_unit (true) + {} + // TODO: can a unit struct have generic fields? assuming yes for now. + + /* Returns whether the struct is a unit struct - struct defined without + * fields. This is important because it also means an implicit constant of its + * type is defined. */ + bool is_unit_struct () const { return is_unit; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + std::vector &get_fields () { return fields; } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + StructStruct *clone_item_impl () const override + { + return new StructStruct (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual StructStruct* clone_statement_impl() const override { + return new StructStruct(*this); + }*/ +}; + +// A single field in a tuple +struct TupleField +{ +private: + // bool has_outer_attributes; + AST::AttrVec outer_attrs; + + // bool has_visibility; + Visibility visibility; + + std::unique_ptr field_type; + + Location locus; + + Analysis::NodeMapping mappings; + +public: + // Returns whether tuple field has outer attributes. + bool has_outer_attributes () const { return !outer_attrs.empty (); } + + /* Returns whether tuple field has a non-default visibility (i.e. a public + * one) */ + bool has_visibility () const { return !visibility.is_error (); } + + // Complete constructor + TupleField (Analysis::NodeMapping mapping, std::unique_ptr field_type, + Visibility vis, Location locus, + AST::AttrVec outer_attrs = AST::AttrVec ()) + : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), + field_type (std::move (field_type)), locus (locus), mappings (mapping) + {} + + // Copy constructor with clone + TupleField (TupleField const &other) + : outer_attrs (other.outer_attrs), visibility (other.visibility), + field_type (other.field_type->clone_type ()), locus (other.locus), + mappings (other.mappings) + {} + + ~TupleField () = default; + + // Overloaded assignment operator to clone + TupleField &operator= (TupleField const &other) + { + field_type = other.field_type->clone_type (); + visibility = other.visibility; + outer_attrs = other.outer_attrs; + locus = other.locus; + mappings = other.mappings; + + return *this; + } + + // move constructors + TupleField (TupleField &&other) = default; + TupleField &operator= (TupleField &&other) = default; + + // Returns whether tuple field is in an error state. + bool is_error () const { return field_type == nullptr; } + + std::string as_string () const; + + Analysis::NodeMapping get_mappings () const { return mappings; } + + Location get_locus () const { return locus; } + + std::unique_ptr &get_field_type () { return field_type; } +}; + +// Rust tuple declared using struct keyword HIR node +class TupleStruct : public Struct +{ + std::vector fields; + +public: + std::string as_string () const override; + + // Mega-constructor with all possible fields + TupleStruct (Analysis::NodeMapping mappings, std::vector fields, + Identifier struct_name, + std::vector> generic_params, + WhereClause where_clause, Visibility vis, + AST::AttrVec outer_attrs, Location locus) + : Struct (std::move (mappings), std::move (struct_name), + std::move (generic_params), std::move (where_clause), + std::move (vis), locus, std::move (outer_attrs)), + fields (std::move (fields)) + {} + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + std::vector &get_fields () { return fields; } + const std::vector &get_fields () const { return fields; } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + TupleStruct *clone_item_impl () const override + { + return new TupleStruct (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual TupleStruct* clone_statement_impl() const override { + return new TupleStruct(*this); + }*/ +}; + +/* An item used in an "enum" tagged union - not abstract: base represents a + name-only enum. Syntactically EnumItem's can have a Visibility. But not + Semantically. So check there is no Visibility when lowering and make this + an Item, not an VisItem. */ +class EnumItem : public Item +{ + Identifier variant_name; + Location locus; + +public: + virtual ~EnumItem () {} + + enum EnumItemKind + { + Named, + Tuple, + Struct, + Discriminant, + }; + + EnumItem (Analysis::NodeMapping mappings, Identifier variant_name, + AST::AttrVec outer_attrs, Location locus) + : Item (std::move (mappings), std::move (outer_attrs)), + variant_name (std::move (variant_name)), locus (locus) + {} + + // Unique pointer custom clone function + std::unique_ptr clone_enum_item () const + { + return std::unique_ptr (clone_item_impl ()); + } + + virtual std::string as_string () const override; + virtual EnumItemKind get_enum_item_kind () const { return Named; }; + + // not pure virtual as not abstract + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + // void accept_vis (HIRVisItemVisitor &vis) override; + + Location get_locus () const override { return locus; } + + Identifier get_identifier () const { return variant_name; } + + ItemKind get_item_kind () const override { return ItemKind::EnumItem; } + +protected: + EnumItem *clone_item_impl () const override { return new EnumItem (*this); } +}; + +// A tuple item used in an "enum" tagged union +class EnumItemTuple : public EnumItem +{ + // bool has_tuple_fields; + std::vector tuple_fields; + +public: + // Returns whether tuple enum item has tuple fields. + bool has_tuple_fields () const { return !tuple_fields.empty (); } + + EnumItemKind get_enum_item_kind () const override + { + return EnumItemKind::Tuple; + } + + EnumItemTuple (Analysis::NodeMapping mappings, Identifier variant_name, + std::vector tuple_fields, AST::AttrVec outer_attrs, + Location locus) + : EnumItem (std::move (mappings), std::move (variant_name), + std::move (outer_attrs), locus), + tuple_fields (std::move (tuple_fields)) + {} + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + + std::vector &get_tuple_fields () { return tuple_fields; } + +protected: + // Clone function implementation as (not pure) virtual method + EnumItemTuple *clone_item_impl () const override + { + return new EnumItemTuple (*this); + } +}; + +// A struct item used in an "enum" tagged union +class EnumItemStruct : public EnumItem +{ + // bool has_struct_fields; + std::vector struct_fields; + +public: + // Returns whether struct enum item has struct fields. + bool has_struct_fields () const { return !struct_fields.empty (); } + + EnumItemKind get_enum_item_kind () const override + { + return EnumItemKind::Struct; + } + + EnumItemStruct (Analysis::NodeMapping mappings, Identifier variant_name, + std::vector struct_fields, + AST::AttrVec outer_attrs, Location locus) + : EnumItem (std::move (mappings), std::move (variant_name), + std::move (outer_attrs), locus), + struct_fields (std::move (struct_fields)) + {} + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + + std::vector &get_struct_fields () { return struct_fields; } + +protected: + // Clone function implementation as (not pure) virtual method + EnumItemStruct *clone_item_impl () const override + { + return new EnumItemStruct (*this); + } +}; + +// A discriminant (numbered enum) item used in an "enum" tagged union +class EnumItemDiscriminant : public EnumItem +{ + std::unique_ptr expression; + +public: + EnumItemDiscriminant (Analysis::NodeMapping mappings, Identifier variant_name, + std::unique_ptr expr, AST::AttrVec outer_attrs, + Location locus) + : EnumItem (std::move (mappings), std::move (variant_name), + std::move (outer_attrs), locus), + expression (std::move (expr)) + {} + + // Copy constructor with clone + EnumItemDiscriminant (EnumItemDiscriminant const &other) + : EnumItem (other), expression (other.expression->clone_expr ()) + {} + + // Overloaded assignment operator to clone + EnumItemDiscriminant &operator= (EnumItemDiscriminant const &other) + { + EnumItem::operator= (other); + expression = other.expression->clone_expr (); + // variant_name = other.variant_name; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + EnumItemDiscriminant (EnumItemDiscriminant &&other) = default; + EnumItemDiscriminant &operator= (EnumItemDiscriminant &&other) = default; + + EnumItemKind get_enum_item_kind () const override + { + return EnumItemKind::Discriminant; + } + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + + std::unique_ptr &get_discriminant_expression () { return expression; } + +protected: + // Clone function implementation as (not pure) virtual method + EnumItemDiscriminant *clone_item_impl () const override + { + return new EnumItemDiscriminant (*this); + } +}; + +// HIR node for Rust "enum" - tagged union +class Enum : public VisItem +{ + Identifier enum_name; + + // bool has_generics; + // Generics generic_params; + std::vector> generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::vector> items; + + Location locus; + +public: + std::string as_string () const override; + + // Returns whether "enum" has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether "enum" has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + /* Returns whether enum is a "zero-variant" (no possible variant) enum, + * which cannot be instantiated. */ + bool is_zero_variant () const { return items.empty (); } + + // Mega-constructor + Enum (Analysis::NodeMapping mappings, Identifier enum_name, Visibility vis, + std::vector> generic_params, + WhereClause where_clause, std::vector> items, + AST::AttrVec outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + enum_name (std::move (enum_name)), + generic_params (std::move (generic_params)), + where_clause (std::move (where_clause)), items (std::move (items)), + locus (locus) + {} + + // TODO: constructor with less arguments + + // Copy constructor with vector clone + Enum (Enum const &other) + : VisItem (other), enum_name (other.enum_name), + where_clause (other.where_clause), locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_enum_item ()); + } + + // Overloaded assignment operator with vector clone + Enum &operator= (Enum const &other) + { + VisItem::operator= (other); + enum_name = other.enum_name; + where_clause = other.where_clause; + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_enum_item ()); + + return *this; + } + + // Move constructors + Enum (Enum &&other) = default; + Enum &operator= (Enum &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + Identifier get_identifier () const { return enum_name; } + ItemKind get_item_kind () const override { return ItemKind::Enum; } + + std::vector> &get_generic_params () + { + return generic_params; + } + + const std::vector> &get_variants () const + { + return items; + } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + Enum *clone_item_impl () const override { return new Enum (*this); } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual Enum* clone_statement_impl() const override { + return new Enum(*this); + }*/ +}; + +// Rust untagged union used for C compat HIR node +class Union : public VisItem +{ + Identifier union_name; + + // bool has_generics; + // Generics generic_params; + std::vector> generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::vector variants; + + Location locus; + +public: + std::string as_string () const override; + + // Returns whether union has generic params. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether union has where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + Union (Analysis::NodeMapping mappings, Identifier union_name, Visibility vis, + std::vector> generic_params, + WhereClause where_clause, std::vector variants, + AST::AttrVec outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + union_name (std::move (union_name)), + generic_params (std::move (generic_params)), + where_clause (std::move (where_clause)), variants (std::move (variants)), + locus (locus) + {} + + // copy constructor with vector clone + Union (Union const &other) + : VisItem (other), union_name (other.union_name), + where_clause (other.where_clause), variants (other.variants), + locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + // overloaded assignment operator with vector clone + Union &operator= (Union const &other) + { + VisItem::operator= (other); + union_name = other.union_name; + where_clause = other.where_clause; + variants = other.variants; + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + Union (Union &&other) = default; + Union &operator= (Union &&other) = default; + + std::vector> &get_generic_params () + { + return generic_params; + } + + Identifier get_identifier () const { return union_name; } + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + std::vector &get_variants () { return variants; } + + WhereClause &get_where_clause () { return where_clause; } + + ItemKind get_item_kind () const override { return ItemKind::Union; } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + Union *clone_item_impl () const override { return new Union (*this); } +}; + +class ConstantItem : public VisItem, public ImplItem +{ + Identifier identifier; + std::unique_ptr type; + std::unique_ptr const_expr; + Location locus; + +public: + std::string as_string () const override; + + ConstantItem (Analysis::NodeMapping mappings, Identifier ident, + Visibility vis, std::unique_ptr type, + std::unique_ptr const_expr, AST::AttrVec outer_attrs, + Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + identifier (std::move (ident)), type (std::move (type)), + const_expr (std::move (const_expr)), locus (locus) + {} + + ConstantItem (ConstantItem const &other) + : VisItem (other), identifier (other.identifier), + type (other.type->clone_type ()), + const_expr (other.const_expr->clone_expr ()), locus (other.locus) + {} + + // Overload assignment operator to clone + ConstantItem &operator= (ConstantItem const &other) + { + VisItem::operator= (other); + identifier = other.identifier; + type = other.type->clone_type (); + const_expr = other.const_expr->clone_expr (); + locus = other.locus; + + return *this; + } + + // move constructors + ConstantItem (ConstantItem &&other) = default; + ConstantItem &operator= (ConstantItem &&other) = default; + + // Returns whether constant item is an "unnamed" (wildcard underscore used + // as identifier) constant. + bool is_unnamed () const { return identifier == std::string ("_"); } + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRImplVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + Type *get_type () { return type.get (); } + + Expr *get_expr () { return const_expr.get (); } + + std::string get_identifier () { return identifier; } + + Analysis::NodeMapping get_impl_mappings () const override + { + return get_mappings (); + }; + + ImplItemType get_impl_item_type () const override final + { + return ImplItem::ImplItemType::CONSTANT; + } + + ItemKind get_item_kind () const override { return ItemKind::Constant; } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + ConstantItem *clone_item_impl () const override + { + return new ConstantItem (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + ConstantItem *clone_inherent_impl_item_impl () const override + { + return new ConstantItem (*this); + } +}; + +/* Static item HIR node - items within module scope with fixed storage + * duration? */ +class StaticItem : public VisItem +{ + Mutability mut; + Identifier name; + std::unique_ptr type; + std::unique_ptr expr; + Location locus; + +public: + std::string as_string () const override; + + StaticItem (Analysis::NodeMapping mappings, Identifier name, Mutability mut, + std::unique_ptr type, std::unique_ptr expr, + Visibility vis, AST::AttrVec outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + mut (mut), name (std::move (name)), type (std::move (type)), + expr (std::move (expr)), locus (locus) + {} + + // Copy constructor with clone + StaticItem (StaticItem const &other) + : VisItem (other), mut (other.mut), name (other.name), + type (other.type->clone_type ()), expr (other.expr->clone_expr ()), + locus (other.locus) + {} + + // Overloaded assignment operator to clone + StaticItem &operator= (StaticItem const &other) + { + VisItem::operator= (other); + name = other.name; + mut = other.mut; + type = other.type->clone_type (); + expr = other.expr->clone_expr (); + locus = other.locus; + + return *this; + } + + // move constructors + StaticItem (StaticItem &&other) = default; + StaticItem &operator= (StaticItem &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + Identifier get_identifier () const { return name; } + + Mutability get_mut () const { return mut; } + + bool is_mut () const { return mut == Mutability::Mut; } + + Expr *get_expr () { return expr.get (); } + + Type *get_type () { return type.get (); } + + ItemKind get_item_kind () const override { return ItemKind::Static; } + +protected: + StaticItem *clone_item_impl () const override + { + return new StaticItem (*this); + } +}; + +// Function declaration in traits +struct TraitFunctionDecl +{ +private: + FunctionQualifiers qualifiers; + Identifier function_name; + std::vector> generic_params; + std::vector function_params; + std::unique_ptr return_type; + WhereClause where_clause; + SelfParam self; + +public: + // Mega-constructor + TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers, + std::vector> generic_params, + SelfParam self, std::vector function_params, + std::unique_ptr return_type, + WhereClause where_clause) + : qualifiers (std::move (qualifiers)), + function_name (std::move (function_name)), + generic_params (std::move (generic_params)), + function_params (std::move (function_params)), + return_type (std::move (return_type)), + where_clause (std::move (where_clause)), self (std::move (self)) + {} + + // Copy constructor with clone + TraitFunctionDecl (TraitFunctionDecl const &other) + : qualifiers (other.qualifiers), function_name (other.function_name), + function_params (other.function_params), + return_type (other.return_type->clone_type ()), + where_clause (other.where_clause), self (other.self) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + ~TraitFunctionDecl () = default; + + // Overloaded assignment operator with clone + TraitFunctionDecl &operator= (TraitFunctionDecl const &other) + { + function_name = other.function_name; + qualifiers = other.qualifiers; + function_params = other.function_params; + return_type = other.return_type->clone_type (); + where_clause = other.where_clause; + self = other.self; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + TraitFunctionDecl (TraitFunctionDecl &&other) = default; + TraitFunctionDecl &operator= (TraitFunctionDecl &&other) = default; + + std::string as_string () const; + + // Returns whether function decl has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether function decl has regular parameters. + bool has_params () const { return !function_params.empty (); } + + // Returns whether function has return type (otherwise is void). + bool has_return_type () const { return return_type != nullptr; } + + // Returns whether function has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + bool is_method () const { return !self.is_error (); } + + SelfParam &get_self () { return self; } + + Identifier get_function_name () const { return function_name; } + + std::vector> &get_generic_params () + { + return generic_params; + } + + std::unique_ptr &get_return_type () + { + rust_assert (has_return_type ()); + return return_type; + } + + std::vector &get_function_params () { return function_params; } + + const FunctionQualifiers &get_qualifiers () const { return qualifiers; } +}; + +// Actual trait item function declaration within traits +class TraitItemFunc : public TraitItem +{ + AST::AttrVec outer_attrs; + TraitFunctionDecl decl; + std::unique_ptr block_expr; + Location locus; + +public: + // Returns whether function has a definition or is just a declaration. + bool has_definition () const { return block_expr != nullptr; } + + TraitItemFunc (Analysis::NodeMapping mappings, TraitFunctionDecl decl, + std::unique_ptr block_expr, + AST::AttrVec outer_attrs, Location locus) + : TraitItem (mappings), outer_attrs (std::move (outer_attrs)), + decl (std::move (decl)), block_expr (std::move (block_expr)), + locus (locus) + {} + + // Copy constructor with clone + TraitItemFunc (TraitItemFunc const &other) + : TraitItem (other.mappings), outer_attrs (other.outer_attrs), + decl (other.decl), locus (other.locus) + { + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + } + + // Overloaded assignment operator to clone + TraitItemFunc &operator= (TraitItemFunc const &other) + { + TraitItem::operator= (other); + outer_attrs = other.outer_attrs; + decl = other.decl; + locus = other.locus; + mappings = other.mappings; + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + + return *this; + } + + // move constructors + TraitItemFunc (TraitItemFunc &&other) = default; + TraitItemFunc &operator= (TraitItemFunc &&other) = default; + + std::string as_string () const override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTraitItemVisitor &vis) override; + + TraitFunctionDecl &get_decl () { return decl; } + + const TraitFunctionDecl &get_decl () const { return decl; } + + bool has_block_defined () const { return block_expr != nullptr; } + + std::unique_ptr &get_block_expr () + { + rust_assert (has_block_defined ()); + return block_expr; + } + + const std::string trait_identifier () const override final + { + return decl.get_function_name (); + } + + TraitItemKind get_item_kind () const override final + { + return TraitItemKind::FUNC; + } + + AST::AttrVec &get_outer_attrs () override final { return outer_attrs; } + const AST::AttrVec &get_outer_attrs () const override final + { + return outer_attrs; + } + +protected: + // Clone function implementation as (not pure) virtual method + TraitItemFunc *clone_trait_item_impl () const override + { + return new TraitItemFunc (*this); + } +}; + +// Constant item within traits +class TraitItemConst : public TraitItem +{ + AST::AttrVec outer_attrs; + Identifier name; + std::unique_ptr type; + std::unique_ptr expr; + Location locus; + +public: + // Whether the constant item has an associated expression. + bool has_expression () const { return expr != nullptr; } + + TraitItemConst (Analysis::NodeMapping mappings, Identifier name, + std::unique_ptr type, std::unique_ptr expr, + AST::AttrVec outer_attrs, Location locus) + : TraitItem (mappings), outer_attrs (std::move (outer_attrs)), + name (std::move (name)), type (std::move (type)), expr (std::move (expr)), + locus (locus) + {} + + // Copy constructor with clones + TraitItemConst (TraitItemConst const &other) + : TraitItem (other.mappings), outer_attrs (other.outer_attrs), + name (other.name), type (other.type->clone_type ()), + expr (other.expr->clone_expr ()), locus (other.locus) + {} + + // Overloaded assignment operator to clone + TraitItemConst &operator= (TraitItemConst const &other) + { + TraitItem::operator= (other); + outer_attrs = other.outer_attrs; + name = other.name; + type = other.type->clone_type (); + expr = other.expr->clone_expr (); + locus = other.locus; + mappings = other.mappings; + + return *this; + } + + // move constructors + TraitItemConst (TraitItemConst &&other) = default; + TraitItemConst &operator= (TraitItemConst &&other) = default; + + std::string as_string () const override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTraitItemVisitor &vis) override; + + Identifier get_name () const { return name; } + + bool has_expr () const { return expr != nullptr; } + + std::unique_ptr &get_type () { return type; } + + std::unique_ptr &get_expr () + { + rust_assert (has_expr ()); + return expr; + } + + const std::string trait_identifier () const override final { return name; } + + TraitItemKind get_item_kind () const override final + { + return TraitItemKind::CONST; + } + + AST::AttrVec &get_outer_attrs () override final { return outer_attrs; } + const AST::AttrVec &get_outer_attrs () const override final + { + return outer_attrs; + } + +protected: + // Clone function implementation as (not pure) virtual method + TraitItemConst *clone_trait_item_impl () const override + { + return new TraitItemConst (*this); + } +}; + +// Type items within traits +class TraitItemType : public TraitItem +{ + AST::AttrVec outer_attrs; + + Identifier name; + std::vector> + type_param_bounds; // inlined form + Location locus; + +public: + // Returns whether trait item type has type param bounds. + bool has_type_param_bounds () const { return !type_param_bounds.empty (); } + + TraitItemType (Analysis::NodeMapping mappings, Identifier name, + std::vector> type_param_bounds, + AST::AttrVec outer_attrs, Location locus) + : TraitItem (mappings), outer_attrs (std::move (outer_attrs)), + name (std::move (name)), + type_param_bounds (std::move (type_param_bounds)), locus (locus) + {} + + // Copy constructor with vector clone + TraitItemType (TraitItemType const &other) + : TraitItem (other.mappings), outer_attrs (other.outer_attrs), + name (other.name), locus (other.locus) + { + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + } + + // Overloaded assignment operator with vector clone + TraitItemType &operator= (TraitItemType const &other) + { + TraitItem::operator= (other); + outer_attrs = other.outer_attrs; + name = other.name; + locus = other.locus; + mappings = other.mappings; + + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + + return *this; + } + + // default move constructors + TraitItemType (TraitItemType &&other) = default; + TraitItemType &operator= (TraitItemType &&other) = default; + + std::string as_string () const override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTraitItemVisitor &vis) override; + + Identifier get_name () const { return name; } + + std::vector> &get_type_param_bounds () + { + return type_param_bounds; + } + + const std::string trait_identifier () const override final { return name; } + + TraitItemKind get_item_kind () const override final + { + return TraitItemKind::TYPE; + } + + AST::AttrVec &get_outer_attrs () override final { return outer_attrs; } + const AST::AttrVec &get_outer_attrs () const override final + { + return outer_attrs; + } + +protected: + // Clone function implementation as (not pure) virtual method + TraitItemType *clone_trait_item_impl () const override + { + return new TraitItemType (*this); + } +}; + +// Rust trait item declaration HIR node +class Trait : public VisItem +{ + Unsafety unsafety; + Identifier name; + std::vector> generic_params; + std::vector> type_param_bounds; + WhereClause where_clause; + std::vector> trait_items; + Location locus; + +public: + std::string as_string () const override; + + // Returns whether trait has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether trait has type parameter bounds. + bool has_type_param_bounds () const { return !type_param_bounds.empty (); } + + // Returns whether trait has where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + // Returns whether trait has trait items. + bool has_trait_items () const { return !trait_items.empty (); } + + std::vector> &get_trait_items () + { + return trait_items; + } + + Identifier get_name () const { return name; } + + // Mega-constructor + Trait (Analysis::NodeMapping mappings, Identifier name, Unsafety unsafety, + std::vector> generic_params, + std::vector> type_param_bounds, + WhereClause where_clause, + std::vector> trait_items, Visibility vis, + AST::AttrVec outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + unsafety (unsafety), name (std::move (name)), + generic_params (std::move (generic_params)), + type_param_bounds (std::move (type_param_bounds)), + where_clause (std::move (where_clause)), + trait_items (std::move (trait_items)), locus (locus) + {} + + // Copy constructor with vector clone + Trait (Trait const &other) + : VisItem (other), unsafety (other.unsafety), name (other.name), + where_clause (other.where_clause), locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + + trait_items.reserve (other.trait_items.size ()); + for (const auto &e : other.trait_items) + trait_items.push_back (e->clone_trait_item ()); + } + + // Overloaded assignment operator with vector clone + Trait &operator= (Trait const &other) + { + VisItem::operator= (other); + name = other.name; + unsafety = other.unsafety; + where_clause = other.where_clause; + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + + trait_items.reserve (other.trait_items.size ()); + for (const auto &e : other.trait_items) + trait_items.push_back (e->clone_trait_item ()); + + return *this; + } + + // default move constructors + Trait (Trait &&other) = default; + Trait &operator= (Trait &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + std::vector> &get_generic_params () + { + return generic_params; + } + + const std::vector> &get_generic_params () const + { + return generic_params; + } + + std::vector> &get_type_param_bounds () + { + return type_param_bounds; + } + + const std::vector> & + get_type_param_bounds () const + { + return type_param_bounds; + } + + ItemKind get_item_kind () const override { return ItemKind::Trait; } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + Trait *clone_item_impl () const override { return new Trait (*this); } +}; + +class ImplBlock : public VisItem +{ + std::vector> generic_params; + std::unique_ptr impl_type; + std::unique_ptr trait_ref; + WhereClause where_clause; + Polarity polarity; + AST::AttrVec inner_attrs; + Location locus; + std::vector> impl_items; + +public: + ImplBlock (Analysis::NodeMapping mappings, + std::vector> impl_items, + std::vector> generic_params, + std::unique_ptr impl_type, + std::unique_ptr trait_ref, WhereClause where_clause, + Polarity polarity, Visibility vis, AST::AttrVec inner_attrs, + AST::AttrVec outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + generic_params (std::move (generic_params)), + impl_type (std::move (impl_type)), trait_ref (std::move (trait_ref)), + where_clause (std::move (where_clause)), polarity (polarity), + inner_attrs (std::move (inner_attrs)), locus (locus), + impl_items (std::move (impl_items)) + {} + + ImplBlock (ImplBlock const &other) + : VisItem (other), impl_type (other.impl_type->clone_type ()), + where_clause (other.where_clause), polarity (other.polarity), + inner_attrs (other.inner_attrs), locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + impl_items.reserve (other.impl_items.size ()); + for (const auto &e : other.impl_items) + impl_items.push_back (e->clone_inherent_impl_item ()); + } + + ImplBlock &operator= (ImplBlock const &other) + { + VisItem::operator= (other); + impl_type = other.impl_type->clone_type (); + where_clause = other.where_clause; + polarity = other.polarity; + inner_attrs = other.inner_attrs; + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + impl_items.reserve (other.impl_items.size ()); + for (const auto &e : other.impl_items) + impl_items.push_back (e->clone_inherent_impl_item ()); + + return *this; + } + + ImplBlock (ImplBlock &&other) = default; + ImplBlock &operator= (ImplBlock &&other) = default; + + std::string as_string () const override; + + // Returns whether inherent impl block has inherent impl items. + bool has_impl_items () const { return !impl_items.empty (); } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + std::vector> &get_impl_items () + { + return impl_items; + }; + + const std::vector> &get_impl_items () const + { + return impl_items; + }; + + // Returns whether impl has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether impl has where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + // Returns the polarity of the impl. + Polarity get_polarity () const { return polarity; } + + // Returns whether impl has inner attributes. + bool has_inner_attrs () const { return !inner_attrs.empty (); } + + Location get_locus () const override final { return locus; } + + std::unique_ptr &get_type () { return impl_type; }; + + std::vector> &get_generic_params () + { + return generic_params; + } + + bool has_trait_ref () const { return trait_ref != nullptr; } + + std::unique_ptr &get_trait_ref () + { + rust_assert (has_trait_ref ()); + return trait_ref; + } + + WhereClause &get_where_clause () { return where_clause; } + + ItemKind get_item_kind () const override { return ItemKind::Impl; } + +protected: + ImplBlock *clone_item_impl () const override { return new ImplBlock (*this); } +}; + +// Abstract base class for an item used inside an extern block +class ExternalItem : public Node +{ + Analysis::NodeMapping mappings; + AST::AttrVec outer_attrs; + Visibility visibility; + Identifier item_name; + Location locus; + +public: + enum class ExternKind + { + Static, + Function, + }; + + virtual ~ExternalItem () {} + + BaseKind get_hir_kind () override final { return EXTERNAL; } + + virtual ExternKind get_extern_kind () = 0; + + // Returns whether item has outer attributes. + bool has_outer_attrs () const { return !outer_attrs.empty (); } + + // Returns whether item has non-default visibility. + bool has_visibility () const { return !visibility.is_error (); } + + // Unique pointer custom clone function + std::unique_ptr clone_external_item () const + { + return std::unique_ptr (clone_external_item_impl ()); + } + + virtual std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (HIRFullVisitor &vis) = 0; + virtual void accept_vis (HIRExternalItemVisitor &vis) = 0; + + Analysis::NodeMapping get_mappings () const { return mappings; } + + Identifier get_item_name () const { return item_name; } + + AST::AttrVec &get_outer_attrs () { return outer_attrs; } + +protected: + ExternalItem (Analysis::NodeMapping mappings, Identifier item_name, + Visibility vis, AST::AttrVec outer_attrs, Location locus) + : mappings (mappings), outer_attrs (std::move (outer_attrs)), + visibility (std::move (vis)), item_name (std::move (item_name)), + locus (locus) + {} + + // Copy constructor + ExternalItem (ExternalItem const &other) + : mappings (other.mappings), outer_attrs (other.outer_attrs), + visibility (other.visibility), item_name (other.item_name), + locus (other.locus) + {} + + // Overloaded assignment operator to clone + ExternalItem &operator= (ExternalItem const &other) + { + mappings = other.mappings; + item_name = other.item_name; + visibility = other.visibility; + outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + // move constructors + ExternalItem (ExternalItem &&other) = default; + ExternalItem &operator= (ExternalItem &&other) = default; + + // Clone function implementation as pure virtual method + virtual ExternalItem *clone_external_item_impl () const = 0; +}; + +// A static item used in an extern block +class ExternalStaticItem : public ExternalItem +{ + Mutability mut; + std::unique_ptr item_type; + +public: + ExternalStaticItem (Analysis::NodeMapping mappings, Identifier item_name, + std::unique_ptr item_type, Mutability mut, + Visibility vis, AST::AttrVec outer_attrs, Location locus) + : ExternalItem (std::move (mappings), std::move (item_name), + std::move (vis), std::move (outer_attrs), locus), + mut (mut), item_type (std::move (item_type)) + {} + + // Copy constructor + ExternalStaticItem (ExternalStaticItem const &other) + : ExternalItem (other), mut (other.mut), + item_type (other.item_type->clone_type ()) + {} + + // Overloaded assignment operator to clone + ExternalStaticItem &operator= (ExternalStaticItem const &other) + { + ExternalItem::operator= (other); + item_type = other.item_type->clone_type (); + mut = other.mut; + + return *this; + } + + // move constructors + ExternalStaticItem (ExternalStaticItem &&other) = default; + ExternalStaticItem &operator= (ExternalStaticItem &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExternalItemVisitor &vis) override; + + bool is_mut () const { return mut == Mutability::Mut; } + + Mutability get_mut () { return mut; } + + std::unique_ptr &get_item_type () { return item_type; } + + ExternKind get_extern_kind () override { return ExternKind::Static; } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + ExternalStaticItem *clone_external_item_impl () const override + { + return new ExternalStaticItem (*this); + } +}; + +// A named function parameter used in external functions +struct NamedFunctionParam +{ +private: + Identifier name; + std::unique_ptr param_type; + Analysis::NodeMapping mappings; + +public: + bool has_name () const { return name != "_"; } + + NamedFunctionParam (Analysis::NodeMapping mappings, Identifier name, + std::unique_ptr param_type) + : name (std::move (name)), param_type (std::move (param_type)), + mappings (std::move (mappings)) + {} + + // Copy constructor + NamedFunctionParam (NamedFunctionParam const &other) + : name (other.name), param_type (other.param_type->clone_type ()), + mappings (other.mappings) + {} + + ~NamedFunctionParam () = default; + + // Overloaded assignment operator to clone + NamedFunctionParam &operator= (NamedFunctionParam const &other) + { + mappings = other.mappings; + name = other.name; + param_type = other.param_type->clone_type (); + // has_name = other.has_name; + + return *this; + } + + // move constructors + NamedFunctionParam (NamedFunctionParam &&other) = default; + NamedFunctionParam &operator= (NamedFunctionParam &&other) = default; + + std::string as_string () const; + + Identifier get_param_name () const { return name; } + + std::unique_ptr &get_type () { return param_type; } + + Analysis::NodeMapping get_mappings () const { return mappings; } +}; + +// A function item used in an extern block +class ExternalFunctionItem : public ExternalItem +{ + // bool has_generics; + // Generics generic_params; + std::vector> generic_params; // inlined + + // bool has_return_type; + // FunctionReturnType return_type; + std::unique_ptr return_type; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::vector function_params; + bool has_variadics; + +public: + // Returns whether item has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether item has a return type (otherwise void). + bool has_return_type () const { return return_type != nullptr; } + + // Returns whether item has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + ExternalFunctionItem ( + Analysis::NodeMapping mappings, Identifier item_name, + std::vector> generic_params, + std::unique_ptr return_type, WhereClause where_clause, + std::vector function_params, bool has_variadics, + Visibility vis, AST::AttrVec outer_attrs, Location locus) + : ExternalItem (std::move (mappings), std::move (item_name), + std::move (vis), std::move (outer_attrs), locus), + generic_params (std::move (generic_params)), + return_type (std::move (return_type)), + where_clause (std::move (where_clause)), + function_params (std::move (function_params)), + has_variadics (has_variadics) + {} + + // Copy constructor with clone + ExternalFunctionItem (ExternalFunctionItem const &other) + : ExternalItem (other), return_type (other.return_type->clone_type ()), + where_clause (other.where_clause), + function_params (other.function_params), + has_variadics (other.has_variadics) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + // Overloaded assignment operator with clone + ExternalFunctionItem &operator= (ExternalFunctionItem const &other) + { + ExternalItem::operator= (other); + return_type = other.return_type->clone_type (); + where_clause = other.where_clause; + function_params = other.function_params; + has_variadics = other.has_variadics; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + ExternalFunctionItem (ExternalFunctionItem &&other) = default; + ExternalFunctionItem &operator= (ExternalFunctionItem &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExternalItemVisitor &vis) override; + + std::vector> &get_generic_params () + { + return generic_params; + } + + std::unique_ptr &get_return_type () { return return_type; } + + std::vector &get_function_params () + { + return function_params; + } + + bool is_variadic () const { return has_variadics; } + + ExternKind get_extern_kind () override { return ExternKind::Function; } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + ExternalFunctionItem *clone_external_item_impl () const override + { + return new ExternalFunctionItem (*this); + } +}; + +// An extern block HIR node +class ExternBlock : public VisItem +{ + ABI abi; + AST::AttrVec inner_attrs; + std::vector> extern_items; + Location locus; + +public: + std::string as_string () const override; + + // Returns whether extern block has inner attributes. + bool has_inner_attrs () const { return !inner_attrs.empty (); } + + // Returns whether extern block has extern items. + bool has_extern_items () const { return !extern_items.empty (); } + + ABI get_abi () const { return abi; } + + ExternBlock (Analysis::NodeMapping mappings, ABI abi, + std::vector> extern_items, + Visibility vis, AST::AttrVec inner_attrs, + AST::AttrVec outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + abi (abi), inner_attrs (std::move (inner_attrs)), + extern_items (std::move (extern_items)), locus (locus) + {} + + // Copy constructor with vector clone + ExternBlock (ExternBlock const &other) + : VisItem (other), abi (other.abi), inner_attrs (other.inner_attrs), + locus (other.locus) + { + extern_items.reserve (other.extern_items.size ()); + for (const auto &e : other.extern_items) + extern_items.push_back (e->clone_external_item ()); + } + + // Overloaded assignment operator with vector clone + ExternBlock &operator= (ExternBlock const &other) + { + VisItem::operator= (other); + abi = other.abi; + inner_attrs = other.inner_attrs; + locus = other.locus; + + extern_items.reserve (other.extern_items.size ()); + for (const auto &e : other.extern_items) + extern_items.push_back (e->clone_external_item ()); + + return *this; + } + + // move constructors + ExternBlock (ExternBlock &&other) = default; + ExternBlock &operator= (ExternBlock &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + void accept_vis (HIRVisItemVisitor &vis) override; + + std::vector> &get_extern_items () + { + return extern_items; + } + + ItemKind get_item_kind () const override { return ItemKind::ExternBlock; } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + ExternBlock *clone_item_impl () const override + { + return new ExternBlock (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual ExternBlock* clone_statement_impl() const override { + return new ExternBlock(*this); + }*/ +}; + +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h new file mode 100644 index 00000000000..03cf5f5d2e8 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -0,0 +1,1013 @@ +// 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_HIR_PATH_H +#define RUST_HIR_PATH_H + +#include "rust-hir.h" + +namespace Rust { +namespace HIR { + +// The "identifier" (not generic args) aspect of each path expression segment +class PathIdentSegment +{ + std::string segment_name; + + // TODO: should this have location info stored? + + // only allow identifiers, "super", "self", "Self", "crate", or "$crate" +public: + PathIdentSegment (std::string segment_name) + : segment_name (std::move (segment_name)) + {} + + /* TODO: insert check in constructor for this? Or is this a semantic error + * best handled then? */ + + /* TODO: does this require visitor? pretty sure this isn't polymorphic, but + * not entirely sure */ + + // Creates an error PathIdentSegment. + static PathIdentSegment create_error () { return PathIdentSegment (""); } + + // Returns whether PathIdentSegment is in an error state. + bool is_error () const { return segment_name.empty (); } + + std::string as_string () const { return segment_name; } +}; + +// A binding of an identifier to a type used in generic arguments in paths +struct GenericArgsBinding +{ +private: + Identifier identifier; + std::unique_ptr type; + + Location locus; + +public: + // Returns whether binding is in an error state. + bool is_error () const + { + return type == nullptr; + // and also identifier is empty, but cheaper computation + } + + // Creates an error state generic args binding. + static GenericArgsBinding create_error () + { + return GenericArgsBinding ("", nullptr); + } + + // Pointer type for type in constructor to enable polymorphism + GenericArgsBinding (Identifier ident, std::unique_ptr type_ptr, + Location locus = Location ()) + : identifier (std::move (ident)), type (std::move (type_ptr)), locus (locus) + {} + + // Copy constructor has to deep copy the type as it is a unique pointer + GenericArgsBinding (GenericArgsBinding const &other) + : identifier (other.identifier), type (other.type->clone_type ()), + locus (other.locus) + {} + + // default destructor + ~GenericArgsBinding () = default; + + // Overload assignment operator to deep copy the pointed-to type + GenericArgsBinding &operator= (GenericArgsBinding const &other) + { + identifier = other.identifier; + type = other.type->clone_type (); + locus = other.locus; + return *this; + } + + // move constructors + GenericArgsBinding (GenericArgsBinding &&other) = default; + GenericArgsBinding &operator= (GenericArgsBinding &&other) = default; + + std::string as_string () const; + + Identifier get_identifier () const { return identifier; } + + std::unique_ptr &get_type () { return type; } + + Location get_locus () const { return locus; } +}; + +class ConstGenericArg +{ + // FIXME: Do we need to disambiguate or no? We should be able to disambiguate + // at name-resolution, hence no need for ambiguities here + +public: + ConstGenericArg (std::unique_ptr expression, Location locus) + : expression (std::move (expression)), locus (locus) + {} + + ConstGenericArg (const ConstGenericArg &other) : locus (other.locus) + { + expression = other.expression->clone_expr (); + } + + ConstGenericArg operator= (const ConstGenericArg &other) + { + expression = other.expression->clone_expr (); + locus = other.locus; + + return *this; + } + +private: + std::unique_ptr expression; + Location locus; +}; + +// Generic arguments allowed in each path expression segment - inline? +struct GenericArgs +{ + std::vector lifetime_args; + std::vector > type_args; + std::vector binding_args; + std::vector const_args; + Location locus; + +public: + // Returns true if there are any generic arguments + bool has_generic_args () const + { + return !(lifetime_args.empty () && type_args.empty () + && binding_args.empty ()); + } + + GenericArgs (std::vector lifetime_args, + std::vector > type_args, + std::vector binding_args, + std::vector const_args, Location locus) + : lifetime_args (std::move (lifetime_args)), + type_args (std::move (type_args)), + binding_args (std::move (binding_args)), + const_args (std::move (const_args)), locus (locus) + {} + + // copy constructor with vector clone + GenericArgs (GenericArgs const &other) + : lifetime_args (other.lifetime_args), binding_args (other.binding_args), + const_args (other.const_args), locus (other.locus) + { + type_args.reserve (other.type_args.size ()); + + for (const auto &e : other.type_args) + type_args.push_back (e->clone_type ()); + } + + ~GenericArgs () = default; + + // overloaded assignment operator to vector clone + GenericArgs &operator= (GenericArgs const &other) + { + lifetime_args = other.lifetime_args; + binding_args = other.binding_args; + const_args = other.const_args; + locus = other.locus; + + type_args.reserve (other.type_args.size ()); + for (const auto &e : other.type_args) + type_args.push_back (e->clone_type ()); + + return *this; + } + + // move constructors + GenericArgs (GenericArgs &&other) = default; + GenericArgs &operator= (GenericArgs &&other) = default; + + // Creates an empty GenericArgs (no arguments) + static GenericArgs create_empty (Location locus = Location ()) + { + return GenericArgs ({}, {}, {}, {}, locus); + } + + bool is_empty () const + { + return lifetime_args.size () == 0 && type_args.size () == 0 + && binding_args.size () == 0; + } + + std::string as_string () const; + + std::vector &get_lifetime_args () { return lifetime_args; } + + std::vector > &get_type_args () { return type_args; } + + std::vector &get_binding_args () { return binding_args; } + + std::vector &get_const_args () { return const_args; } + + Location get_locus () const { return locus; } +}; + +/* A segment of a path in expression, including an identifier aspect and maybe + * generic args */ +class PathExprSegment +{ +private: + Analysis::NodeMapping mappings; + PathIdentSegment segment_name; + GenericArgs generic_args; + Location locus; + +public: + // Returns true if there are any generic arguments + bool has_generic_args () const { return generic_args.has_generic_args (); } + + // Constructor for segment (from IdentSegment and GenericArgs) + PathExprSegment (Analysis::NodeMapping mappings, + PathIdentSegment segment_name, Location locus = Location (), + GenericArgs generic_args = GenericArgs::create_empty ()) + : mappings (std::move (mappings)), segment_name (std::move (segment_name)), + generic_args (std::move (generic_args)), locus (locus) + {} + + std::string as_string () const; + + Location get_locus () const { return locus; } + + PathIdentSegment get_segment () const { return segment_name; } + + GenericArgs &get_generic_args () { return generic_args; } + + const Analysis::NodeMapping &get_mappings () const { return mappings; } +}; + +// HIR node representing a pattern that involves a "path" - abstract base class +class PathPattern : public Pattern +{ + std::vector segments; + +protected: + PathPattern (std::vector segments) + : segments (std::move (segments)) + {} + + // Returns whether path has segments. + bool has_segments () const { return !segments.empty (); } + + /* Converts path segments to their equivalent SimplePath segments if possible, + * and creates a SimplePath from them. */ + AST::SimplePath + convert_to_simple_path (bool with_opening_scope_resolution) const; + +public: + /* Returns whether the path is a single segment (excluding qualified path + * initial as segment). */ + bool is_single_segment () const { return segments.size () == 1; } + + std::string as_string () const override; + + void iterate_path_segments (std::function cb) + { + for (auto it = segments.begin (); it != segments.end (); it++) + { + if (!cb (*it)) + return; + } + } + + size_t get_num_segments () const { return segments.size (); } + + std::vector &get_segments () { return segments; } + + const std::vector &get_segments () const { return segments; } + + PathExprSegment &get_root_seg () { return segments.at (0); } + + PathExprSegment get_final_segment () const { return segments.back (); } + + PatternType get_pattern_type () const override final + { + return PatternType::PATH; + } +}; + +/* HIR node representing a path-in-expression pattern (path that allows generic + * arguments) */ +class PathInExpression : public PathPattern, public PathExpr +{ + bool has_opening_scope_resolution; + Location locus; + +public: + std::string as_string () const override; + + // Constructor + PathInExpression (Analysis::NodeMapping mappings, + std::vector path_segments, + Location locus = Location (), + bool has_opening_scope_resolution = false, + std::vector outer_attrs + = std::vector ()) + : PathPattern (std::move (path_segments)), + PathExpr (std::move (mappings), std::move (outer_attrs)), + has_opening_scope_resolution (has_opening_scope_resolution), locus (locus) + {} + + // Creates an error state path in expression. + static PathInExpression create_error () + { + return PathInExpression (Analysis::NodeMapping::get_error (), + std::vector ()); + } + + // Returns whether path in expression is in an error state. + bool is_error () const { return !has_segments (); } + + /* Converts PathInExpression to SimplePath if possible (i.e. no generic + * arguments). Otherwise returns an empty SimplePath. */ + AST::SimplePath as_simple_path () const + { + /* delegate to parent class as can't access segments. however, + * QualifiedPathInExpression conversion to simple path wouldn't make sense, + * so the method in the parent class should be protected, not public. Have + * to pass in opening scope resolution as parent class has no access to it. + */ + return convert_to_simple_path (has_opening_scope_resolution); + } + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + void accept_vis (HIRPatternVisitor &vis) override; + + bool opening_scope_resolution () { return has_opening_scope_resolution; } + + bool is_self () const + { + if (!is_single_segment ()) + return false; + + return get_final_segment ().get_segment ().as_string ().compare ("self") + == 0; + } + + Analysis::NodeMapping get_pattern_mappings () const override final + { + return get_mappings (); + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + PathInExpression *clone_pattern_impl () const override + { + return new PathInExpression (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + PathInExpression *clone_expr_without_block_impl () const override + { + return new PathInExpression (*this); + } +}; + +/* Base class for segments used in type paths - not abstract (represents an + * ident-only segment) */ +class TypePathSegment +{ +public: + enum SegmentType + { + REG, + GENERIC, + FUNCTION + }; + +private: + Analysis::NodeMapping mappings; + PathIdentSegment ident_segment; + Location locus; + +protected: + bool has_separating_scope_resolution; + SegmentType type; + + // Clone function implementation - not pure virtual as overrided by subclasses + virtual TypePathSegment *clone_type_path_segment_impl () const + { + return new TypePathSegment (*this); + } + +public: + virtual ~TypePathSegment () {} + + virtual SegmentType get_type () const { return SegmentType::REG; } + + // Unique pointer custom clone function + std::unique_ptr clone_type_path_segment () const + { + return std::unique_ptr (clone_type_path_segment_impl ()); + } + + TypePathSegment (Analysis::NodeMapping mappings, + PathIdentSegment ident_segment, + bool has_separating_scope_resolution, Location locus) + : mappings (std::move (mappings)), + ident_segment (std::move (ident_segment)), locus (locus), + has_separating_scope_resolution (has_separating_scope_resolution), + type (SegmentType::REG) + {} + + TypePathSegment (Analysis::NodeMapping mappings, std::string segment_name, + bool has_separating_scope_resolution, Location locus) + : mappings (std::move (mappings)), + ident_segment (PathIdentSegment (std::move (segment_name))), + locus (locus), + has_separating_scope_resolution (has_separating_scope_resolution), + type (SegmentType::REG) + {} + + virtual std::string as_string () const { return ident_segment.as_string (); } + + /* Returns whether the type path segment is in an error state. May be virtual + * in future. */ + bool is_error () const { return ident_segment.is_error (); } + + /* Returns whether segment is identifier only (as opposed to generic args or + * function). Overriden in derived classes with other segments. */ + virtual bool is_ident_only () const { return true; } + + Location get_locus () const { return locus; } + + // not pure virtual as class not abstract + virtual void accept_vis (HIRFullVisitor &vis); + + const Analysis::NodeMapping &get_mappings () const { return mappings; } + + const PathIdentSegment &get_ident_segment () const { return ident_segment; } + + bool is_generic_segment () const + { + return get_type () == SegmentType::GENERIC; + } +}; + +// Segment used in type path with generic args +class TypePathSegmentGeneric : public TypePathSegment +{ + GenericArgs generic_args; + +public: + bool has_generic_args () const { return generic_args.has_generic_args (); } + + bool is_ident_only () const override { return false; } + + // Constructor with PathIdentSegment and GenericArgs + TypePathSegmentGeneric (Analysis::NodeMapping mappings, + PathIdentSegment ident_segment, + bool has_separating_scope_resolution, + GenericArgs generic_args, Location locus) + : TypePathSegment (std::move (mappings), std::move (ident_segment), + has_separating_scope_resolution, locus), + generic_args (std::move (generic_args)) + {} + + // Constructor from segment name and all args + TypePathSegmentGeneric (Analysis::NodeMapping mappings, + std::string segment_name, + bool has_separating_scope_resolution, + std::vector lifetime_args, + std::vector > type_args, + std::vector binding_args, + std::vector const_args, + Location locus) + : TypePathSegment (std::move (mappings), std::move (segment_name), + has_separating_scope_resolution, locus), + generic_args ( + GenericArgs (std::move (lifetime_args), std::move (type_args), + std::move (binding_args), std::move (const_args), locus)) + {} + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + GenericArgs &get_generic_args () { return generic_args; } + + virtual SegmentType get_type () const override final + { + return SegmentType::GENERIC; + } + +protected: + // Use covariance to override base class method + TypePathSegmentGeneric *clone_type_path_segment_impl () const override + { + return new TypePathSegmentGeneric (*this); + } +}; + +// A function as represented in a type path +struct TypePathFunction +{ +private: + // TODO: remove + /*bool has_inputs; + TypePathFnInputs inputs;*/ + // inlined from TypePathFnInputs + std::vector > inputs; + + // bool has_type; + std::unique_ptr return_type; + + // FIXME: think of better way to mark as invalid than taking up storage + bool is_invalid; + + // TODO: should this have location info? + +protected: + // Constructor only used to create invalid type path functions. + TypePathFunction (bool is_invalid) : is_invalid (is_invalid) {} + +public: + // Returns whether the return type of the function has been specified. + bool has_return_type () const { return return_type != nullptr; } + + // Returns whether the function has inputs. + bool has_inputs () const { return !inputs.empty (); } + + // Returns whether function is in an error state. + bool is_error () const { return is_invalid; } + + // Creates an error state function. + static TypePathFunction create_error () { return TypePathFunction (true); } + + // Constructor + TypePathFunction (std::vector > inputs, + Type *type = nullptr) + : inputs (std::move (inputs)), return_type (type), is_invalid (false) + {} + // FIXME: deprecated + + // Constructor + TypePathFunction (std::vector > inputs, + std::unique_ptr type = nullptr) + : inputs (std::move (inputs)), return_type (std::move (type)), + is_invalid (false) + {} + + // Copy constructor with clone + TypePathFunction (TypePathFunction const &other) + : return_type (other.return_type->clone_type ()), + is_invalid (other.is_invalid) + { + inputs.reserve (other.inputs.size ()); + for (const auto &e : other.inputs) + inputs.push_back (e->clone_type ()); + } + + ~TypePathFunction () = default; + + // Overloaded assignment operator to clone type + TypePathFunction &operator= (TypePathFunction const &other) + { + return_type = other.return_type->clone_type (); + is_invalid = other.is_invalid; + + inputs.reserve (other.inputs.size ()); + for (const auto &e : other.inputs) + inputs.push_back (e->clone_type ()); + + return *this; + } + + // move constructors + TypePathFunction (TypePathFunction &&other) = default; + TypePathFunction &operator= (TypePathFunction &&other) = default; + + std::string as_string () const; +}; + +// Segment used in type path with a function argument +class TypePathSegmentFunction : public TypePathSegment +{ + TypePathFunction function_path; + +public: + // Constructor with PathIdentSegment and TypePathFn + TypePathSegmentFunction (Analysis::NodeMapping mappings, + PathIdentSegment ident_segment, + bool has_separating_scope_resolution, + TypePathFunction function_path, Location locus) + : TypePathSegment (std::move (mappings), std::move (ident_segment), + has_separating_scope_resolution, locus), + function_path (std::move (function_path)) + {} + + // Constructor with segment name and TypePathFn + TypePathSegmentFunction (Analysis::NodeMapping mappings, + std::string segment_name, + bool has_separating_scope_resolution, + TypePathFunction function_path, Location locus) + : TypePathSegment (std::move (mappings), std::move (segment_name), + has_separating_scope_resolution, locus), + function_path (std::move (function_path)) + {} + + std::string as_string () const override; + + bool is_ident_only () const override { return false; } + + void accept_vis (HIRFullVisitor &vis) override; + + virtual SegmentType get_type () const override final + { + return SegmentType::FUNCTION; + } + +protected: + // Use covariance to override base class method + TypePathSegmentFunction *clone_type_path_segment_impl () const override + { + return new TypePathSegmentFunction (*this); + } +}; + +// Path used inside types +class TypePath : public TypeNoBounds +{ +public: + bool has_opening_scope_resolution; + std::vector > segments; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TypePath *clone_type_impl () const override { return new TypePath (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + TypePath *clone_type_no_bounds_impl () const override + { + return new TypePath (*this); + } + +public: + /* Returns whether the TypePath has an opening scope resolution operator (i.e. + * is global path or crate-relative path, not module-relative) */ + bool has_opening_scope_resolution_op () const + { + return has_opening_scope_resolution; + } + + // Returns whether the TypePath is in an invalid state. + bool is_error () const { return segments.empty (); } + + // Creates an error state TypePath. + static TypePath create_error () + { + return TypePath (Analysis::NodeMapping::get_error (), + std::vector > (), + Location ()); + } + + // Constructor + TypePath (Analysis::NodeMapping mappings, + std::vector > segments, + Location locus, bool has_opening_scope_resolution = false) + : TypeNoBounds (mappings, locus), + has_opening_scope_resolution (has_opening_scope_resolution), + segments (std::move (segments)) + {} + + // Copy constructor with vector clone + TypePath (TypePath const &other) + : TypeNoBounds (other.mappings, other.locus), + has_opening_scope_resolution (other.has_opening_scope_resolution) + { + segments.reserve (other.segments.size ()); + for (const auto &e : other.segments) + segments.push_back (e->clone_type_path_segment ()); + } + + // Overloaded assignment operator with clone + TypePath &operator= (TypePath const &other) + { + has_opening_scope_resolution = other.has_opening_scope_resolution; + locus = other.locus; + mappings = other.mappings; + + segments.reserve (other.segments.size ()); + for (const auto &e : other.segments) + segments.push_back (e->clone_type_path_segment ()); + + return *this; + } + + // move constructors + TypePath (TypePath &&other) = default; + TypePath &operator= (TypePath &&other) = default; + + std::string as_string () const override; + + /* Converts TypePath to SimplePath if possible (i.e. no generic or function + * arguments). Otherwise returns an empty SimplePath. */ + AST::SimplePath as_simple_path () const; + + // Creates a trait bound with a clone of this type path as its only element. + TraitBound *to_trait_bound (bool in_parens) const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; + + size_t get_num_segments () const { return segments.size (); } + + std::vector > &get_segments () + { + return segments; + } + + std::unique_ptr &get_final_segment () + { + return segments.back (); + } +}; + +struct QualifiedPathType +{ +private: + std::unique_ptr type; + std::unique_ptr trait; + Location locus; + Analysis::NodeMapping mappings; + +public: + // Constructor + QualifiedPathType (Analysis::NodeMapping mappings, std::unique_ptr type, + std::unique_ptr trait, Location locus) + : type (std::move (type)), trait (std::move (trait)), locus (locus), + mappings (mappings) + {} + + // Copy constructor uses custom deep copy for Type to preserve polymorphism + QualifiedPathType (QualifiedPathType const &other) + : type (other.type->clone_type ()), + trait (other.has_as_clause () ? std::unique_ptr ( + new HIR::TypePath (*other.trait)) + : nullptr), + locus (other.locus), mappings (other.mappings) + {} + + // default destructor + ~QualifiedPathType () = default; + + // overload assignment operator to use custom clone method + QualifiedPathType &operator= (QualifiedPathType const &other) + { + type = other.type->clone_type (); + locus = other.locus; + mappings = other.mappings; + trait + = other.has_as_clause () + ? std::unique_ptr (new HIR::TypePath (*other.trait)) + : nullptr; + + return *this; + } + + // move constructor + QualifiedPathType (QualifiedPathType &&other) = default; + QualifiedPathType &operator= (QualifiedPathType &&other) = default; + + // Returns whether the qualified path type has a rebind as clause. + bool has_as_clause () const { return trait != nullptr; } + + std::string as_string () const; + + Location get_locus () const { return locus; } + + Analysis::NodeMapping get_mappings () const { return mappings; } + + std::unique_ptr &get_type () { return type; } + + std::unique_ptr &get_trait () + { + rust_assert (has_as_clause ()); + return trait; + } + + bool trait_has_generic_args () const + { + rust_assert (has_as_clause ()); + bool is_generic_seg = trait->get_final_segment ()->get_type () + == TypePathSegment::SegmentType::GENERIC; + if (!is_generic_seg) + return false; + + TypePathSegmentGeneric *seg = static_cast ( + trait->get_final_segment ().get ()); + return seg->has_generic_args (); + } + + GenericArgs &get_trait_generic_args () + { + rust_assert (trait_has_generic_args ()); + TypePathSegmentGeneric *seg = static_cast ( + trait->get_final_segment ().get ()); + return seg->get_generic_args (); + } +}; + +/* HIR node representing a qualified path-in-expression pattern (path that + * allows specifying trait functions) */ +class QualifiedPathInExpression : public PathPattern, public PathExpr +{ + QualifiedPathType path_type; + Location locus; + +public: + std::string as_string () const override; + + QualifiedPathInExpression (Analysis::NodeMapping mappings, + QualifiedPathType qual_path_type, + std::vector path_segments, + Location locus = Location (), + std::vector outer_attrs + = std::vector ()) + : PathPattern (std::move (path_segments)), + PathExpr (std::move (mappings), std::move (outer_attrs)), + path_type (std::move (qual_path_type)), locus (locus) + {} + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + void accept_vis (HIRPatternVisitor &vis) override; + + QualifiedPathType &get_path_type () { return path_type; } + + Location get_locus () { return locus; } + + Analysis::NodeMapping get_pattern_mappings () const override final + { + return get_mappings (); + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + QualifiedPathInExpression *clone_pattern_impl () const override + { + return new QualifiedPathInExpression (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + QualifiedPathInExpression *clone_expr_without_block_impl () const override + { + return new QualifiedPathInExpression (*this); + } +}; + +/* Represents a qualified path in a type; used for disambiguating trait function + * calls */ +class QualifiedPathInType : public TypeNoBounds +{ + QualifiedPathType path_type; + std::unique_ptr associated_segment; + std::vector > segments; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + QualifiedPathInType *clone_type_impl () const override + { + return new QualifiedPathInType (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + QualifiedPathInType *clone_type_no_bounds_impl () const override + { + return new QualifiedPathInType (*this); + } + +public: + QualifiedPathInType ( + Analysis::NodeMapping mappings, QualifiedPathType qual_path_type, + std::unique_ptr associated_segment, + std::vector > path_segments, + Location locus = Location ()) + : TypeNoBounds (mappings, locus), path_type (std::move (qual_path_type)), + associated_segment (std::move (associated_segment)), + segments (std::move (path_segments)) + {} + + /* TODO: maybe make a shortcut constructor that has QualifiedPathType elements + * as params */ + + // Copy constructor with vector clone + QualifiedPathInType (QualifiedPathInType const &other) + : TypeNoBounds (other.mappings, other.locus), path_type (other.path_type) + { + segments.reserve (other.segments.size ()); + for (const auto &e : other.segments) + segments.push_back (e->clone_type_path_segment ()); + + // Untested. + gcc_unreachable (); + } + + // Overloaded assignment operator with vector clone + QualifiedPathInType &operator= (QualifiedPathInType const &other) + { + path_type = other.path_type; + locus = other.locus; + mappings = other.mappings; + + segments.reserve (other.segments.size ()); + for (const auto &e : other.segments) + segments.push_back (e->clone_type_path_segment ()); + + return *this; + } + + // move constructors + QualifiedPathInType (QualifiedPathInType &&other) = default; + QualifiedPathInType &operator= (QualifiedPathInType &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; + + QualifiedPathType &get_path_type () { return path_type; } + + std::unique_ptr &get_associated_segment () + { + return associated_segment; + } + + std::vector > &get_segments () + { + return segments; + } +}; + +class SimplePathSegment +{ + Analysis::NodeMapping mappings; + +public: + SimplePathSegment (Analysis::NodeMapping mappings) : mappings (mappings) {} + + const Analysis::NodeMapping &get_mappings () const { return mappings; } +}; + +class SimplePath +{ + std::vector segments; + Analysis::NodeMapping mappings; + Location locus; + +public: + SimplePath (std::vector segments, + Analysis::NodeMapping mappings, Location locus) + : segments (std::move (segments)), mappings (mappings), locus (locus) + {} + + static HIR::SimplePath create_empty () + { + return HIR::SimplePath ({}, Analysis::NodeMapping::get_error (), + Location ()); + } + + bool is_error () const { return segments.empty (); } + + const Analysis::NodeMapping &get_mappings () const { return mappings; } + const Location &get_locus () const { return locus; } +}; + +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h new file mode 100644 index 00000000000..7129b5a3684 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-pattern.h @@ -0,0 +1,1356 @@ +// 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_HIR_PATTERN_H +#define RUST_HIR_PATTERN_H + +#include "rust-common.h" +#include "rust-hir.h" + +namespace Rust { +namespace HIR { + +// Literal pattern HIR node (comparing to a literal) +class LiteralPattern : public Pattern +{ + Literal lit; + Location locus; + Analysis::NodeMapping mappings; + +public: + std::string as_string () const override; + + // Constructor for a literal pattern + LiteralPattern (Analysis::NodeMapping mappings, Literal lit, Location locus) + : lit (std::move (lit)), locus (locus), mappings (mappings) + {} + + LiteralPattern (Analysis::NodeMapping mappings, std::string val, + Literal::LitType type, Location locus) + : lit (Literal (std::move (val), type, PrimitiveCoreType::CORETYPE_STR)), + locus (locus), mappings (mappings) + {} + + Location get_locus () const override { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRPatternVisitor &vis) override; + + Analysis::NodeMapping get_pattern_mappings () const override final + { + return mappings; + } + + PatternType get_pattern_type () const override final + { + return PatternType::LITERAL; + } + + Literal &get_literal () { return lit; } + const Literal &get_literal () const { return lit; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + virtual LiteralPattern *clone_pattern_impl () const override + { + return new LiteralPattern (*this); + } +}; + +// Identifier pattern HIR node (bind value matched to a variable) +class IdentifierPattern : public Pattern +{ + Identifier variable_ident; + bool is_ref; + Mutability mut; + std::unique_ptr to_bind; + Location locus; + Analysis::NodeMapping mappings; + +public: + std::string as_string () const override; + + // Returns whether the IdentifierPattern has a pattern to bind. + bool has_pattern_to_bind () const { return to_bind != nullptr; } + + // Constructor + IdentifierPattern (Analysis::NodeMapping mappings, Identifier ident, + Location locus, bool is_ref = false, + Mutability mut = Mutability::Imm, + std::unique_ptr to_bind = nullptr) + : variable_ident (std::move (ident)), is_ref (is_ref), mut (mut), + to_bind (std::move (to_bind)), locus (locus), mappings (mappings) + {} + + // Copy constructor with clone + IdentifierPattern (IdentifierPattern const &other) + : variable_ident (other.variable_ident), is_ref (other.is_ref), + mut (other.mut), locus (other.locus), mappings (other.mappings) + { + // fix to get prevent null pointer dereference + if (other.to_bind != nullptr) + to_bind = other.to_bind->clone_pattern (); + } + + // Overload assignment operator to use clone + IdentifierPattern &operator= (IdentifierPattern const &other) + { + variable_ident = other.variable_ident; + is_ref = other.is_ref; + mut = other.mut; + locus = other.locus; + mappings = other.mappings; + + // fix to get prevent null pointer dereference + if (other.to_bind != nullptr) + to_bind = other.to_bind->clone_pattern (); + + return *this; + } + + // default move semantics + IdentifierPattern (IdentifierPattern &&other) = default; + IdentifierPattern &operator= (IdentifierPattern &&other) = default; + + Location get_locus () const override { return locus; } + + bool is_mut () const { return mut == Mutability::Mut; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRPatternVisitor &vis) override; + + Analysis::NodeMapping get_pattern_mappings () const override final + { + return mappings; + } + + Identifier get_identifier () const { return variable_ident; } + + PatternType get_pattern_type () const override final + { + return PatternType::IDENTIFIER; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IdentifierPattern *clone_pattern_impl () const override + { + return new IdentifierPattern (*this); + } +}; + +// HIR node for using the '_' wildcard "match any value" pattern +class WildcardPattern : public Pattern +{ + Location locus; + Analysis::NodeMapping mappings; + +public: + std::string as_string () const override { return std::string (1, '_'); } + + WildcardPattern (Analysis::NodeMapping mappings, Location locus) + : locus (locus), mappings (mappings) + {} + + Location get_locus () const override { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRPatternVisitor &vis) override; + + Analysis::NodeMapping get_pattern_mappings () const override final + { + return mappings; + } + + PatternType get_pattern_type () const override final + { + return PatternType::WILDCARD; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + WildcardPattern *clone_pattern_impl () const override + { + return new WildcardPattern (*this); + } +}; + +// Base range pattern bound (lower or upper limit) - abstract +class RangePatternBound +{ +public: + enum RangePatternBoundType + { + LITERAL, + PATH, + QUALPATH + }; + + virtual ~RangePatternBound () {} + + // Unique pointer custom clone function + std::unique_ptr clone_range_pattern_bound () const + { + return std::unique_ptr ( + clone_range_pattern_bound_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (HIRFullVisitor &vis) = 0; + + virtual RangePatternBoundType get_bound_type () const = 0; + +protected: + // pure virtual as RangePatternBound is abstract + virtual RangePatternBound *clone_range_pattern_bound_impl () const = 0; +}; + +// Literal-based pattern bound +class RangePatternBoundLiteral : public RangePatternBound +{ + Literal literal; + /* Can only be a char, byte, int, or float literal - same impl here as + * previously */ + + // Minus prefixed to literal (if integer or floating-point) + bool has_minus; + + Location locus; + +public: + // Constructor + RangePatternBoundLiteral (Literal literal, Location locus, + bool has_minus = false) + : literal (literal), has_minus (has_minus), locus (locus) + {} + + std::string as_string () const override; + + Location get_locus () const { return locus; } + + Literal get_literal () const { return literal; } + + void accept_vis (HIRFullVisitor &vis) override; + + RangePatternBoundType get_bound_type () const override + { + return RangePatternBoundType::LITERAL; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangePatternBoundLiteral *clone_range_pattern_bound_impl () const override + { + return new RangePatternBoundLiteral (*this); + } +}; + +// Path-based pattern bound +class RangePatternBoundPath : public RangePatternBound +{ + PathInExpression path; + + /* TODO: should this be refactored so that PathInExpression is a subclass of + * RangePatternBound? */ + +public: + RangePatternBoundPath (PathInExpression path) : path (std::move (path)) {} + + std::string as_string () const override { return path.as_string (); } + + Location get_locus () const { return path.get_locus (); } + + PathInExpression &get_path () { return path; } + const PathInExpression &get_path () const { return path; } + + void accept_vis (HIRFullVisitor &vis) override; + + RangePatternBoundType get_bound_type () const override + { + return RangePatternBoundType::PATH; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangePatternBoundPath *clone_range_pattern_bound_impl () const override + { + return new RangePatternBoundPath (*this); + } +}; + +// Qualified path-based pattern bound +class RangePatternBoundQualPath : public RangePatternBound +{ + QualifiedPathInExpression path; + + /* TODO: should this be refactored so that QualifiedPathInExpression is a + * subclass of RangePatternBound? */ + +public: + RangePatternBoundQualPath (QualifiedPathInExpression path) + : path (std::move (path)) + {} + + std::string as_string () const override { return path.as_string (); } + + Location get_locus () const { return path.get_locus (); } + + void accept_vis (HIRFullVisitor &vis) override; + + QualifiedPathInExpression &get_qualified_path () { return path; } + const QualifiedPathInExpression &get_qualified_path () const { return path; } + + RangePatternBoundType get_bound_type () const override + { + return RangePatternBoundType::QUALPATH; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangePatternBoundQualPath *clone_range_pattern_bound_impl () const override + { + return new RangePatternBoundQualPath (*this); + } +}; + +// HIR node for matching within a certain range (range pattern) +class RangePattern : public Pattern +{ + std::unique_ptr lower; + std::unique_ptr upper; + + bool has_ellipsis_syntax; + + /* location only stored to avoid a dereference - lower pattern should give + * correct location so maybe change in future */ + Location locus; + Analysis::NodeMapping mappings; + +public: + std::string as_string () const override; + + // Constructor + RangePattern (Analysis::NodeMapping mappings, + std::unique_ptr lower, + std::unique_ptr upper, Location locus, + bool has_ellipsis_syntax = false) + : lower (std::move (lower)), upper (std::move (upper)), + has_ellipsis_syntax (has_ellipsis_syntax), locus (locus), + mappings (mappings) + {} + + // Copy constructor with clone + RangePattern (RangePattern const &other) + : lower (other.lower->clone_range_pattern_bound ()), + upper (other.upper->clone_range_pattern_bound ()), + has_ellipsis_syntax (other.has_ellipsis_syntax), locus (other.locus), + mappings (other.mappings) + {} + + // Overloaded assignment operator to clone + RangePattern &operator= (RangePattern const &other) + { + lower = other.lower->clone_range_pattern_bound (); + upper = other.upper->clone_range_pattern_bound (); + has_ellipsis_syntax = other.has_ellipsis_syntax; + locus = other.locus; + mappings = other.mappings; + + return *this; + } + + // default move semantics + RangePattern (RangePattern &&other) = default; + RangePattern &operator= (RangePattern &&other) = default; + + Location get_locus () const override { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRPatternVisitor &vis) override; + + Analysis::NodeMapping get_pattern_mappings () const override final + { + return mappings; + } + + PatternType get_pattern_type () const override final + { + return PatternType::RANGE; + } + + std::unique_ptr &get_lower_bound () + { + rust_assert (lower != nullptr); + return lower; + } + + std::unique_ptr &get_upper_bound () + { + rust_assert (upper != nullptr); + return upper; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangePattern *clone_pattern_impl () const override + { + return new RangePattern (*this); + } +}; + +// HIR node for pattern based on dereferencing the pointers given +class ReferencePattern : public Pattern +{ + bool has_two_amps; + Mutability mut; + std::unique_ptr pattern; + Location locus; + Analysis::NodeMapping mappings; + +public: + std::string as_string () const override; + + ReferencePattern (Analysis::NodeMapping mappings, + std::unique_ptr pattern, Mutability reference_mut, + bool ref_has_two_amps, Location locus) + : has_two_amps (ref_has_two_amps), mut (reference_mut), + pattern (std::move (pattern)), locus (locus), mappings (mappings) + {} + + // Copy constructor requires clone + ReferencePattern (ReferencePattern const &other) + : has_two_amps (other.has_two_amps), mut (other.mut), + pattern (other.pattern->clone_pattern ()), locus (other.locus), + mappings (other.mappings) + {} + + // Overload assignment operator to clone + ReferencePattern &operator= (ReferencePattern const &other) + { + pattern = other.pattern->clone_pattern (); + mut = other.mut; + has_two_amps = other.has_two_amps; + locus = other.locus; + mappings = other.mappings; + + return *this; + } + + // default move semantics + ReferencePattern (ReferencePattern &&other) = default; + ReferencePattern &operator= (ReferencePattern &&other) = default; + + bool is_mut () const { return mut == Mutability::Mut; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRPatternVisitor &vis) override; + + Analysis::NodeMapping get_pattern_mappings () const override final + { + return mappings; + } + + Location get_locus () const override final { return locus; } + + PatternType get_pattern_type () const override final + { + return PatternType::REFERENCE; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ReferencePattern *clone_pattern_impl () const override + { + return new ReferencePattern (*this); + } +}; + +// Base class for a single field in a struct pattern - abstract +class StructPatternField +{ + AST::AttrVec outer_attrs; + Location locus; + Analysis::NodeMapping mappings; + +public: + enum ItemType + { + TUPLE_PAT, + IDENT_PAT, + IDENT + }; + + virtual ~StructPatternField () {} + + // Unique pointer custom clone function + std::unique_ptr clone_struct_pattern_field () const + { + return std::unique_ptr ( + clone_struct_pattern_field_impl ()); + } + + virtual std::string as_string () const; + virtual void accept_vis (HIRFullVisitor &vis) = 0; + virtual ItemType get_item_type () const = 0; + + Location get_locus () const { return locus; } + Analysis::NodeMapping get_mappings () const { return mappings; }; + +protected: + StructPatternField (Analysis::NodeMapping mappings, + AST::AttrVec outer_attribs, Location locus) + : outer_attrs (std::move (outer_attribs)), locus (locus), + mappings (mappings) + {} + + // Clone function implementation as pure virtual method + virtual StructPatternField *clone_struct_pattern_field_impl () const = 0; +}; + +// Tuple pattern single field in a struct pattern +class StructPatternFieldTuplePat : public StructPatternField +{ + TupleIndex index; + std::unique_ptr tuple_pattern; + +public: + StructPatternFieldTuplePat (Analysis::NodeMapping mappings, TupleIndex index, + std::unique_ptr tuple_pattern, + AST::AttrVec outer_attribs, Location locus) + : StructPatternField (mappings, std::move (outer_attribs), locus), + index (index), tuple_pattern (std::move (tuple_pattern)) + {} + + // Copy constructor requires clone + StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other) + : StructPatternField (other), index (other.index), + tuple_pattern (other.tuple_pattern->clone_pattern ()) + {} + + // Overload assignment operator to perform clone + StructPatternFieldTuplePat & + operator= (StructPatternFieldTuplePat const &other) + { + StructPatternField::operator= (other); + tuple_pattern = other.tuple_pattern->clone_pattern (); + index = other.index; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // default move semantics + StructPatternFieldTuplePat (StructPatternFieldTuplePat &&other) = default; + StructPatternFieldTuplePat &operator= (StructPatternFieldTuplePat &&other) + = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructPatternFieldTuplePat *clone_struct_pattern_field_impl () const override + { + return new StructPatternFieldTuplePat (*this); + } +}; + +// Identifier pattern single field in a struct pattern +class StructPatternFieldIdentPat : public StructPatternField +{ + Identifier ident; + std::unique_ptr ident_pattern; + +public: + StructPatternFieldIdentPat (Analysis::NodeMapping mappings, Identifier ident, + std::unique_ptr ident_pattern, + AST::AttrVec outer_attrs, Location locus) + : StructPatternField (mappings, std::move (outer_attrs), locus), + ident (std::move (ident)), ident_pattern (std::move (ident_pattern)) + {} + + // Copy constructor requires clone + StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other) + : StructPatternField (other), ident (other.ident), + ident_pattern (other.ident_pattern->clone_pattern ()) + {} + + // Overload assignment operator to clone + StructPatternFieldIdentPat & + operator= (StructPatternFieldIdentPat const &other) + { + StructPatternField::operator= (other); + ident = other.ident; + ident_pattern = other.ident_pattern->clone_pattern (); + // outer_attrs = other.outer_attrs; + + return *this; + } + + // default move semantics + StructPatternFieldIdentPat (StructPatternFieldIdentPat &&other) = default; + StructPatternFieldIdentPat &operator= (StructPatternFieldIdentPat &&other) + = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + ItemType get_item_type () const override final { return ItemType::IDENT_PAT; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructPatternFieldIdentPat *clone_struct_pattern_field_impl () const override + { + return new StructPatternFieldIdentPat (*this); + } +}; + +// Identifier only (with no pattern) single field in a struct pattern +class StructPatternFieldIdent : public StructPatternField +{ + bool has_ref; + Mutability mut; + Identifier ident; + +public: + StructPatternFieldIdent (Analysis::NodeMapping mappings, Identifier ident, + bool is_ref, Mutability mut, + AST::AttrVec outer_attrs, Location locus) + : StructPatternField (mappings, std::move (outer_attrs), locus), + has_ref (is_ref), mut (mut), ident (std::move (ident)) + {} + + std::string as_string () const override; + + bool is_mut () const { return mut == Mutability::Mut; } + + void accept_vis (HIRFullVisitor &vis) override; + + ItemType get_item_type () const override final { return ItemType::IDENT; } + + Identifier get_identifier () const { return ident; }; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructPatternFieldIdent *clone_struct_pattern_field_impl () const override + { + return new StructPatternFieldIdent (*this); + } +}; + +// Elements of a struct pattern +struct StructPatternElements +{ +private: + std::vector > fields; + +public: + // Returns whether there are any struct pattern fields + bool has_struct_pattern_fields () const { return !fields.empty (); } + + /* Returns whether the struct pattern elements is entirely empty (no fields, + * no etc). */ + bool is_empty () const { return !has_struct_pattern_fields (); } + + // Constructor for StructPatternElements with both (potentially) + StructPatternElements ( + std::vector > fields) + : fields (std::move (fields)) + {} + + // Copy constructor with vector clone + StructPatternElements (StructPatternElements const &other) + { + fields.reserve (other.fields.size ()); + for (const auto &e : other.fields) + fields.push_back (e->clone_struct_pattern_field ()); + } + + // Overloaded assignment operator with vector clone + StructPatternElements &operator= (StructPatternElements const &other) + { + fields.reserve (other.fields.size ()); + for (const auto &e : other.fields) + fields.push_back (e->clone_struct_pattern_field ()); + + return *this; + } + + // move constructors + StructPatternElements (StructPatternElements &&other) = default; + StructPatternElements &operator= (StructPatternElements &&other) = default; + + // Creates an empty StructPatternElements + static StructPatternElements create_empty () + { + return StructPatternElements ( + std::vector > ()); + } + + std::string as_string () const; + + std::vector > & + get_struct_pattern_fields () + { + return fields; + } +}; + +// Struct pattern HIR node representation +class StructPattern : public Pattern +{ + PathInExpression path; + StructPatternElements elems; + Analysis::NodeMapping mappings; + +public: + std::string as_string () const override; + + StructPattern (Analysis::NodeMapping mappings, PathInExpression struct_path, + StructPatternElements elems) + : path (std::move (struct_path)), elems (std::move (elems)), + mappings (mappings) + {} + + bool has_struct_pattern_elems () const { return !elems.is_empty (); } + + Location get_locus () const override { return path.get_locus (); } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRPatternVisitor &vis) override; + + PathInExpression &get_path () { return path; } + StructPatternElements &get_struct_pattern_elems () { return elems; } + + Analysis::NodeMapping get_pattern_mappings () const override final + { + return mappings; + } + + PatternType get_pattern_type () const override final + { + return PatternType::STRUCT; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructPattern *clone_pattern_impl () const override + { + return new StructPattern (*this); + } +}; + +// Base abstract class for patterns used in TupleStructPattern +class TupleStructItems +{ +public: + enum ItemType + { + RANGE, + NO_RANGE + }; + + virtual ~TupleStructItems () {} + + // TODO: should this store location data? + + // Unique pointer custom clone function + std::unique_ptr clone_tuple_struct_items () const + { + return std::unique_ptr (clone_tuple_struct_items_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (HIRFullVisitor &vis) = 0; + + virtual ItemType get_item_type () const = 0; + +protected: + // pure virtual clone implementation + virtual TupleStructItems *clone_tuple_struct_items_impl () const = 0; +}; + +// Class for non-ranged tuple struct pattern patterns +class TupleStructItemsNoRange : public TupleStructItems +{ + std::vector > patterns; + +public: + TupleStructItemsNoRange (std::vector > patterns) + : patterns (std::move (patterns)) + {} + + // Copy constructor with vector clone + TupleStructItemsNoRange (TupleStructItemsNoRange const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator with vector clone + TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default; + TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other) + = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + std::vector > &get_patterns () { return patterns; } + const std::vector > &get_patterns () const + { + return patterns; + } + + ItemType get_item_type () const override final { return ItemType::NO_RANGE; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleStructItemsNoRange *clone_tuple_struct_items_impl () const override + { + return new TupleStructItemsNoRange (*this); + } +}; + +// Class for ranged tuple struct pattern patterns +class TupleStructItemsRange : public TupleStructItems +{ + std::vector > lower_patterns; + std::vector > upper_patterns; + +public: + TupleStructItemsRange (std::vector > lower_patterns, + std::vector > upper_patterns) + : lower_patterns (std::move (lower_patterns)), + upper_patterns (std::move (upper_patterns)) + {} + + // Copy constructor with vector clone + TupleStructItemsRange (TupleStructItemsRange const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to clone + TupleStructItemsRange &operator= (TupleStructItemsRange const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + TupleStructItemsRange (TupleStructItemsRange &&other) = default; + TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + std::vector > &get_lower_patterns () + { + return lower_patterns; + } + const std::vector > &get_lower_patterns () const + { + return lower_patterns; + } + + // TODO: seems kinda dodgy. Think of better way. + std::vector > &get_upper_patterns () + { + return upper_patterns; + } + const std::vector > &get_upper_patterns () const + { + return upper_patterns; + } + + ItemType get_item_type () const override final { return ItemType::RANGE; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleStructItemsRange *clone_tuple_struct_items_impl () const override + { + return new TupleStructItemsRange (*this); + } +}; + +// HIR node representing a tuple struct pattern +class TupleStructPattern : public Pattern +{ + PathInExpression path; + std::unique_ptr items; + Analysis::NodeMapping mappings; + + /* TOOD: should this store location data? current accessor uses path location + * data */ + +public: + std::string as_string () const override; + + TupleStructPattern (Analysis::NodeMapping mappings, + PathInExpression tuple_struct_path, + std::unique_ptr items) + : path (std::move (tuple_struct_path)), items (std::move (items)), + mappings (mappings) + {} + + // Copy constructor required to clone + TupleStructPattern (TupleStructPattern const &other) + : path (other.path), items (other.items->clone_tuple_struct_items ()), + mappings (other.mappings) + {} + + // Operator overload assignment operator to clone + TupleStructPattern &operator= (TupleStructPattern const &other) + { + path = other.path; + items = other.items->clone_tuple_struct_items (); + mappings = other.mappings; + + return *this; + } + + // move constructors + TupleStructPattern (TupleStructPattern &&other) = default; + TupleStructPattern &operator= (TupleStructPattern &&other) = default; + + Location get_locus () const override { return path.get_locus (); } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRPatternVisitor &vis) override; + + PathInExpression &get_path () { return path; } + + std::unique_ptr &get_items () { return items; } + + Analysis::NodeMapping get_pattern_mappings () const override final + { + return mappings; + } + + PatternType get_pattern_type () const override final + { + return PatternType::TUPLE_STRUCT; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleStructPattern *clone_pattern_impl () const override + { + return new TupleStructPattern (*this); + } +}; + +// Base abstract class representing TuplePattern patterns +class TuplePatternItems +{ +public: + enum TuplePatternItemType + { + MULTIPLE, + RANGED, + }; + + virtual ~TuplePatternItems () {} + + // TODO: should this store location data? + + // Unique pointer custom clone function + std::unique_ptr clone_tuple_pattern_items () const + { + return std::unique_ptr ( + clone_tuple_pattern_items_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (HIRFullVisitor &vis) = 0; + + virtual TuplePatternItemType get_pattern_type () const = 0; + +protected: + // pure virtual clone implementation + virtual TuplePatternItems *clone_tuple_pattern_items_impl () const = 0; +}; + +// Class representing TuplePattern patterns where there are multiple patterns +class TuplePatternItemsMultiple : public TuplePatternItems +{ + std::vector > patterns; + +public: + TuplePatternItemsMultiple (std::vector > patterns) + : patterns (std::move (patterns)) + {} + + // Copy constructor with vector clone + TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to vector clone + TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default; + TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other) + = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + TuplePatternItemType get_pattern_type () const override + { + return TuplePatternItemType::MULTIPLE; + } + + std::vector > &get_patterns () { return patterns; } + const std::vector > &get_patterns () const + { + return patterns; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TuplePatternItemsMultiple *clone_tuple_pattern_items_impl () const override + { + return new TuplePatternItemsMultiple (*this); + } +}; + +// Class representing TuplePattern patterns where there are a range of patterns +class TuplePatternItemsRanged : public TuplePatternItems +{ + std::vector > lower_patterns; + std::vector > upper_patterns; + +public: + TuplePatternItemsRanged ( + std::vector > lower_patterns, + std::vector > upper_patterns) + : lower_patterns (std::move (lower_patterns)), + upper_patterns (std::move (upper_patterns)) + {} + + // Copy constructor with vector clone + TuplePatternItemsRanged (TuplePatternItemsRanged const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to clone + TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default; + TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other) + = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + TuplePatternItemType get_pattern_type () const override + { + return TuplePatternItemType::RANGED; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TuplePatternItemsRanged *clone_tuple_pattern_items_impl () const override + { + return new TuplePatternItemsRanged (*this); + } +}; + +// HIR node representing a tuple pattern +class TuplePattern : public Pattern +{ + std::unique_ptr items; + Location locus; + Analysis::NodeMapping mappings; + +public: + std::string as_string () const override; + + // Returns true if the tuple pattern has items + bool has_tuple_pattern_items () const { return items != nullptr; } + + TuplePattern (Analysis::NodeMapping mappings, + std::unique_ptr items, Location locus) + : items (std::move (items)), locus (locus), mappings (mappings) + {} + + // Copy constructor requires clone + TuplePattern (TuplePattern const &other) + : items (other.items->clone_tuple_pattern_items ()), locus (other.locus), + mappings (other.mappings) + {} + + // Overload assignment operator to clone + TuplePattern &operator= (TuplePattern const &other) + { + items = other.items->clone_tuple_pattern_items (); + locus = other.locus; + mappings = other.mappings; + + return *this; + } + + Location get_locus () const override { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRPatternVisitor &vis) override; + + Analysis::NodeMapping get_pattern_mappings () const override final + { + return mappings; + } + + PatternType get_pattern_type () const override final + { + return PatternType::TUPLE; + } + + std::unique_ptr &get_items () { return items; } + const std::unique_ptr &get_items () const { return items; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TuplePattern *clone_pattern_impl () const override + { + return new TuplePattern (*this); + } +}; + +// HIR node representing a pattern in parentheses, used to control precedence +class GroupedPattern : public Pattern +{ + std::unique_ptr pattern_in_parens; + Location locus; + Analysis::NodeMapping mappings; + +public: + std::string as_string () const override + { + return "(" + pattern_in_parens->as_string () + ")"; + } + + GroupedPattern (Analysis::NodeMapping mappings, + std::unique_ptr pattern_in_parens, Location locus) + : pattern_in_parens (std::move (pattern_in_parens)), locus (locus), + mappings (mappings) + {} + + // Copy constructor uses clone + GroupedPattern (GroupedPattern const &other) + : pattern_in_parens (other.pattern_in_parens->clone_pattern ()), + locus (other.locus), mappings (other.mappings) + {} + + // Overload assignment operator to clone + GroupedPattern &operator= (GroupedPattern const &other) + { + pattern_in_parens = other.pattern_in_parens->clone_pattern (); + locus = other.locus; + mappings = other.mappings; + + return *this; + } + + // default move semantics + GroupedPattern (GroupedPattern &&other) = default; + GroupedPattern &operator= (GroupedPattern &&other) = default; + + Location get_locus () const override { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRPatternVisitor &vis) override; + + Analysis::NodeMapping get_pattern_mappings () const override final + { + return mappings; + } + + PatternType get_pattern_type () const override final + { + return PatternType::GROUPED; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + GroupedPattern *clone_pattern_impl () const override + { + return new GroupedPattern (*this); + } +}; + +// HIR node representing patterns that can match slices and arrays +class SlicePattern : public Pattern +{ + std::vector > items; + Location locus; + Analysis::NodeMapping mappings; + +public: + std::string as_string () const override; + + SlicePattern (Analysis::NodeMapping mappings, + std::vector > items, Location locus) + : items (std::move (items)), locus (locus), mappings (mappings) + {} + + // Copy constructor with vector clone + SlicePattern (SlicePattern const &other) + : locus (other.locus), mappings (other.mappings) + { + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to vector clone + SlicePattern &operator= (SlicePattern const &other) + { + locus = other.locus; + mappings = other.mappings; + + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + SlicePattern (SlicePattern &&other) = default; + SlicePattern &operator= (SlicePattern &&other) = default; + + Location get_locus () const override { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRPatternVisitor &vis) override; + + Analysis::NodeMapping get_pattern_mappings () const override final + { + return mappings; + } + + PatternType get_pattern_type () const override final + { + return PatternType::SLICE; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePattern *clone_pattern_impl () const override + { + return new SlicePattern (*this); + } +}; + +// Moved definition to rust-path.h +class PathPattern; + +// Forward decls for paths (defined in rust-path.h) +class PathInExpression; +class QualifiedPathInExpression; + +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-stmt.h b/gcc/rust/hir/tree/rust-hir-stmt.h new file mode 100644 index 00000000000..5247b0aa0f0 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-stmt.h @@ -0,0 +1,273 @@ +// 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_HIR_STATEMENT_H +#define RUST_HIR_STATEMENT_H + +#include "rust-hir.h" +#include "rust-hir-path.h" +#include "rust-hir-expr.h" + +namespace Rust { +namespace HIR { +// Just a semi-colon, which apparently is a statement. +class EmptyStmt : public Stmt +{ + Location locus; + +public: + std::string as_string () const override { return std::string (1, ';'); } + + EmptyStmt (Analysis::NodeMapping mappings, Location locus) + : Stmt (std::move (mappings)), locus (locus) + {} + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + + bool is_item () const override final { return false; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + EmptyStmt *clone_stmt_impl () const override { return new EmptyStmt (*this); } +}; + +/* Variable assignment let statement - type of "declaration statement" as it + * introduces new name into scope */ +class LetStmt : public Stmt +{ + // bool has_outer_attrs; + AST::AttrVec outer_attrs; + + std::unique_ptr variables_pattern; + + // bool has_type; + std::unique_ptr type; + + // bool has_init_expr; + std::unique_ptr init_expr; + + Location locus; + +public: + // Returns whether let statement has outer attributes. + bool has_outer_attrs () const { return !outer_attrs.empty (); } + + // Returns whether let statement has a given return type. + bool has_type () const { return type != nullptr; } + + // Returns whether let statement has an initialisation expression. + bool has_init_expr () const { return init_expr != nullptr; } + + std::string as_string () const override; + + LetStmt (Analysis::NodeMapping mappings, + std::unique_ptr variables_pattern, + std::unique_ptr init_expr, std::unique_ptr type, + AST::AttrVec outer_attrs, Location locus) + : Stmt (std::move (mappings)), outer_attrs (std::move (outer_attrs)), + variables_pattern (std::move (variables_pattern)), + type (std::move (type)), init_expr (std::move (init_expr)), locus (locus) + {} + + // Copy constructor with clone + LetStmt (LetStmt const &other) + : Stmt (other.mappings), outer_attrs (other.outer_attrs), + locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.variables_pattern != nullptr) + variables_pattern = other.variables_pattern->clone_pattern (); + + // guard to prevent null dereference (always required) + if (other.init_expr != nullptr) + init_expr = other.init_expr->clone_expr (); + if (other.type != nullptr) + type = other.type->clone_type (); + } + + // Overloaded assignment operator to clone + LetStmt &operator= (LetStmt const &other) + { + outer_attrs = other.outer_attrs; + locus = other.locus; + + // guard to prevent null dereference (only required if error state) + if (other.variables_pattern != nullptr) + variables_pattern = other.variables_pattern->clone_pattern (); + else + variables_pattern = nullptr; + + // guard to prevent null dereference (always required) + if (other.init_expr != nullptr) + init_expr = other.init_expr->clone_expr (); + else + init_expr = nullptr; + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + + return *this; + } + + // move constructors + LetStmt (LetStmt &&other) = default; + LetStmt &operator= (LetStmt &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + + HIR::Type *get_type () { return type.get (); } + + HIR::Expr *get_init_expr () { return init_expr.get (); } + + HIR::Pattern *get_pattern () { return variables_pattern.get (); } + + bool is_item () const override final { return false; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + LetStmt *clone_stmt_impl () const override { return new LetStmt (*this); } +}; + +/* Abstract base class for expression statements (statements containing an + * expression) */ +class ExprStmt : public Stmt +{ + // TODO: add any useful virtual functions + + Location locus; + +public: + Location get_locus () const override final { return locus; } + + bool is_item () const override final { return false; } + +protected: + ExprStmt (Analysis::NodeMapping mappings, Location locus) + : Stmt (std::move (mappings)), locus (locus) + {} +}; + +/* Statement containing an expression without a block (or, due to technical + * difficulties, can only be guaranteed to hold an expression). */ +class ExprStmtWithoutBlock : public ExprStmt +{ + std::unique_ptr expr; + +public: + std::string as_string () const override; + + ExprStmtWithoutBlock (Analysis::NodeMapping mappings, + std::unique_ptr expr, Location locus) + : ExprStmt (std::move (mappings), locus), expr (std::move (expr)) + {} + + // Copy constructor with clone + ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other) + : ExprStmt (other), expr (other.expr->clone_expr ()) + {} + + // Overloaded assignment operator to clone + ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock const &other) + { + ExprStmt::operator= (other); + expr = other.expr->clone_expr (); + + return *this; + } + + // move constructors + ExprStmtWithoutBlock (ExprStmtWithoutBlock &&other) = default; + ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + + Expr *get_expr () { return expr.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ExprStmtWithoutBlock *clone_stmt_impl () const override + { + return new ExprStmtWithoutBlock (*this); + } +}; + +// Statement containing an expression with a block +class ExprStmtWithBlock : public ExprStmt +{ + std::unique_ptr expr; + bool must_be_unit; + +public: + std::string as_string () const override; + + ExprStmtWithBlock (Analysis::NodeMapping mappings, + std::unique_ptr expr, Location locus, + bool must_be_unit) + : ExprStmt (std::move (mappings), locus), expr (std::move (expr)), + must_be_unit (must_be_unit) + {} + + // Copy constructor with clone + ExprStmtWithBlock (ExprStmtWithBlock const &other) + : ExprStmt (other), expr (other.expr->clone_expr_with_block ()) + {} + + // Overloaded assignment operator to clone + ExprStmtWithBlock &operator= (ExprStmtWithBlock const &other) + { + ExprStmt::operator= (other); + expr = other.expr->clone_expr_with_block (); + + return *this; + } + + // move constructors + ExprStmtWithBlock (ExprStmtWithBlock &&other) = default; + ExprStmtWithBlock &operator= (ExprStmtWithBlock &&other) = default; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRStmtVisitor &vis) override; + + ExprWithBlock *get_expr () { return expr.get (); } + + bool is_unit_check_needed () const override { return must_be_unit; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ExprStmtWithBlock *clone_stmt_impl () const override + { + return new ExprStmtWithBlock (*this); + } +}; + +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h new file mode 100644 index 00000000000..0d2e7436acc --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-type.h @@ -0,0 +1,860 @@ +// 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_HIR_TYPE_H +#define RUST_HIR_TYPE_H + +#include "rust-common.h" +#include "rust-hir.h" +#include "rust-hir-path.h" + +namespace Rust { +namespace HIR { +// definitions moved to rust-ast.h +class TypeParamBound; +class Lifetime; + +// A trait bound +class TraitBound : public TypeParamBound +{ + bool in_parens; + bool opening_question_mark; + std::vector for_lifetimes; + TypePath type_path; + Location locus; + + Analysis::NodeMapping mappings; + +public: + // Returns whether trait bound has "for" lifetimes + bool has_for_lifetimes () const { return !for_lifetimes.empty (); } + + TraitBound (Analysis::NodeMapping mapping, TypePath type_path, Location locus, + bool in_parens = false, bool opening_question_mark = false, + std::vector for_lifetimes + = std::vector ()) + : in_parens (in_parens), opening_question_mark (opening_question_mark), + for_lifetimes (std::move (for_lifetimes)), + type_path (std::move (type_path)), locus (locus), mappings (mapping) + {} + + std::string as_string () const override; + + Location get_locus () const override final { return locus; } + + void accept_vis (HIRFullVisitor &vis) override; + + Analysis::NodeMapping get_mappings () const override final + { + return mappings; + } + + BoundType get_bound_type () const final override { return TRAITBOUND; } + + TypePath &get_path () { return type_path; } + + const TypePath &get_path () const { return type_path; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TraitBound *clone_type_param_bound_impl () const override + { + return new TraitBound (*this); + } +}; + +// definition moved to rust-ast.h +class TypeNoBounds; + +// An impl trait? Poor reference material here. +class ImplTraitType : public Type +{ + // TypeParamBounds type_param_bounds; + // inlined form + std::vector> type_param_bounds; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ImplTraitType *clone_type_impl () const override + { + return new ImplTraitType (*this); + } + +public: + ImplTraitType (Analysis::NodeMapping mappings, + std::vector> type_param_bounds, + Location locus) + : Type (mappings, locus), type_param_bounds (std::move (type_param_bounds)) + {} + + // copy constructor with vector clone + ImplTraitType (ImplTraitType const &other) + : Type (other.mappings, other.locus) + { + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + } + + // overloaded assignment operator to clone + ImplTraitType &operator= (ImplTraitType const &other) + { + locus = other.locus; + mappings = other.mappings; + + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + + return *this; + } + + // move constructors + ImplTraitType (ImplTraitType &&other) = default; + ImplTraitType &operator= (ImplTraitType &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; +}; + +// An opaque value of another type that implements a set of traits +class TraitObjectType : public Type +{ + bool has_dyn; + std::vector> type_param_bounds; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TraitObjectType *clone_type_impl () const override + { + return new TraitObjectType (*this); + } + +public: + TraitObjectType ( + Analysis::NodeMapping mappings, + std::vector> type_param_bounds, + Location locus, bool is_dyn_dispatch) + : Type (mappings, locus), has_dyn (is_dyn_dispatch), + type_param_bounds (std::move (type_param_bounds)) + {} + + // copy constructor with vector clone + TraitObjectType (TraitObjectType const &other) + : Type (other.mappings, other.locus), has_dyn (other.has_dyn) + { + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + } + + // overloaded assignment operator to clone + TraitObjectType &operator= (TraitObjectType const &other) + { + mappings = other.mappings; + has_dyn = other.has_dyn; + locus = other.locus; + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + + return *this; + } + + // move constructors + TraitObjectType (TraitObjectType &&other) = default; + TraitObjectType &operator= (TraitObjectType &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; + + std::vector> &get_type_param_bounds () + { + return type_param_bounds; + } + + const std::vector> & + get_type_param_bounds () const + { + return type_param_bounds; + } +}; + +// A type with parentheses around it, used to avoid ambiguity. +class ParenthesisedType : public TypeNoBounds +{ + std::unique_ptr type_in_parens; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ParenthesisedType *clone_type_impl () const override + { + return new ParenthesisedType (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ParenthesisedType *clone_type_no_bounds_impl () const override + { + return new ParenthesisedType (*this); + } + +public: + // Constructor uses Type pointer for polymorphism + ParenthesisedType (Analysis::NodeMapping mappings, + std::unique_ptr type_inside_parens, Location locus) + : TypeNoBounds (mappings, locus), + type_in_parens (std::move (type_inside_parens)) + {} + + /* Copy constructor uses custom deep copy method for type to preserve + * polymorphism */ + ParenthesisedType (ParenthesisedType const &other) + : TypeNoBounds (other.mappings, other.locus), + type_in_parens (other.type_in_parens->clone_type ()) + {} + + // overload assignment operator to use custom clone method + ParenthesisedType &operator= (ParenthesisedType const &other) + { + mappings = other.mappings; + type_in_parens = other.type_in_parens->clone_type (); + locus = other.locus; + return *this; + } + + // default move semantics + ParenthesisedType (ParenthesisedType &&other) = default; + ParenthesisedType &operator= (ParenthesisedType &&other) = default; + + std::string as_string () const override + { + return "(" + type_in_parens->as_string () + ")"; + } + + // Creates a trait bound (clone of this one's trait bound) - HACK + TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const override + { + /* NOTE: obviously it is unknown whether the internal type is a trait bound + * due to polymorphism, so just let the internal type handle it. As + * parenthesised type, it must be in parentheses. */ + return type_in_parens->to_trait_bound (true); + } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; +}; + +// Impl trait with a single bound? Poor reference material here. +class ImplTraitTypeOneBound : public TypeNoBounds +{ + TraitBound trait_bound; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ImplTraitTypeOneBound *clone_type_impl () const override + { + return new ImplTraitTypeOneBound (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override + { + return new ImplTraitTypeOneBound (*this); + } + +public: + ImplTraitTypeOneBound (Analysis::NodeMapping mappings, TraitBound trait_bound, + Location locus) + : TypeNoBounds (mappings, locus), trait_bound (std::move (trait_bound)) + {} + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; +}; + +class TypePath; // definition moved to "rust-path.h" + +/* A type consisting of the "product" of others (the tuple's elements) in a + * specific order */ +class TupleType : public TypeNoBounds +{ + std::vector> elems; + +public: + // Returns whether the tuple type is the unit type, i.e. has no elements. + bool is_unit_type () const { return elems.empty (); } + + TupleType (Analysis::NodeMapping mappings, + std::vector> elems, Location locus) + : TypeNoBounds (mappings, locus), elems (std::move (elems)) + {} + + // copy constructor with vector clone + TupleType (TupleType const &other) + : TypeNoBounds (other.mappings, other.locus) + { + mappings = other.mappings; + elems.reserve (other.elems.size ()); + for (const auto &e : other.elems) + elems.push_back (e->clone_type ()); + } + + // overloaded assignment operator to clone + TupleType &operator= (TupleType const &other) + { + locus = other.locus; + + elems.reserve (other.elems.size ()); + for (const auto &e : other.elems) + elems.push_back (e->clone_type ()); + + return *this; + } + + // move constructors + TupleType (TupleType &&other) = default; + TupleType &operator= (TupleType &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; + + std::vector> &get_elems () { return elems; } + const std::vector> &get_elems () const { return elems; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleType *clone_type_impl () const override { return new TupleType (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleType *clone_type_no_bounds_impl () const override + { + return new TupleType (*this); + } +}; + +/* A type with no values, representing the result of computations that never + * complete. Expressions of NeverType can be coerced into any other types. + * Represented as "!". */ +class NeverType : public TypeNoBounds +{ +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + NeverType *clone_type_impl () const override { return new NeverType (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + NeverType *clone_type_no_bounds_impl () const override + { + return new NeverType (*this); + } + +public: + NeverType (Analysis::NodeMapping mappings, Location locus) + : TypeNoBounds (mappings, locus) + {} + + std::string as_string () const override { return "! (never type)"; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; +}; + +// A type consisting of a pointer without safety or liveness guarantees +class RawPointerType : public TypeNoBounds +{ +private: + Mutability mut; + std::unique_ptr type; + +public: + // Constructor requires pointer for polymorphism reasons + RawPointerType (Analysis::NodeMapping mappings, Mutability mut, + std::unique_ptr type, Location locus) + : TypeNoBounds (mappings, locus), mut (mut), type (std::move (type)) + {} + + // Copy constructor calls custom polymorphic clone function + RawPointerType (RawPointerType const &other) + : TypeNoBounds (other.mappings, other.locus), mut (other.mut), + type (other.type->clone_type ()) + {} + + // overload assignment operator to use custom clone method + RawPointerType &operator= (RawPointerType const &other) + { + mappings = other.mappings; + mut = other.mut; + type = other.type->clone_type (); + locus = other.locus; + return *this; + } + + // default move semantics + RawPointerType (RawPointerType &&other) = default; + RawPointerType &operator= (RawPointerType &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; + + std::unique_ptr &get_type () { return type; } + + Mutability get_mut () const { return mut; } + + bool is_mut () const { return mut == Mutability::Mut; } + + bool is_const () const { return mut == Mutability::Imm; } + + std::unique_ptr &get_base_type () { return type; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RawPointerType *clone_type_impl () const override + { + return new RawPointerType (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RawPointerType *clone_type_no_bounds_impl () const override + { + return new RawPointerType (*this); + } +}; + +// A type pointing to memory owned by another value +class ReferenceType : public TypeNoBounds +{ + // bool has_lifetime; // TODO: handle in lifetime or something? + Lifetime lifetime; + + Mutability mut; + std::unique_ptr type; + +public: + // Returns whether the reference is mutable or immutable. + bool is_mut () const { return mut == Mutability::Mut; } + + // Returns whether the reference has a lifetime. + bool has_lifetime () const { return !lifetime.is_error (); } + + // Constructor + ReferenceType (Analysis::NodeMapping mappings, Mutability mut, + std::unique_ptr type_no_bounds, Location locus, + Lifetime lifetime) + : TypeNoBounds (mappings, locus), lifetime (std::move (lifetime)), + mut (mut), type (std::move (type_no_bounds)) + {} + + // Copy constructor with custom clone method + ReferenceType (ReferenceType const &other) + : TypeNoBounds (other.mappings, other.locus), lifetime (other.lifetime), + mut (other.mut), type (other.type->clone_type ()) + {} + + // Operator overload assignment operator to custom clone the unique pointer + ReferenceType &operator= (ReferenceType const &other) + { + mappings = other.mappings; + lifetime = other.lifetime; + mut = other.mut; + type = other.type->clone_type (); + locus = other.locus; + + return *this; + } + + // move constructors + ReferenceType (ReferenceType &&other) = default; + ReferenceType &operator= (ReferenceType &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; + + Lifetime &get_lifetime () { return lifetime; } + + Mutability get_mut () const { return mut; } + + std::unique_ptr &get_base_type () { return type; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ReferenceType *clone_type_impl () const override + { + return new ReferenceType (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ReferenceType *clone_type_no_bounds_impl () const override + { + return new ReferenceType (*this); + } +}; + +// A fixed-size sequence of elements of a specified type +class ArrayType : public TypeNoBounds +{ + std::unique_ptr elem_type; + std::unique_ptr size; + +public: + // Constructor requires pointers for polymorphism + ArrayType (Analysis::NodeMapping mappings, std::unique_ptr type, + std::unique_ptr array_size, Location locus) + : TypeNoBounds (mappings, locus), elem_type (std::move (type)), + size (std::move (array_size)) + {} + + // Copy constructor requires deep copies of both unique pointers + ArrayType (ArrayType const &other) + : TypeNoBounds (other.mappings, other.locus), + elem_type (other.elem_type->clone_type ()), + size (other.size->clone_expr ()) + {} + + // Overload assignment operator to deep copy pointers + ArrayType &operator= (ArrayType const &other) + { + mappings = other.mappings; + elem_type = other.elem_type->clone_type (); + size = other.size->clone_expr (); + locus = other.locus; + return *this; + } + + // move constructors + ArrayType (ArrayType &&other) = default; + ArrayType &operator= (ArrayType &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; + + Type *get_element_type () { return elem_type.get (); } + + Expr *get_size_expr () { return size.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArrayType *clone_type_impl () const override { return new ArrayType (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArrayType *clone_type_no_bounds_impl () const override + { + return new ArrayType (*this); + } +}; + +/* A dynamically-sized type representing a "view" into a sequence of elements of + * a type */ +class SliceType : public TypeNoBounds +{ + std::unique_ptr elem_type; + +public: + // Constructor requires pointer for polymorphism + SliceType (Analysis::NodeMapping mappings, std::unique_ptr type, + Location locus) + : TypeNoBounds (mappings, locus), elem_type (std::move (type)) + {} + + // Copy constructor requires deep copy of Type smart pointer + SliceType (SliceType const &other) + : TypeNoBounds (other.mappings, other.locus), + elem_type (other.elem_type->clone_type ()) + {} + + // Overload assignment operator to deep copy + SliceType &operator= (SliceType const &other) + { + mappings = other.mappings; + elem_type = other.elem_type->clone_type (); + locus = other.locus; + + return *this; + } + + // move constructors + SliceType (SliceType &&other) = default; + SliceType &operator= (SliceType &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; + + std::unique_ptr &get_element_type () { return elem_type; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SliceType *clone_type_impl () const override { return new SliceType (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + SliceType *clone_type_no_bounds_impl () const override + { + return new SliceType (*this); + } +}; + +/* Type used in generic arguments to explicitly request type inference (wildcard + * pattern) */ +class InferredType : public TypeNoBounds +{ + // e.g. Vec<_> = whatever +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + InferredType *clone_type_impl () const override + { + return new InferredType (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + InferredType *clone_type_no_bounds_impl () const override + { + return new InferredType (*this); + } + +public: + InferredType (Analysis::NodeMapping mappings, Location locus) + : TypeNoBounds (mappings, locus) + {} + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; +}; + +class QualifiedPathInType; // definition moved to "rust-path.h" + +// A possibly named param used in a BaseFunctionType +struct MaybeNamedParam +{ +public: + enum ParamKind + { + UNNAMED, + IDENTIFIER, + WILDCARD + }; + +private: + std::unique_ptr param_type; + + ParamKind param_kind; + Identifier name; // technically, can be an identifier or '_' + + Location locus; + +public: + MaybeNamedParam (Identifier name, ParamKind param_kind, + std::unique_ptr param_type, Location locus) + : param_type (std::move (param_type)), param_kind (param_kind), + name (std::move (name)), locus (locus) + {} + + // Copy constructor with clone + MaybeNamedParam (MaybeNamedParam const &other) + : param_type (other.param_type->clone_type ()), + param_kind (other.param_kind), name (other.name), locus (other.locus) + {} + + ~MaybeNamedParam () = default; + + // Overloaded assignment operator with clone + MaybeNamedParam &operator= (MaybeNamedParam const &other) + { + name = other.name; + param_kind = other.param_kind; + param_type = other.param_type->clone_type (); + locus = other.locus; + + return *this; + } + + // move constructors + MaybeNamedParam (MaybeNamedParam &&other) = default; + MaybeNamedParam &operator= (MaybeNamedParam &&other) = default; + + std::string as_string () const; + + // Returns whether the param is in an error state. + bool is_error () const { return param_type == nullptr; } + + // Creates an error state param. + static MaybeNamedParam create_error () + { + return MaybeNamedParam ("", UNNAMED, nullptr, Location ()); + } + + Location get_locus () const { return locus; } + + std::unique_ptr &get_type () + { + rust_assert (param_type != nullptr); + return param_type; + } + + ParamKind get_param_kind () const { return param_kind; } + + Identifier get_name () const { return name; } +}; + +/* A function pointer type - can be created via coercion from function items and + * non- capturing closures. */ +class BareFunctionType : public TypeNoBounds +{ + // bool has_for_lifetimes; + // ForLifetimes for_lifetimes; + std::vector for_lifetimes; // inlined version + + FunctionQualifiers function_qualifiers; + std::vector params; + bool is_variadic; + + std::unique_ptr return_type; // inlined version + +public: + // Whether a return type is defined with the function. + bool has_return_type () const { return return_type != nullptr; } + + // Whether the function has ForLifetimes. + bool has_for_lifetimes () const { return !for_lifetimes.empty (); } + + BareFunctionType (Analysis::NodeMapping mappings, + std::vector lifetime_params, + FunctionQualifiers qualifiers, + std::vector named_params, bool is_variadic, + std::unique_ptr type, Location locus) + : TypeNoBounds (mappings, locus), + for_lifetimes (std::move (lifetime_params)), + function_qualifiers (std::move (qualifiers)), + params (std::move (named_params)), is_variadic (is_variadic), + return_type (std::move (type)) + {} + + // Copy constructor with clone + BareFunctionType (BareFunctionType const &other) + : TypeNoBounds (other.mappings, other.locus), + for_lifetimes (other.for_lifetimes), + function_qualifiers (other.function_qualifiers), params (other.params), + is_variadic (other.is_variadic), + return_type (other.return_type->clone_type ()) + {} + + // Overload assignment operator to deep copy + BareFunctionType &operator= (BareFunctionType const &other) + { + mappings = other.mappings; + for_lifetimes = other.for_lifetimes; + function_qualifiers = other.function_qualifiers; + params = other.params; + is_variadic = other.is_variadic; + return_type = other.return_type->clone_type (); + locus = other.locus; + + return *this; + } + + // move constructors + BareFunctionType (BareFunctionType &&other) = default; + BareFunctionType &operator= (BareFunctionType &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; + + std::vector &get_function_params () { return params; } + const std::vector &get_function_params () const + { + return params; + } + + // TODO: would a "vis_type" be better? + std::unique_ptr &get_return_type () + { + rust_assert (has_return_type ()); + return return_type; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + BareFunctionType *clone_type_impl () const override + { + return new BareFunctionType (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + BareFunctionType *clone_type_no_bounds_impl () const override + { + return new BareFunctionType (*this); + } +}; + +/* TODO: possible types + * struct type? + * "enum" (tagged union) type? + * C-like union type? + * function item type? + * closure expression types? + * primitive types (bool, int, float, char, str (the slice)) + * Although supposedly TypePaths are used to reference these types (including + * primitives) */ + +/* FIXME: Incomplete spec references: + * anonymous type parameters, aka "impl Trait in argument position" - impl then + * trait bounds abstract return types, aka "impl Trait in return position" - + * impl then trait bounds */ +} // namespace HIR +} // namespace Rust + +#endif -- 2.37.2