reductions of expressions in ASTs - code compiles but doesn't yet link

This commit is contained in:
Vern Paxson 2021-01-10 14:04:01 -08:00
parent 6aa84087b0
commit 10e80dfcd3
8 changed files with 3264 additions and 164 deletions

View file

@ -68,6 +68,15 @@ enum BroExprTag : int {
EXPR_IS,
EXPR_INDEX_SLICE_ASSIGN,
EXPR_INLINE,
// The following types of expressions are only created for
// ASTs transformed to reduced form; they aren't germane for
// ASTs produced by parsing .zeek script files.
EXPR_INDEX_ASSIGN, EXPR_FIELD_LHS_ASSIGN,
EXPR_APPEND_TO,
EXPR_TO_ANY_COERCE, EXPR_FROM_ANY_COERCE,
EXPR_ANY_INDEX,
EXPR_NOP,
#define NUM_EXPRS (int(EXPR_NOP) + 1)
@ -75,18 +84,27 @@ enum BroExprTag : int {
extern const char* expr_name(BroExprTag t);
class ListExpr;
class NameExpr;
class ConstExpr;
class IndexExpr;
class AssignExpr;
class CallExpr;
class ConstExpr;
class EventExpr;
class Stmt;
class FieldAssignExpr;
class FieldExpr;
class ForExpr;
class IndexExpr;
class ListExpr;
class NameExpr;
class RefExpr;
class Expr;
using ExprPtr = IntrusivePtr<Expr>;
using CallExprPtr = IntrusivePtr<CallExpr>;
using ConstExprPtr = IntrusivePtr<ConstExpr>;
using EventExprPtr = IntrusivePtr<EventExpr>;
using ExprPtr = IntrusivePtr<Expr>;
using NameExprPtr = IntrusivePtr<NameExpr>;
using RefExprPtr = IntrusivePtr<RefExpr>;
class Stmt;
using StmtPtr = IntrusivePtr<Stmt>;
class Expr : public Obj {
@ -182,13 +200,17 @@ public:
ctype* As ## ctype (); \
IntrusivePtr<ctype> As ## ctype ## Ptr ();
ZEEK_EXPR_ACCESSOR_DECLS(AssignExpr)
ZEEK_EXPR_ACCESSOR_DECLS(CallExpr)
ZEEK_EXPR_ACCESSOR_DECLS(ConstExpr)
ZEEK_EXPR_ACCESSOR_DECLS(EventExpr)
ZEEK_EXPR_ACCESSOR_DECLS(FieldAssignExpr)
ZEEK_EXPR_ACCESSOR_DECLS(FieldExpr)
ZEEK_EXPR_ACCESSOR_DECLS(ForExpr)
ZEEK_EXPR_ACCESSOR_DECLS(IndexExpr)
ZEEK_EXPR_ACCESSOR_DECLS(ListExpr)
ZEEK_EXPR_ACCESSOR_DECLS(NameExpr)
ZEEK_EXPR_ACCESSOR_DECLS(ConstExpr)
ZEEK_EXPR_ACCESSOR_DECLS(CallExpr)
ZEEK_EXPR_ACCESSOR_DECLS(AssignExpr)
ZEEK_EXPR_ACCESSOR_DECLS(IndexExpr)
ZEEK_EXPR_ACCESSOR_DECLS(EventExpr)
ZEEK_EXPR_ACCESSOR_DECLS(RefExpr)
void Describe(ODesc* d) const override final;
@ -200,6 +222,117 @@ public:
// Recursively traverses the AST to inline eligible function calls.
virtual ExprPtr Inline(Inliner* inl) { return ThisPtr(); }
// True if the expression can serve as an operand to a reduced
// expression.
bool IsSingleton(Reducer* r) const
{
return (tag == EXPR_NAME && IsReduced(r)) || tag == EXPR_CONST;
}
// True if the expression has no side effects, false otherwise.
virtual bool HasNoSideEffects() const { return IsPure(); }
// True if the expression is in fully reduced form: a singleton
// or an assignment to an operator with singleton operands.
virtual bool IsReduced(Reducer* c) const;
// True if the expression's operands are singletons.
virtual bool HasReducedOps(Reducer* c) const;
// True if (a) the expression has at least one operand, and (b) all
// of its operands are constant.
bool HasConstantOps() const
{
return GetOp1() && GetOp1()->IsConst() &&
(! GetOp2() ||
(GetOp2()->IsConst() &&
(! GetOp3() || GetOp3()->IsConst())));
}
// True if the expression is reduced to a form that can be
// used in a conditional.
bool IsReducedConditional(Reducer* c) const;
// True if the expression is reduced to a form that can be
// used in a field assignment.
bool IsReducedFieldAssignment(Reducer* c) const;
// True if this expression can be the RHS for a field assignment.
bool IsFieldAssignable(const Expr* e) const;
// True if the expression will transform to one of another type
// upon reduction, for non-constant operands. "Transform" means
// something beyond assignment to a temporary. Necessary so that
// we know to fully reduce such expressions if they're the RHS
// of an assignment.
virtual bool WillTransform(Reducer* c) const { return false; }
// The same, but for the expression when used in a conditional context.
virtual bool WillTransformInConditional(Reducer* c) const
{ return false; }
// Returns the current expression transformed into "new_me".
// Takes a bare pointer for "new_me" since often it's newly
// allocated.
ExprPtr TransformMe(Expr* new_me, Reducer* c, StmtPtr& red_stmt);
ExprPtr TransformMe(ExprPtr new_me, Reducer* c, StmtPtr& red_stmt)
{ return TransformMe(new_me.get(), c, red_stmt); }
// Returns a set of predecessor statements in red_stmt (which might
// be nil if no reduction necessary), and the reduced version of
// the expression, suitable for replacing previous uses. The
// second version always yields a singleton suitable for use
// as an operand. The first version does this too except
// for assignment statements; thus, its form is not guarantee
// suitable for use as an operand.
virtual ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt);
virtual ExprPtr ReduceToSingleton(Reducer* c, StmtPtr& red_stmt)
{ return Reduce(c, red_stmt); }
// Reduces the expression to one whose operands are singletons.
// Returns a predecessor statement (which might be a StmtList), if any.
virtual StmtPtr ReduceToSingletons(Reducer* c);
// Reduces the expression to one that can appear as a conditional.
ExprPtr ReduceToConditional(Reducer* c, StmtPtr& red_stmt);
// Reduces the expression to one that can appear as a field
// assignment.
ExprPtr ReduceToFieldAssignment(Reducer* c, StmtPtr& red_stmt);
// Helper function for factoring out complexities related to
// index-based assignment.
void AssignToIndex(ValPtr v1, ValPtr v2, ValPtr v3) const;
// Returns a new expression corresponding to a temporary
// that's been assigned to the given expression via red_stmt.
ExprPtr AssignToTemporary(ExprPtr e, Reducer* c, StmtPtr& red_stmt);
// Same but for this expression.
ExprPtr AssignToTemporary(Reducer* c, StmtPtr& red_stmt)
{ return AssignToTemporary(ThisPtr(), c, red_stmt); }
// If the expression always evaluates to the same value, returns
// that value. Otherwise, returns nullptr.
virtual ValPtr FoldVal() const { return nullptr; }
// Returns a Val or a constant Expr corresponding to zero.
ValPtr MakeZero(TypeTag t) const;
ConstExprPtr MakeZeroExpr(TypeTag t) const;
// Returns the expression's operands, or nil if it doesn't
// have the given operand.
virtual ExprPtr GetOp1() const;
virtual ExprPtr GetOp2() const;
virtual ExprPtr GetOp3() const;
// Sets the operands to new values.
virtual void SetOp1(ExprPtr new_op);
virtual void SetOp2(ExprPtr new_op);
virtual void SetOp3(ExprPtr new_op);
// Helper function to reduce boring code runs.
StmtPtr MergeStmts(StmtPtr s1, StmtPtr s2, StmtPtr s3 = nullptr) const;
// Access to the original expression from which this one is derived,
// or this one if we don't have an original. Returns a bare pointer
// rather than an ExprPtr to emphasize that the access is read-only.
@ -272,6 +405,7 @@ public:
explicit NameExpr(IDPtr id, bool const_init = false);
ID* Id() const { return id.get(); }
IDPtr IdPtr();
ValPtr Eval(Frame* f) const override;
void Assign(Frame* f, ValPtr v) override;
@ -282,10 +416,20 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool HasNoSideEffects() const override { return true; }
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override { return IsReduced(c); }
bool WillTransform(Reducer* c) const override { return ! IsReduced(c); }
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
ValPtr FoldVal() const override;
protected:
void ExprDescribe(ODesc* d) const override;
// Returns true if our identifier is a global with a constant value
// that can be propagated; used for optimization.
bool FoldableGlobal() const;
IDPtr id;
bool in_const_init;
};
@ -303,6 +447,7 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
ValPtr FoldVal() const override { return val; }
protected:
void ExprDescribe(ODesc* d) const override;
@ -325,6 +470,14 @@ public:
// Optimization-related:
ExprPtr Inline(Inliner* inl) override;
bool HasNoSideEffects() const override;
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
ExprPtr GetOp1() const override final { return op; }
void SetOp1(ExprPtr _op) override final { op = std::move(_op); }
protected:
UnaryExpr(BroExprTag arg_tag, ExprPtr arg_op);
@ -353,6 +506,17 @@ public:
// Optimization-related:
ExprPtr Inline(Inliner* inl) override;
bool HasNoSideEffects() const override;
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
ExprPtr GetOp1() const override final { return op1; }
ExprPtr GetOp2() const override final { return op2; }
void SetOp1(ExprPtr _op) override final { std::move(op1 = _op); }
void SetOp2(ExprPtr _op) override final { std::move(op2 = _op); }
protected:
BinaryExpr(BroExprTag arg_tag,
ExprPtr arg_op1, ExprPtr arg_op2)
@ -425,6 +589,12 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool HasNoSideEffects() const override;
bool WillTransform(Reducer* c) const override { return true; }
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override { return false; }
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
ExprPtr ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) override;
};
class ComplementExpr final : public UnaryExpr {
@ -433,6 +603,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected:
ValPtr Fold(Val* v) const override;
@ -444,6 +616,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected:
ValPtr Fold(Val* v) const override;
@ -455,6 +629,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected:
ValPtr Fold(Val* v) const override;
@ -466,6 +642,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected:
ValPtr Fold(Val* v) const override;
@ -490,6 +668,11 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected:
ExprPtr BuildSub(const ExprPtr& op1, const ExprPtr& op2);
};
class AddToExpr final : public BinaryExpr {
@ -499,6 +682,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override { return true; }
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
};
class RemoveFromExpr final : public BinaryExpr {
@ -508,6 +693,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override { return true; }
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
};
class SubExpr final : public BinaryExpr {
@ -516,6 +703,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
};
class TimesExpr final : public BinaryExpr {
@ -525,6 +714,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
};
class DivideExpr final : public BinaryExpr {
@ -533,6 +724,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected:
ValPtr AddrFold(Val* v1, Val* v2) const override;
@ -555,6 +748,13 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override { return true; }
bool WillTransformInConditional(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected:
bool IsTrue(const ExprPtr& e) const;
bool IsFalse(const ExprPtr& e) const;
};
class BitExpr final : public BinaryExpr {
@ -563,6 +763,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
};
class EqExpr final : public BinaryExpr {
@ -572,6 +774,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected:
ValPtr Fold(Val* v1, Val* v2) const override;
@ -584,6 +788,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
};
class CondExpr final : public Expr {
@ -603,6 +809,20 @@ public:
ExprPtr Duplicate() override;
ExprPtr Inline(Inliner* inl) override;
bool WillTransform(Reducer* c) const override;
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
StmtPtr ReduceToSingletons(Reducer* c) override;
ExprPtr GetOp1() const override final { return op1; }
ExprPtr GetOp2() const override final { return op2; }
ExprPtr GetOp3() const override final { return op3; }
void SetOp1(ExprPtr _op) override final { op1 = std::move(_op); }
void SetOp2(ExprPtr _op) override final { op2 = std::move(_op); }
void SetOp3(ExprPtr _op) override final { op3 = std::move(_op); }
protected:
void ExprDescribe(ODesc* d) const override;
@ -620,6 +840,14 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
// Reduce to simplifed LHS form, i.e., a reference to only a name.
StmtPtr ReduceToLHS(Reducer* c);
};
class AssignExpr : public BinaryExpr {
@ -628,7 +856,8 @@ public:
// yet still perform the assignment. Used for triggers.
AssignExpr(ExprPtr op1, ExprPtr op2, bool is_init,
ValPtr val = nullptr,
const AttributesPtr& attrs = nullptr);
const AttributesPtr& attrs = nullptr,
bool type_check = true);
ValPtr Eval(Frame* f) const override;
void EvalIntoAggregate(const zeek::Type* t, Val* aggr, Frame* f) const override;
@ -637,20 +866,29 @@ public:
ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override;
bool IsPure() const override;
void SetOp2(ExprPtr e)
{
op2 = std::move(e);
}
// Optimization-related:
ExprPtr Duplicate() override;
bool HasNoSideEffects() const override;
bool WillTransform(Reducer* c) const override { return true; }
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
ExprPtr ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) override;
// Whether this is an assignment to a temporary.
bool IsTemp() const { return is_temp; }
void SetIsTemp() { is_temp = true; }
protected:
bool TypeCheck(const AttributesPtr& attrs = nullptr);
bool TypeCheckArithmetics(TypeTag bt1, TypeTag bt2);
bool is_init;
ValPtr val; // optional
// Optimization-related:
bool is_temp = false;
};
class IndexSliceAssignExpr final : public AssignExpr {
@ -688,6 +926,9 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool HasReducedOps(Reducer* c) const override;
StmtPtr ReduceToSingletons(Reducer* c) override;
protected:
ValPtr Fold(Val* v1, Val* v2) const override;
@ -797,6 +1038,10 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
StmtPtr ReduceToSingletons(Reducer* c) override;
protected:
ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override;
@ -823,6 +1068,10 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
StmtPtr ReduceToSingletons(Reducer* c) override;
protected:
ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override;
@ -849,6 +1098,10 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
StmtPtr ReduceToSingletons(Reducer* c) override;
protected:
ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override;
@ -867,6 +1120,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool HasReducedOps(Reducer* c) const override;
protected:
ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override;
@ -885,6 +1140,9 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override { return true; }
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected:
void ExprDescribe(ODesc* d) const override;
@ -898,6 +1156,9 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool WillTransform(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected:
ValPtr FoldSingleVal(Val* v, InternalTypeTag t) const;
ValPtr Fold(Val* v) const override;
@ -974,6 +1235,16 @@ public:
ExprPtr Duplicate() override;
ExprPtr Inline(Inliner* inl) override;
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
ExprPtr GetOp1() const override final;
ExprPtr GetOp2() const override final;
void SetOp1(ExprPtr _op) override final;
void SetOp2(ExprPtr _op) override final;
protected:
void ExprDescribe(ODesc* d) const override;
@ -988,6 +1259,8 @@ public:
// Optimization-related:
ExprPtr Duplicate() override;
bool HasReducedOps(Reducer* c) const override;
protected:
ValPtr Fold(Val* v1, Val* v2) const override;
@ -1011,6 +1284,11 @@ public:
ExprPtr Duplicate() override;
ExprPtr Inline(Inliner* inl) override;
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
StmtPtr ReduceToSingletons(Reducer* c) override;
protected:
void ExprDescribe(ODesc* d) const override;
@ -1038,6 +1316,8 @@ public:
ExprPtr Duplicate() override;
ExprPtr Inline(Inliner* inl) override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected:
void ExprDescribe(ODesc* d) const override;
@ -1048,30 +1328,8 @@ private:
std::string my_name;
};
class EventExpr final : public Expr {
public:
EventExpr(const char* name, ListExprPtr args);
const char* Name() const { return name.c_str(); }
ListExpr* Args() const { return args.get(); }
EventHandlerPtr Handler() const { return handler; }
ValPtr Eval(Frame* f) const override;
TraversalCode Traverse(TraversalCallback* cb) const override;
// Optimization-related:
ExprPtr Duplicate() override;
ExprPtr Inline(Inliner* inl) override;
protected:
void ExprDescribe(ODesc* d) const override;
std::string name;
EventHandlerPtr handler;
ListExprPtr args;
};
// This comes before EventExpr so that EventExpr::GetOp1 can return its
// arguments as convertible to ExprPtr.
class ListExpr : public Expr {
public:
ListExpr();
@ -1099,6 +1357,11 @@ public:
ExprPtr Duplicate() override;
ExprPtr Inline(Inliner* inl) override;
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
StmtPtr ReduceToSingletons(Reducer* c) override;
protected:
ValPtr AddSetInit(const zeek::Type* t, ValPtr aggr) const;
@ -1107,6 +1370,38 @@ protected:
ExprPList exprs;
};
class EventExpr final : public Expr {
public:
EventExpr(const char* name, ListExprPtr args);
const char* Name() const { return name.c_str(); }
ListExpr* Args() const { return args.get(); }
EventHandlerPtr Handler() const { return handler; }
ValPtr Eval(Frame* f) const override;
TraversalCode Traverse(TraversalCallback* cb) const override;
// Optimization-related:
ExprPtr Duplicate() override;
ExprPtr Inline(Inliner* inl) override;
bool IsReduced(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
StmtPtr ReduceToSingletons(Reducer* c) override;
ExprPtr GetOp1() const override final { return args; }
void SetOp1(ExprPtr _op) override final
{ args = {NewRef{}, _op->AsListExpr()}; }
protected:
void ExprDescribe(ODesc* d) const override;
std::string name;
EventHandlerPtr handler;
ListExprPtr args;
};
class RecordAssignExpr final : public ListExpr {
public:
@ -1155,6 +1450,9 @@ public:
ExprPtr Duplicate() override;
bool IsReduced(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
TraversalCode Traverse(TraversalCallback* cb) const override;
protected:
@ -1166,6 +1464,134 @@ protected:
StmtPtr body;
};
// A companion to AddToExpr that's for vector-append, instantiated during
// the reduction process.
class AppendToExpr : public BinaryExpr {
public:
AppendToExpr(ExprPtr op1, ExprPtr op2);
ValPtr Eval(Frame* f) const override;
bool IsReduced(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
ExprPtr Duplicate() override;
};
// An internal class for reduced form.
class IndexAssignExpr : public BinaryExpr {
public:
// "op1[op2] = op3", all reduced.
IndexAssignExpr(ExprPtr op1, ExprPtr op2, ExprPtr op3);
ValPtr Eval(Frame* f) const override;
ExprPtr Duplicate() override;
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
ExprPtr ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) override;
ExprPtr GetOp3() const override final { return op3; }
void SetOp3(ExprPtr _op) override final { op3 = _op; }
TraversalCode Traverse(TraversalCallback* cb) const override;
protected:
void ExprDescribe(ODesc* d) const override;
ExprPtr op3; // assignment RHS
};
// An internal class for reduced form.
class FieldLHSAssignExpr : public BinaryExpr {
public:
// "op1$field = RHS", where RHS is reduced with respect to
// ReduceToFieldAssignment().
FieldLHSAssignExpr(ExprPtr op1, ExprPtr op2, const char* field_name,
int field);
const char* FieldName() const { return field_name; }
int Field() const { return field; }
ValPtr Eval(Frame* f) const override;
ExprPtr Duplicate() override;
bool IsReduced(Reducer* c) const override;
bool HasReducedOps(Reducer* c) const override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
ExprPtr ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) override;
protected:
void ExprDescribe(ODesc* d) const override;
const char* field_name;
int field;
};
// Expression to explicitly capture conversion to an "any" type, rather
// than it occurring implicitly during script interpretation.
class CoerceToAnyExpr : public UnaryExpr {
public:
CoerceToAnyExpr(ExprPtr op);
protected:
ValPtr Fold(Val* v) const override;
ExprPtr Duplicate() override;
};
// Same, but for conversion from an "any" type.
class CoerceFromAnyExpr : public UnaryExpr {
public:
CoerceFromAnyExpr(ExprPtr op, TypePtr to_type);
protected:
ValPtr Fold(Val* v) const override;
ExprPtr Duplicate() override;
};
// Expression used to explicitly capture [a, b, c, ...] = x assignments.
class AnyIndexExpr : public UnaryExpr {
public:
AnyIndexExpr(ExprPtr op, int index);
int Index() const { return index; }
protected:
ValPtr Fold(Val* v) const override;
void ExprDescribe(ODesc* d) const override;
ExprPtr Duplicate() override;
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
int index;
};
// Used internally for optimization, when a placeholder is needed.
class NopExpr : public Expr {
public:
explicit NopExpr() : Expr(EXPR_NOP) { }
ValPtr Eval(Frame* f) const override;
ExprPtr Duplicate() override;
TraversalCode Traverse(TraversalCallback* cb) const override;
protected:
void ExprDescribe(ODesc* d) const override;
};
// Assigns v1[v2] = v3. Returns an error message, or nullptr on success.
// Factored out so that compiled code can call it as well as the interpreter.
extern const char* assign_to_index(ValPtr v1, ValPtr v2, ValPtr v3,
bool& iterators_invalidated);
inline Val* Expr::ExprVal() const
{