void
DefaultASTVisitor::visit (AST::AnonConst &expr)
{
- visit (expr.get_inner_expr ());
+ if (!expr.is_deferred ())
+ visit (expr.get_inner_expr ());
}
void
std::string
AnonConst::as_string () const
{
- return "AnonConst: " + expr->as_string ();
+ std::string str = "AnonConst: ";
+
+ if (kind == AnonConst::Kind::DeferredInference)
+ str += "_";
+ else
+ str += expr.value ()->as_string ();
+
+ return str;
}
std::string
ArrayType::as_string () const
{
// TODO: rewrite to work with non-linearisable types and exprs
- return "[" + elem_type->as_string () + "; " + size->as_string () + "]";
+ return "[" + elem_type->as_string () + "; " + size.as_string () + "]";
}
std::string
#ifndef RUST_AST_EXPR_H
#define RUST_AST_EXPR_H
+#include "optional.h"
#include "rust-ast.h"
#include "rust-common.h"
#include "rust-path.h"
class AnonConst : public ExprWithBlock
{
public:
+ enum class Kind
+ {
+ Explicit,
+ DeferredInference,
+ };
+
AnonConst (std::unique_ptr<Expr> &&expr, location_t locus = UNKNOWN_LOCATION)
- : ExprWithBlock (), locus (locus), expr (std::move (expr))
+ : ExprWithBlock (), locus (locus), kind (Kind::Explicit),
+ expr (std::move (expr))
{
- rust_assert (this->expr);
+ rust_assert (this->expr.value ());
}
+ AnonConst (location_t locus = UNKNOWN_LOCATION)
+ : ExprWithBlock (), locus (locus), kind (Kind::DeferredInference),
+ expr (tl::nullopt)
+ {}
+
AnonConst (const AnonConst &other)
{
node_id = other.node_id;
locus = other.locus;
- expr = other.expr->clone_expr ();
+ kind = other.kind;
+
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
}
AnonConst operator= (const AnonConst &other)
{
node_id = other.node_id;
locus = other.locus;
- expr = other.expr->clone_expr ();
+ kind = other.kind;
+
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
return *this;
}
Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstExpr; }
location_t get_locus () const override { return locus; }
- Expr &get_inner_expr () { return *expr; }
+
+ Expr &get_inner_expr ()
+ {
+ rust_assert (expr.has_value ());
+ return *expr.value ();
+ }
+
NodeId get_node_id () const override { return node_id; }
/* FIXME: AnonConst are always "internal" and should not have outer attributes
void accept_vis (ASTVisitor &vis) override;
+ bool is_deferred () const { return kind == Kind::DeferredInference; }
+
private:
location_t locus;
- std::unique_ptr<Expr> expr;
+ Kind kind;
+ tl::optional<std::unique_ptr<Expr>> expr;
AnonConst *clone_expr_with_block_impl () const override
{
#include "optional.h"
#include "rust-ast.h"
+#include "rust-expr.h"
#include "rust-path.h"
namespace Rust {
class ArrayType : public TypeNoBounds
{
std::unique_ptr<Type> elem_type;
- std::unique_ptr<Expr> size;
+ AnonConst size;
location_t locus;
public:
// Constructor requires pointers for polymorphism
- ArrayType (std::unique_ptr<Type> type, std::unique_ptr<Expr> array_size,
- location_t locus)
+ ArrayType (std::unique_ptr<Type> type, AnonConst array_size, location_t locus)
: elem_type (std::move (type)), size (std::move (array_size)), locus (locus)
{}
// Copy constructor requires deep copies of both unique pointers
ArrayType (ArrayType const &other)
- : elem_type (other.elem_type->clone_type ()),
- size (other.size->clone_expr ()), locus (other.locus)
+ : elem_type (other.elem_type->clone_type ()), size (other.size),
+ locus (other.locus)
{}
// Overload assignment operator to deep copy pointers
ArrayType &operator= (ArrayType const &other)
{
elem_type = other.elem_type->clone_type ();
- size = other.size->clone_expr ();
+ size = other.size;
locus = other.locus;
return *this;
}
}
// TODO: would a "vis_expr" be better?
- Expr &get_size_expr ()
+ AnonConst &get_size_expr ()
{
- rust_assert (size != nullptr);
- return *size;
+ // rust_assert (size != nullptr);
+
+ return size;
}
std::unique_ptr<Type> &get_element_type () { return elem_type; }
- // Additional getter for direct access to the size expr unique_ptr
- std::unique_ptr<Expr> &get_size_ptr () { return size; }
-
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
}
ArrayType *reconstruct_impl () const override
{
- return new ArrayType (
- elem_type->reconstruct (),
- size->clone_expr () /* FIXME: This should be `reconstruct_expr()` */,
- locus);
+ return new ArrayType (elem_type->reconstruct (),
+ size /* FIXME: This should be `reconstruct_expr()` */,
+ locus);
}
};
/* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h
* This is also the reason why there are no include guards. */
+#include "expected.h"
+#include "rust-ast.h"
#include "rust-common.h"
#include "rust-expr.h"
#include "rust-item.h"
#include "rust-common.h"
+#include "rust-parse.h"
#include "rust-token.h"
#define INCLUDE_ALGORITHM
#include "rust-diagnostics.h"
std::move (label), locus, end_locus));
}
+/* Parse an anonymous const expression. This can be a regular const expression
+ * or an underscore for deferred const inference */
+template <typename ManagedTokenSource>
+tl::expected<AST::AnonConst, AnonConstError>
+Parser<ManagedTokenSource>::parse_anon_const ()
+{
+ auto current = lexer.peek_token ();
+ auto locus = current->get_locus ();
+
+ // Special case deferred inference constants
+ if (maybe_skip_token (UNDERSCORE))
+ return AST::AnonConst (locus);
+
+ auto expr = parse_expr ();
+
+ if (!expr)
+ return tl::make_unexpected (AnonConstError::InvalidSizeExpr);
+
+ return AST::AnonConst (std::move (expr), locus);
+}
+
/* Parse a "const block", a block preceded by the `const` keyword whose
* statements can be const evaluated and used in constant contexts */
template <typename ManagedTokenSource>
lexer.skip_token ();
// parse required array size expression
- std::unique_ptr<AST::Expr> size = parse_expr ();
- if (size == nullptr)
+ auto size = parse_anon_const ();
+
+ if (!size)
{
Error error (lexer.peek_token ()->get_locus (),
"failed to parse size expression in array type");
}
return std::unique_ptr<AST::ArrayType> (
- new AST::ArrayType (std::move (inner_type), std::move (size), locus));
+ new AST::ArrayType (std::move (inner_type), std::move (*size),
+ locus));
}
default:
// error
class ParseLifetimeError
{
};
+
+enum class AnonConstError
+{
+ InvalidSizeExpr,
+};
+
enum class ParseLoopLabelError
{
NOT_LOOP_LABEL,
MISSING_COLON,
};
+
enum class ParseSelfError
{
SELF_PTR,
tl::optional<AST::LoopLabel> = tl::nullopt,
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
+ tl::expected<AST::AnonConst, AnonConstError> parse_anon_const ();
+
std::unique_ptr<AST::ConstBlock>
parse_const_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
location_t loc = UNKNOWN_LOCATION);