mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 12:38:20 +00:00
GH-927: Fix circumvention of evaluation order in 'when' conditions
Historically, a 'when' condition performed an AST-traversal to locate any index-expressions like `x[9]` and evaluated them so that it could register the associated value as something for which it needs to receive "modification" notifications. Evaluating arbitrary expressions during an AST-traversal like that ignores the typical order-of-evaluation/short-circuiting you'd expect if the condition was evaluated normally, from its root expression. Now, a new subclass of IndexExpr is used to keep track of all IndexExpr results in the context of evaluating a 'when' condition without having to do a secondary AST-traversal-and-eval. i.e. the first evaluation of the full 'when' condition follows the typical expression-evaluation semantics (as always), but additionally now captures all the values a Trigger needs to monitor for modifications.
This commit is contained in:
parent
0771dbcec6
commit
33ca675515
6 changed files with 141 additions and 29 deletions
35
src/Expr.h
35
src/Expr.h
|
@ -519,7 +519,7 @@ public:
|
|||
ValPtr Eval(Frame* f) const override;
|
||||
};
|
||||
|
||||
class IndexExpr final : public BinaryExpr {
|
||||
class IndexExpr : public BinaryExpr {
|
||||
public:
|
||||
IndexExpr(ExprPtr op1,
|
||||
ListExprPtr op2, bool is_slice = false);
|
||||
|
@ -549,6 +549,39 @@ protected:
|
|||
bool is_slice;
|
||||
};
|
||||
|
||||
class IndexExprWhen final : public IndexExpr {
|
||||
public:
|
||||
static inline std::vector<ValPtr> results = {};
|
||||
static inline int evaluating = 0;
|
||||
|
||||
static void StartEval()
|
||||
{ ++evaluating; }
|
||||
|
||||
static void EndEval()
|
||||
{ --evaluating; }
|
||||
|
||||
static std::vector<ValPtr> TakeAllResults()
|
||||
{
|
||||
auto rval = std::move(results);
|
||||
results = {};
|
||||
return rval;
|
||||
}
|
||||
|
||||
IndexExprWhen(ExprPtr op1, ListExprPtr op2, bool is_slice = false)
|
||||
: IndexExpr(std::move(op1), std::move(op2), is_slice)
|
||||
{ }
|
||||
|
||||
ValPtr Eval(Frame* f) const override
|
||||
{
|
||||
auto v = IndexExpr::Eval(f);
|
||||
|
||||
if ( v && evaluating > 0 )
|
||||
results.emplace_back(v);
|
||||
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
class FieldExpr final : public UnaryExpr {
|
||||
public:
|
||||
FieldExpr(ExprPtr op, const char* field_name);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue