// Copyright (C) 2020-2024 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// .
#ifndef RUST_HIR_EXPR_H
#define RUST_HIR_EXPR_H
#include "rust-ast.h"
#include "rust-hir-expr-abstract.h"
#include "rust-hir-literal.h"
#include "rust-common.h"
#include "rust-hir-bound.h"
#include "rust-hir-attrs.h"
#include "rust-expr.h"
#include "rust-hir-map.h"
namespace Rust {
namespace HIR {
// Loop label expression HIR node used with break and continue expressions
// TODO: inline?
class LoopLabel /*: public Node*/
{
Lifetime label; // of type LIFETIME_OR_LABEL
location_t locus;
Analysis::NodeMapping mappings;
public:
std::string as_string () const;
LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label,
location_t locus);
location_t get_locus () const { return locus; }
Analysis::NodeMapping &get_mappings () { return mappings; }
Lifetime &get_lifetime () { return label; }
};
// 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 ());
// 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_t locus;
bool negative_number = false;
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_t locus, AST::AttrVec outer_attrs);
LiteralExpr (Analysis::NodeMapping mappings, Literal literal,
location_t locus, AST::AttrVec outer_attrs);
// Unique pointer custom clone function
std::unique_ptr clone_literal_expr () const
{
return std::unique_ptr (clone_literal_expr_impl ());
}
location_t 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; }
bool is_negative () const { return negative_number; }
void set_negative ()
{
rust_assert (get_lit_type () == Literal::LitType::INT
|| get_lit_type () == Literal::LitType::FLOAT);
negative_number = true;
}
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?
private:
location_t 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_t locus);
// Copy constructor (only for initialisation of expr purposes)
OperatorExpr (OperatorExpr const &other);
// Overload assignment operator to deep copy expr
OperatorExpr &operator= (OperatorExpr const &other);
// move constructors
OperatorExpr (OperatorExpr &&other) = default;
OperatorExpr &operator= (OperatorExpr &&other) = default;
public:
location_t get_locus () const override final { return locus; }
Expr &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 raw;
public:
std::string as_string () const override;
BorrowExpr (Analysis::NodeMapping mappings,
std::unique_ptr borrow_lvalue, Mutability mut, bool raw,
AST::AttrVec outer_attribs, location_t locus);
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 is_raw_borrow () const { return raw; }
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_t 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_t 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_t 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 */
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_t locus);
// outer attributes not allowed
// Copy constructor - probably required due to unique pointer
ArithmeticOrLogicalExpr (ArithmeticOrLogicalExpr const &other);
// Overload assignment operator
ArithmeticOrLogicalExpr &operator= (ArithmeticOrLogicalExpr const &other);
// 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; }
Expr &get_rhs () { return *right_expr; }
std::string get_operator_str () const;
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_t locus);
// outer attributes not allowed
// Copy constructor also calls OperatorExpr's protected constructor
ComparisonExpr (ComparisonExpr const &other);
// Overload assignment operator to deep copy
ComparisonExpr &operator= (ComparisonExpr const &other);
// 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; }
Expr &get_rhs () { return *right_expr; }
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_t locus);
// outer attributes not allowed
// Copy constructor also calls OperatorExpr's protected constructor
LazyBooleanExpr (LazyBooleanExpr const &other);
// Overload assignment operator to deep copy
LazyBooleanExpr &operator= (LazyBooleanExpr const &other);
// 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; }
Expr &get_rhs () { return *right_expr; }
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_t locus);
// outer attributes not allowed
// Copy constructor also requires calling protected constructor
TypeCastExpr (TypeCastExpr const &other);
// Overload assignment operator to deep copy
TypeCastExpr &operator= (TypeCastExpr const &other);
// 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;
// FIXME: isn't it the same as get_expr() from parent?
Expr &get_casted_expr () { return *main_or_left_expr; }
Type &get_type_to_convert_to () { 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_t locus);
// outer attributes not allowed
// Call OperatorExpr constructor in copy constructor, as well as clone
AssignmentExpr (AssignmentExpr const &other);
// Overload assignment operator to clone unique_ptr right_expr
AssignmentExpr &operator= (AssignmentExpr const &other);
// 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; }
Expr &get_rhs () { return *right_expr; }
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_t locus);
// outer attributes not allowed
// Have clone in copy constructor
CompoundAssignmentExpr (CompoundAssignmentExpr const &other);
// Overload assignment operator to clone
CompoundAssignmentExpr &operator= (CompoundAssignmentExpr const &other);
// move constructors
CompoundAssignmentExpr (CompoundAssignmentExpr &&other) = default;
CompoundAssignmentExpr &operator= (CompoundAssignmentExpr &&other) = default;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &get_lhs () { return *main_or_left_expr; }
Expr &get_rhs () { 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); }
std::string get_operator_str () const;
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, public WithInnerAttrs
{
std::unique_ptr expr_in_parens;
location_t locus;
public:
std::string as_string () const override;
GroupedExpr (Analysis::NodeMapping mappings,
std::unique_ptr parenthesised_expr,
AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
location_t locus);
// Copy constructor includes clone for expr_in_parens
GroupedExpr (GroupedExpr const &other);
// Overloaded assignment operator to clone expr_in_parens
GroupedExpr &operator= (GroupedExpr const &other);
// move constructors
GroupedExpr (GroupedExpr &&other) = default;
GroupedExpr &operator= (GroupedExpr &&other) = default;
location_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &get_expr_in_parens () { 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 FullVisitable
{
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);
// copy constructor with vector clone
ArrayElemsValues (ArrayElemsValues const &other);
// overloaded assignment operator with vector clone
ArrayElemsValues &operator= (ArrayElemsValues const &other);
// 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);
// Copy constructor required due to unique_ptr - uses custom clone
ArrayElemsCopied (ArrayElemsCopied const &other);
// Overloaded assignment operator for deep copying
ArrayElemsCopied &operator= (ArrayElemsCopied const &other);
// 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; }
Expr &get_num_copies_expr () { return *num_copies; }
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, public WithInnerAttrs
{
std::unique_ptr internal_elements;
location_t locus;
public:
std::string as_string () const override;
// 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_t locus);
// Copy constructor requires cloning ArrayElems for polymorphism to hold
ArrayExpr (ArrayExpr const &other);
// Overload assignment operator to clone internal_elements
ArrayExpr &operator= (ArrayExpr const &other);
// move constructors
ArrayExpr (ArrayExpr &&other) = default;
ArrayExpr &operator= (ArrayExpr &&other) = default;
location_t 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; };
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_t 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_t locus);
// Copy constructor requires special cloning due to unique_ptr
ArrayIndexExpr (ArrayIndexExpr const &other);
// Overload assignment operator to clone unique_ptrs
ArrayIndexExpr &operator= (ArrayIndexExpr const &other);
// move constructors
ArrayIndexExpr (ArrayIndexExpr &&other) = default;
ArrayIndexExpr &operator= (ArrayIndexExpr &&other) = default;
location_t 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; }
Expr &get_index_expr () { return *index_expr; }
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, public WithInnerAttrs
{
std::vector> tuple_elems;
// replaces (inlined version of) TupleElements
location_t locus;
public:
std::string as_string () const override;
TupleExpr (Analysis::NodeMapping mappings,
std::vector> tuple_elements,
AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
location_t locus);
// copy constructor with vector clone
TupleExpr (TupleExpr const &other);
// overloaded assignment operator to vector clone
TupleExpr &operator= (TupleExpr const &other);
// 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_t 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_t 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_t locus);
// Copy constructor requires a clone for tuple_expr
TupleIndexExpr (TupleIndexExpr const &other);
// Overload assignment operator in order to clone
TupleIndexExpr &operator= (TupleIndexExpr const &other);
// move constructors
TupleIndexExpr (TupleIndexExpr &&other) = default;
TupleIndexExpr &operator= (TupleIndexExpr &&other) = default;
location_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &get_tuple_expr () { 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);
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, public WithInnerAttrs
{
location_t locus;
public:
std::string as_string () const override;
// 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_t locus);
location_t 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
{
private:
std::unique_ptr base_struct;
public:
// TODO: should this store location data?
StructBase (std::unique_ptr base_struct_ptr);
// Copy constructor requires clone
StructBase (StructBase const &other);
// Destructor
~StructBase () = default;
// Overload assignment operator to clone base_struct
StructBase &operator= (StructBase const &other);
// 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; }
};
/* Base HIR node for a single struct expression field (in struct instance
* creation) - abstract */
class StructExprField : public FullVisitable
{
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_t 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_t locus);
Analysis::NodeMapping mappings;
location_t 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_t locus);
std::string as_string () const override { return field_name.as_string (); }
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_t locus);
// Copy constructor requires clone
StructExprFieldWithVal (StructExprFieldWithVal const &other);
// Overload assignment operator to clone unique_ptr
StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other);
// move constructors
StructExprFieldWithVal (StructExprFieldWithVal &&other) = default;
StructExprFieldWithVal &operator= (StructExprFieldWithVal &&other) = default;
public:
std::string as_string () const override;
Expr &get_value () { return *value; }
};
// 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_t locus);
std::string as_string () const override;
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_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_t locus);
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
{
// std::vector fields;
std::vector> fields;
tl::optional> struct_base;
public:
// 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.has_value (); }
// Constructor for StructExprStructFields when no struct base is used
StructExprStructFields (
Analysis::NodeMapping mappings, PathInExpression struct_path,
std::vector> expr_fields, location_t locus,
tl::optional> base_struct,
AST::AttrVec inner_attribs, AST::AttrVec outer_attribs);
// copy constructor with vector clone
StructExprStructFields (StructExprStructFields const &other);
// overloaded assignment operator with vector clone
StructExprStructFields &operator= (StructExprStructFields const &other);
// 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;
};
StructBase &get_struct_base () { return *struct_base.value (); }
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:
StructExprStructBase (Analysis::NodeMapping mappings,
PathInExpression struct_path, StructBase base_struct,
AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
location_t locus);
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_t 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_t locus);
// copy constructor requires clone
CallExpr (CallExpr const &other);
// Overload assignment operator to clone
CallExpr &operator= (CallExpr const &other);
// 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_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
bool has_fnexpr () const { return function != nullptr; }
Expr &get_fnexpr () { return *function; }
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_t 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_t locus);
// copy constructor required due to cloning
MethodCallExpr (MethodCallExpr const &other);
// Overload assignment operator to clone receiver object
MethodCallExpr &operator= (MethodCallExpr const &other);
// move constructors
MethodCallExpr (MethodCallExpr &&other) = default;
MethodCallExpr &operator= (MethodCallExpr &&other) = default;
location_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &get_receiver () { return *receiver; }
PathExprSegment &get_method_name () { return method_name; };
const PathExprSegment &get_method_name () const { return method_name; };
bool has_params () const { return !params.empty (); }
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_t 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_t locus);
// Copy constructor required due to unique_ptr cloning
FieldAccessExpr (FieldAccessExpr const &other);
// Overload assignment operator to clone unique_ptr
FieldAccessExpr &operator= (FieldAccessExpr const &other);
// move constructors
FieldAccessExpr (FieldAccessExpr &&other) = default;
FieldAccessExpr &operator= (FieldAccessExpr &&other) = default;
location_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &get_receiver_expr () { 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::vector outer_attrs;
std::unique_ptr pattern;
std::unique_ptr type;
location_t locus;
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, location_t locus,
std::unique_ptr param_type = nullptr,
std::vector outer_attrs = {});
// Copy constructor required due to cloning as a result of unique_ptrs
ClosureParam (ClosureParam const &other);
~ClosureParam () = default;
// Assignment operator must be overloaded to clone as well
ClosureParam &operator= (ClosureParam const &other);
// move constructors
ClosureParam (ClosureParam &&other) = default;
ClosureParam &operator= (ClosureParam &&other) = default;
std::string as_string () const;
const std::vector &get_outer_attrs () const
{
return outer_attrs;
}
std::vector &get_outer_attrs () { return outer_attrs; }
Pattern &get_pattern () { return *pattern; }
Type &get_type () { return *type; }
location_t get_locus () const { return locus; }
};
// Base closure definition expression HIR node - abstract
class ClosureExpr : public ExprWithoutBlock
{
private:
bool has_move;
std::vector params;
location_t locus;
std::unique_ptr return_type;
std::unique_ptr expr;
public:
ClosureExpr (Analysis::NodeMapping mappings,
std::vector closure_params,
std::unique_ptr closure_return_type,
std::unique_ptr closure_expr, bool has_move,
AST::AttrVec outer_attribs, location_t locus);
// Copy constructor requires cloning
ClosureExpr (ClosureExpr const &other);
// Overload assignment operator to clone unique_ptrs
ClosureExpr &operator= (ClosureExpr const &other);
// move constructors
ClosureExpr (ClosureExpr &&other) = default;
ClosureExpr &operator= (ClosureExpr &&other) = default;
std::string as_string () const override;
location_t get_locus () const override final { return locus; }
ExprType get_expression_type () const override final
{
return ExprType::Closure;
}
bool get_has_move () const { return has_move; }
bool has_return_type () const { return return_type != nullptr; }
Type &get_return_type () { return *return_type; };
Expr &get_expr () { return *expr; }
bool has_params () const { return !params.empty (); }
std::vector &get_params () { return params; }
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 */
ClosureExpr *clone_expr_impl () const override
{
return new ClosureExpr (*this);
}
/* Use covariance to implement clone function as returning this object rather
* than base */
ClosureExpr *clone_expr_without_block_impl () const override
{
return new ClosureExpr (*this);
}
};
// A block HIR node
class BlockExpr : public ExprWithBlock, public WithInnerAttrs
{
// FIXME this should be private + get/set
public:
std::vector> statements;
std::unique_ptr expr;
bool tail_reachable;
tl::optional label;
location_t start_locus;
location_t end_locus;
std::string as_string () const override;
AST::AttrVec get_inner_attrs () const { return inner_attrs; }
// 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,
tl::optional label, location_t start_locus,
location_t end_locus);
// Copy constructor with clone
BlockExpr (BlockExpr const &other);
// Overloaded assignment operator to clone pointer
BlockExpr &operator= (BlockExpr const &other);
// 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_t get_locus () const override final { return start_locus; }
location_t get_start_locus () const { return start_locus; }
location_t 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; }
bool has_final_expr () { return expr != nullptr; }
Expr &get_final_expr () { return *expr; }
std::vector> &get_statements () { return statements; }
ExprType get_expression_type () const final override
{
return ExprType::Block;
}
bool has_label () const { return label.has_value (); }
LoopLabel &get_label () { return label.value (); }
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);
}
};
class AnonConst : public ExprWithBlock
{
public:
AnonConst (Analysis::NodeMapping mappings, std::unique_ptr &&expr,
location_t locus = UNKNOWN_LOCATION);
AnonConst (const AnonConst &other);
AnonConst operator= (const AnonConst &other);
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
ExprType get_expression_type () const final override
{
return ExprType::AnonConst;
}
location_t get_locus () const override { return locus; }
Expr &get_inner_expr () { return *expr; }
const Expr &get_inner_expr () const { return *expr; }
private:
location_t locus;
std::unique_ptr expr;
AnonConst *clone_expr_with_block_impl () const override
{
return new AnonConst (*this);
}
};
class ConstBlock : public ExprWithBlock
{
public:
ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr,
location_t locus = UNKNOWN_LOCATION,
AST::AttrVec outer_attrs = {});
ConstBlock (const ConstBlock &other);
ConstBlock operator= (const ConstBlock &other);
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
std::string as_string () const override;
ExprType get_expression_type () const final override
{
return ExprType::ConstBlock;
}
location_t get_locus () const override { return locus; }
AnonConst &get_const_expr () { return expr; }
const AnonConst &get_const_expr () const { return expr; }
private:
AnonConst expr;
location_t locus;
ConstBlock *clone_expr_with_block_impl () const override
{
return new ConstBlock (*this);
}
};
// HIR node representing continue expression within loops
class ContinueExpr : public ExprWithoutBlock
{
tl::optional label;
location_t locus;
public:
std::string as_string () const override;
// Returns true if the continue expr has a label.
bool has_label () const { return label.has_value (); }
// Constructor for a ContinueExpr with a label.
ContinueExpr (Analysis::NodeMapping mappings, location_t locus,
tl::optional label,
AST::AttrVec outer_attribs = AST::AttrVec ());
location_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Lifetime &get_label () { return label.value (); }
const Lifetime &get_label () const { return label.value (); }
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;
tl::optional label;
// bool has_break_expr;
std::unique_ptr break_expr;
location_t locus;
public:
std::string as_string () const override;
// Returns whether the break expression has a label or not.
bool has_label () const { return label.has_value (); }
/* 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_t locus,
tl::optional break_label,
std::unique_ptr expr_in_break = nullptr,
AST::AttrVec outer_attribs = AST::AttrVec ());
// Copy constructor defined to use clone for unique pointer
BreakExpr (BreakExpr const &other);
// Overload assignment operator to clone unique pointer
BreakExpr &operator= (BreakExpr const &other);
// move constructors
BreakExpr (BreakExpr &&other) = default;
BreakExpr &operator= (BreakExpr &&other) = default;
location_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Lifetime &get_label () { return label.value (); }
const Lifetime &get_label () const { return label.value (); }
Expr &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_t locus;
protected:
// outer attributes not allowed before range expressions
RangeExpr (Analysis::NodeMapping mappings, location_t locus);
public:
location_t 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_t locus);
// Copy constructor with cloning
RangeFromToExpr (RangeFromToExpr const &other);
// Overload assignment operator to clone unique pointers
RangeFromToExpr &operator= (RangeFromToExpr const &other);
// move constructors
RangeFromToExpr (RangeFromToExpr &&other) = default;
RangeFromToExpr &operator= (RangeFromToExpr &&other) = default;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &get_from_expr () { return *from; }
Expr &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_t locus);
// Copy constructor with clone
RangeFromExpr (RangeFromExpr const &other);
// Overload assignment operator to clone unique_ptr
RangeFromExpr &operator= (RangeFromExpr const &other);
// move constructors
RangeFromExpr (RangeFromExpr &&other) = default;
RangeFromExpr &operator= (RangeFromExpr &&other) = default;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &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_t locus);
// Copy constructor with clone
RangeToExpr (RangeToExpr const &other);
// Overload assignment operator to clone unique_ptr
RangeToExpr &operator= (RangeToExpr const &other);
// move constructors
RangeToExpr (RangeToExpr &&other) = default;
RangeToExpr &operator= (RangeToExpr &&other) = default;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &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_t 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_t locus);
// outer attributes not allowed
// Copy constructor with clone
RangeFromToInclExpr (RangeFromToInclExpr const &other);
// Overload assignment operator to use clone
RangeFromToInclExpr &operator= (RangeFromToInclExpr const &other);
// move constructors
RangeFromToInclExpr (RangeFromToInclExpr &&other) = default;
RangeFromToInclExpr &operator= (RangeFromToInclExpr &&other) = default;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &get_from_expr () { return *from; }
Expr &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_t locus);
// outer attributes not allowed
// Copy constructor with clone
RangeToInclExpr (RangeToInclExpr const &other);
// Overload assignment operator to clone pointer
RangeToInclExpr &operator= (RangeToInclExpr const &other);
// move constructors
RangeToInclExpr (RangeToInclExpr &&other) = default;
RangeToInclExpr &operator= (RangeToInclExpr &&other) = default;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &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_t 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_t locus,
std::unique_ptr returned_expr = nullptr,
AST::AttrVec outer_attribs = AST::AttrVec ());
// Copy constructor with clone
ReturnExpr (ReturnExpr const &other);
// Overloaded assignment operator to clone return_expr pointer
ReturnExpr &operator= (ReturnExpr const &other);
// move constructors
ReturnExpr (ReturnExpr &&other) = default;
ReturnExpr &operator= (ReturnExpr &&other) = default;
location_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
bool has_expr () { return return_expr != nullptr; }
Expr &get_expr () { return *return_expr; }
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_t locus;
public:
std::string as_string () const override;
UnsafeBlockExpr (Analysis::NodeMapping mappings,
std::unique_ptr block_expr,
AST::AttrVec outer_attribs, location_t locus);
// Copy constructor with clone
UnsafeBlockExpr (UnsafeBlockExpr const &other);
// Overloaded assignment operator to clone
UnsafeBlockExpr &operator= (UnsafeBlockExpr const &other);
// move constructors
UnsafeBlockExpr (UnsafeBlockExpr &&other) = default;
UnsafeBlockExpr &operator= (UnsafeBlockExpr &&other) = default;
location_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
BlockExpr &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);
}
};
// Base loop expression HIR node - aka LoopExpr
class BaseLoopExpr : public ExprWithBlock
{
protected:
tl::optional loop_label;
std::unique_ptr loop_block;
private:
location_t locus;
protected:
// Constructor for BaseLoopExpr
BaseLoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr loop_block, location_t locus,
tl::optional loop_label,
AST::AttrVec outer_attribs = AST::AttrVec ());
// Copy constructor for BaseLoopExpr with clone
BaseLoopExpr (BaseLoopExpr const &other);
// Overloaded assignment operator to clone
BaseLoopExpr &operator= (BaseLoopExpr const &other);
// 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.has_value (); }
location_t get_locus () const override final { return locus; }
HIR::BlockExpr &get_loop_block () { return *loop_block; };
LoopLabel &get_loop_label () { return loop_label.value (); }
const LoopLabel &get_loop_label () const { return loop_label.value (); }
};
// '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_t locus,
tl::optional loop_label,
AST::AttrVec outer_attribs = AST::AttrVec ());
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_t locus,
tl::optional loop_label,
AST::AttrVec outer_attribs = AST::AttrVec ());
// Copy constructor with clone
WhileLoopExpr (WhileLoopExpr const &other);
// Overloaded assignment operator to clone
WhileLoopExpr &operator= (WhileLoopExpr const &other);
// move constructors
WhileLoopExpr (WhileLoopExpr &&other) = default;
WhileLoopExpr &operator= (WhileLoopExpr &&other) = default;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &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_t locus,
tl::optional loop_label,
AST::AttrVec outer_attribs = AST::AttrVec ());
// Copy constructor with clone
WhileLetLoopExpr (WhileLetLoopExpr const &other);
// Overloaded assignment operator to clone pointers
WhileLetLoopExpr &operator= (WhileLetLoopExpr const &other);
// move constructors
WhileLetLoopExpr (WhileLetLoopExpr &&other) = default;
WhileLetLoopExpr &operator= (WhileLetLoopExpr &&other) = default;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &get_cond () { return *condition; }
std::vector> &get_patterns ()
{
return match_arm_patterns;
}
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);
}
};
// 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_t locus;
public:
std::string as_string () const override;
IfExpr (Analysis::NodeMapping mappings, std::unique_ptr condition,
std::unique_ptr if_block, location_t locus);
// outer attributes are never allowed on IfExprs
// Copy constructor with clone
IfExpr (IfExpr const &other);
// Overloaded assignment operator to clone expressions
IfExpr &operator= (IfExpr const &other);
// 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_t 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; }
BlockExpr &get_if_block () { return *if_block; }
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_t locus);
// again, outer attributes not allowed
// Copy constructor with clone
IfExprConseqElse (IfExprConseqElse const &other);
// Overloaded assignment operator with cloning
IfExprConseqElse &operator= (IfExprConseqElse const &other);
// 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); }
ExprWithBlock &get_else_block () { return *else_block; }
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);
}
};
// Match arm expression
struct MatchArm
{
private:
AST::AttrVec outer_attrs;
std::vector> match_arm_patterns;
std::unique_ptr guard_expr;
location_t 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_t locus, std::unique_ptr guard_expr = nullptr,
AST::AttrVec outer_attrs = AST::AttrVec ());
// Copy constructor with clone
MatchArm (MatchArm const &other);
~MatchArm () = default;
// Overload assignment operator to clone
MatchArm &operator= (MatchArm const &other);
// 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_t locus = UNDEF_LOCATION;
return MatchArm (std::vector> (), locus);
}
std::string as_string () const;
std::vector> &get_patterns ()
{
return match_arm_patterns;
}
Expr &get_guard_expr () { return *guard_expr; }
location_t 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);
MatchCase (const MatchCase &other);
MatchCase &operator= (const MatchCase &other);
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; }
Expr &get_expr () { return *expr; }
};
// Match expression HIR node
class MatchExpr : public ExprWithBlock, public WithInnerAttrs
{
std::unique_ptr branch_value;
std::vector match_arms;
location_t 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_t locus);
// Copy constructor requires clone due to unique_ptr
MatchExpr (MatchExpr const &other);
// Overloaded assignment operator to clone due to unique_ptr
MatchExpr &operator= (MatchExpr const &other);
// move constructors
MatchExpr (MatchExpr &&other) = default;
MatchExpr &operator= (MatchExpr &&other) = default;
location_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &get_scrutinee_expr () { return *branch_value; }
AST::AttrVec get_inner_attrs () const { return inner_attrs; }
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_t locus;
public:
// TODO: ensure outer attributes are actually allowed
AwaitExpr (Analysis::NodeMapping mappings, std::unique_ptr awaited_expr,
AST::AttrVec outer_attrs, location_t locus);
// copy constructor with clone
AwaitExpr (AwaitExpr const &other);
// overloaded assignment operator with clone
AwaitExpr &operator= (AwaitExpr const &other);
// move constructors
AwaitExpr (AwaitExpr &&other) = default;
AwaitExpr &operator= (AwaitExpr &&other) = default;
std::string as_string () const override;
location_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
Expr &get_awaited_expr () { return *awaited_expr; }
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_t locus;
public:
AsyncBlockExpr (Analysis::NodeMapping mappings,
std::unique_ptr block_expr, bool has_move,
AST::AttrVec outer_attrs, location_t locus);
// copy constructor with clone
AsyncBlockExpr (AsyncBlockExpr const &other);
// overloaded assignment operator to clone
AsyncBlockExpr &operator= (AsyncBlockExpr const &other);
// move constructors
AsyncBlockExpr (AsyncBlockExpr &&other) = default;
AsyncBlockExpr &operator= (AsyncBlockExpr &&other) = default;
std::string as_string () const override;
location_t get_locus () const override final { return locus; }
bool get_has_move () const { return has_move; }
BlockExpr &get_block_expr () { return *block_expr; }
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);
OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr);
OperatorExprMeta (HIR::NegationExpr &expr);
OperatorExprMeta (HIR::DereferenceExpr &expr);
OperatorExprMeta (HIR::ArrayIndexExpr &expr);
OperatorExprMeta (HIR::ComparisonExpr &expr);
const Analysis::NodeMapping &get_mappings () const { return node_mappings; }
const Analysis::NodeMapping &get_lvalue_mappings () const
{
return lvalue_mappings;
}
location_t get_locus () const { return locus; }
private:
const Analysis::NodeMapping node_mappings;
const Analysis::NodeMapping lvalue_mappings;
location_t locus;
};
class InlineAsmReg
{
enum Kind
{
X86,
Arm,
AArch64,
RiscV,
Nvptx,
PowerPC,
Hexagon,
Mips,
S390x,
SpirV,
Wasm,
Bpf,
Avr,
Msp430,
// Placeholder for invalid register constraints for the current target
Err,
};
// this placeholder is to be removed when the definations
// of the above enums are made in a later PR/patch.
std::string placeholder;
};
class InlineAsmRegClass
{
enum Type
{
X86,
Arm,
AArch64,
RiscV,
Nvptx,
PowerPC,
Hexagon,
Mips,
S390x,
SpirV,
Wasm,
Bpf,
Avr,
Msp430,
// Placeholder for invalid register constraints for the current target
Err,
};
// this placeholder is to be removed when the definations
// of the above enums are made in a later PR/patch.
std::string placeholder;
};
class InlineAsmOperand
{
public:
struct In
{
tl::optional reg;
std::unique_ptr expr;
In (const tl::optional ®,
std::unique_ptr expr);
In (const struct In &other);
In operator= (const struct In &other);
};
struct Out
{
tl::optional reg;
bool late;
std::unique_ptr expr; // can be null
Out (tl::optional ®, bool late,
std::unique_ptr expr);
Out (const struct Out &other);
Out operator= (const struct Out &other);
};
struct InOut
{
tl::optional reg;
bool late;
std::unique_ptr expr; // this can't be null
InOut (tl::optional ®, bool late,
std::unique_ptr expr);
InOut (const struct InOut &other);
InOut operator= (const struct InOut &other);
};
struct SplitInOut
{
tl::optional reg;
bool late;
std::unique_ptr in_expr;
std::unique_ptr out_expr; // could be null
SplitInOut (tl::optional ®,
bool late, std::unique_ptr in_expr,
std::unique_ptr out_expr);
SplitInOut (const struct SplitInOut &other);
SplitInOut operator= (const struct SplitInOut &other);
};
struct Const
{
AnonConst anon_const;
};
struct Sym
{
std::unique_ptr expr;
Sym (std::unique_ptr expr);
Sym (const struct Sym &other);
Sym operator= (const struct Sym &other);
};
struct Label
{
std::string label_name;
std::unique_ptr expr;
Label (tl::optional label_name, std::unique_ptr expr);
Label (const struct Label &other);
Label operator= (const struct Label &other);
};
private:
using RegisterType = AST::InlineAsmOperand::RegisterType;
AST::InlineAsmOperand::RegisterType register_type;
tl::optional in;
tl::optional out;
tl::optional in_out;
tl::optional split_in_out;
tl::optional cnst;
tl::optional sym;
tl::optional label;
public:
InlineAsmOperand (const InlineAsmOperand &other)
: register_type (other.register_type), in (other.in), out (other.out),
in_out (other.in_out), split_in_out (other.split_in_out),
cnst (other.cnst), sym (other.sym)
{}
InlineAsmOperand (const struct In ®)
: register_type (RegisterType::In), in (reg)
{}
InlineAsmOperand (const struct Out ®)
: register_type (RegisterType::Out), out (reg)
{}
InlineAsmOperand (const struct InOut ®)
: register_type (RegisterType::InOut), in_out (reg)
{}
InlineAsmOperand (const struct SplitInOut ®)
: register_type (RegisterType::SplitInOut), split_in_out (reg)
{}
InlineAsmOperand (const struct Const ®)
: register_type (RegisterType::Const), cnst (reg)
{}
InlineAsmOperand (const struct Sym ®)
: register_type (RegisterType::Sym), sym (reg)
{}
InlineAsmOperand (const struct Label ®)
: register_type (RegisterType::Label), label (reg)
{}
RegisterType get_register_type () const { return register_type; }
// Potentially unsafe without get_register_type() check
struct In get_in () const { return in.value (); }
struct Out get_out () const { return out.value (); }
struct InOut get_in_out () const { return in_out.value (); }
struct SplitInOut get_split_in_out () const { return split_in_out.value (); }
struct Const get_const () const { return cnst.value (); }
struct Sym get_sym () const { return sym.value (); }
struct Label get_label () const { return label.value (); }
};
// Inline Assembly Node
class InlineAsm : public ExprWithoutBlock
{
NodeId id;
location_t locus;
public:
bool is_global_asm;
std::vector template_;
std::vector template_strs;
std::vector operands;
std::vector clobber_abi;
std::set options;
std::vector line_spans;
void accept_vis (HIRExpressionVisitor &vis) override;
void accept_vis (HIRFullVisitor &vis) override;
std::string as_string () const override { return "InlineAsm HIR Node"; }
location_t get_locus () const override { return locus; }
InlineAsm *clone_expr_without_block_impl () const override
{
return new InlineAsm (*this);
}
ExprType get_expression_type () const final override
{
return ExprType::InlineAsm;
}
std::vector get_template_ ()
{
return template_;
}
std::vector get_template_strs ()
{
return template_strs;
}
std::vector get_operands () { return operands; }
std::vector get_clobber_abi () { return clobber_abi; }
std::set get_options () { return options; }
bool is_simple_asm ()
{
// INFO: A simple asm is an asm that does not have any operands
return this->operands.size () == 0;
}
bool is_inline_asm ()
{
// INFO: An inline asm is asm!, which is the opposite of a global_asm()
return !this->is_global_asm;
}
InlineAsm (location_t locus, bool is_global_asm,
std::vector template_,
std::vector template_strs,
std::vector operands,
std::vector clobber_abi,
std::set options,
Analysis::NodeMapping mappings,
AST::AttrVec outer_attribs = AST::AttrVec ());
};
struct LlvmOperand
{
std::string constraint;
std::unique_ptr expr;
LlvmOperand (std::string constraint, std::unique_ptr &&expr)
: constraint (constraint), expr (std::move (expr))
{}
LlvmOperand (const LlvmOperand &other)
: constraint (other.constraint), expr (other.expr->clone_expr ())
{}
LlvmOperand &operator= (const LlvmOperand &other)
{
constraint = other.constraint;
expr = other.expr->clone_expr ();
return *this;
}
};
class LlvmInlineAsm : public ExprWithoutBlock
{
public:
struct Options
{
bool is_volatile;
bool align_stack;
AST::LlvmInlineAsm::Dialect dialect;
};
location_t locus;
AST::AttrVec outer_attrs;
std::vector inputs;
std::vector outputs;
std::vector templates;
std::vector clobbers;
Options options;
LlvmInlineAsm (location_t locus, std::vector inputs,
std::vector outputs,
std::vector templates,
std::vector clobbers, Options options,
AST::AttrVec outer_attrs, Analysis::NodeMapping mappings)
: ExprWithoutBlock (mappings, std::move (outer_attrs)), locus (locus),
inputs (std::move (inputs)), outputs (std::move (outputs)),
templates (std::move (templates)), clobbers (std::move (clobbers)),
options (options)
{}
AST::LlvmInlineAsm::Dialect get_dialect () { return options.dialect; }
location_t get_locus () const override { return locus; }
std::vector &get_outer_attrs () { return outer_attrs; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
LlvmInlineAsm *clone_expr_without_block_impl () const override
{
return new LlvmInlineAsm (*this);
}
std::vector &get_templates () { return templates; }
Expr::ExprType get_expression_type () const override
{
return Expr::ExprType::LlvmInlineAsm;
}
std::vector get_clobbers () { return clobbers; }
};
} // namespace HIR
} // namespace Rust
#endif