mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 16:18:19 +00:00
support for conditional expressions transforming into interal has-elements expr
This commit is contained in:
parent
86d3c932b7
commit
52f506b7ae
2 changed files with 66 additions and 1 deletions
|
@ -329,6 +329,11 @@ public:
|
||||||
// Reduces the expression to one that can appear as a conditional.
|
// Reduces the expression to one that can appear as a conditional.
|
||||||
ExprPtr ReduceToConditional(Reducer* c, StmtPtr& red_stmt);
|
ExprPtr ReduceToConditional(Reducer* c, StmtPtr& red_stmt);
|
||||||
|
|
||||||
|
// Transforms the expression into its form suitable for use in
|
||||||
|
// a conditional. Only meaningful for expressions that return true
|
||||||
|
// for WillTransformInConditional().
|
||||||
|
virtual ExprPtr TransformToConditional(Reducer* c, StmtPtr& red_stmt);
|
||||||
|
|
||||||
// Reduces the expression to one that can appear as a field
|
// Reduces the expression to one that can appear as a field
|
||||||
// assignment.
|
// assignment.
|
||||||
ExprPtr ReduceToFieldAssignment(Reducer* c, StmtPtr& red_stmt);
|
ExprPtr ReduceToFieldAssignment(Reducer* c, StmtPtr& red_stmt);
|
||||||
|
@ -806,6 +811,7 @@ public:
|
||||||
bool WillTransform(Reducer* c) const override;
|
bool WillTransform(Reducer* c) const override;
|
||||||
bool WillTransformInConditional(Reducer* c) const override;
|
bool WillTransformInConditional(Reducer* c) const override;
|
||||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||||
|
ExprPtr TransformToConditional(Reducer* c, StmtPtr& red_stmt) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool IsTrue(const ExprPtr& e) const;
|
bool IsTrue(const ExprPtr& e) const;
|
||||||
|
|
|
@ -274,6 +274,18 @@ StmtPtr Expr::ReduceToSingletons(Reducer* c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprPtr Expr::ReduceToConditional(Reducer* c, StmtPtr& red_stmt) {
|
ExprPtr Expr::ReduceToConditional(Reducer* c, StmtPtr& red_stmt) {
|
||||||
|
if ( WillTransformInConditional(c) ) {
|
||||||
|
auto new_me = TransformToConditional(c, red_stmt);
|
||||||
|
|
||||||
|
// Now that we've transformed, reduce the result for use in a
|
||||||
|
// conditional.
|
||||||
|
StmtPtr red_stmt2;
|
||||||
|
new_me = new_me->ReduceToConditional(c, red_stmt2);
|
||||||
|
red_stmt = MergeStmts(red_stmt, red_stmt2);
|
||||||
|
|
||||||
|
return new_me;
|
||||||
|
}
|
||||||
|
|
||||||
switch ( tag ) {
|
switch ( tag ) {
|
||||||
case EXPR_CONST: return ThisPtr();
|
case EXPR_CONST: return ThisPtr();
|
||||||
|
|
||||||
|
@ -355,6 +367,13 @@ ExprPtr Expr::ReduceToConditional(Reducer* c, StmtPtr& red_stmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExprPtr Expr::TransformToConditional(Reducer* c, StmtPtr& red_stmt) {
|
||||||
|
// This shouldn't happen since every expression that can return
|
||||||
|
// true for WillTransformInConditional() should implement this
|
||||||
|
// method.
|
||||||
|
reporter->InternalError("Expr::TransformToConditional called");
|
||||||
|
}
|
||||||
|
|
||||||
ExprPtr Expr::ReduceToFieldAssignment(Reducer* c, StmtPtr& red_stmt) {
|
ExprPtr Expr::ReduceToFieldAssignment(Reducer* c, StmtPtr& red_stmt) {
|
||||||
if ( ! IsFieldAssignable(this) || tag == EXPR_NAME )
|
if ( ! IsFieldAssignable(this) || tag == EXPR_NAME )
|
||||||
return ReduceToSingleton(c, red_stmt);
|
return ReduceToSingleton(c, red_stmt);
|
||||||
|
@ -1291,7 +1310,7 @@ bool CondExpr::IsReduced(Reducer* c) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CondExpr::HasReducedOps(Reducer* c) const {
|
bool CondExpr::HasReducedOps(Reducer* c) const {
|
||||||
return op1->IsSingleton(c) && op2->IsSingleton(c) && op3->IsSingleton(c) && ! op1->IsConst();
|
return ! IsMinOrMax(c) && op1->IsSingleton(c) && op2->IsSingleton(c) && op3->IsSingleton(c) && ! op1->IsConst();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CondExpr::WillTransform(Reducer* c) const { return ! HasReducedOps(c); }
|
bool CondExpr::WillTransform(Reducer* c) const { return ! HasReducedOps(c); }
|
||||||
|
@ -1303,6 +1322,16 @@ ExprPtr CondExpr::Reduce(Reducer* c, StmtPtr& red_stmt) {
|
||||||
op3 = c->UpdateExpr(op3);
|
op3 = c->UpdateExpr(op3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while ( op1->Tag() == EXPR_NOT ) {
|
||||||
|
op1 = op1->GetOp1();
|
||||||
|
std::swap(op2, op3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( IsMinOrMax(c) ) {
|
||||||
|
auto res = TransformToMinOrMax();
|
||||||
|
return res->Reduce(c, red_stmt);
|
||||||
|
}
|
||||||
|
|
||||||
StmtPtr op1_red_stmt;
|
StmtPtr op1_red_stmt;
|
||||||
op1 = op1->ReduceToSingleton(c, op1_red_stmt);
|
op1 = op1->ReduceToSingleton(c, op1_red_stmt);
|
||||||
|
|
||||||
|
@ -1391,6 +1420,36 @@ StmtPtr CondExpr::ReduceToSingletons(Reducer* c) {
|
||||||
return MergeStmts(red1_stmt, if_else);
|
return MergeStmts(red1_stmt, if_else);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CondExpr::IsMinOrMax(Reducer* c) const {
|
||||||
|
switch ( op1->Tag() ) {
|
||||||
|
case EXPR_LT:
|
||||||
|
case EXPR_LE:
|
||||||
|
case EXPR_GE:
|
||||||
|
case EXPR_GT: break;
|
||||||
|
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto relop1 = op1->GetOp1();
|
||||||
|
auto relop2 = op1->GetOp2();
|
||||||
|
|
||||||
|
return (same_expr(relop1, op2) && same_expr(relop2, op3)) || (same_expr(relop1, op3) && same_expr(relop2, op2));
|
||||||
|
}
|
||||||
|
|
||||||
|
ExprPtr CondExpr::TransformToMinOrMax() const {
|
||||||
|
auto relop1 = op1->GetOp1();
|
||||||
|
auto relop2 = op1->GetOp2();
|
||||||
|
|
||||||
|
auto is_min = (op1->Tag() == EXPR_LT || op1->Tag() == EXPR_LE);
|
||||||
|
|
||||||
|
if ( same_expr(relop1, op3) )
|
||||||
|
is_min = ! is_min;
|
||||||
|
|
||||||
|
auto built_in = is_min ? ScriptOptBuiltinExpr::MINIMUM : ScriptOptBuiltinExpr::MAXIMUM;
|
||||||
|
|
||||||
|
return with_location_of(make_intrusive<ScriptOptBuiltinExpr>(built_in, relop1, relop2), this);
|
||||||
|
}
|
||||||
|
|
||||||
ExprPtr RefExpr::Duplicate() { return SetSucc(new RefExpr(op->Duplicate())); }
|
ExprPtr RefExpr::Duplicate() { return SetSucc(new RefExpr(op->Duplicate())); }
|
||||||
|
|
||||||
bool RefExpr::IsReduced(Reducer* c) const {
|
bool RefExpr::IsReduced(Reducer* c) const {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue