mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Merge remote-tracking branch 'origin/topic/vern/add-del-expr'
* origin/topic/vern/add-del-expr: removing now-vestigial "add" and "delete" statements script optimization support for "add" and "delete" being expressions "add" and "delete" are now expressions rather than statements bug fix for dealing with illegal types of initializers added a space when rendering some expressions so they're more readable
This commit is contained in:
commit
c04e503c92
54 changed files with 738 additions and 715 deletions
12
CHANGES
12
CHANGES
|
@ -1,3 +1,15 @@
|
|||
7.0.0-dev.298 | 2024-05-29 13:49:00 -0700
|
||||
|
||||
* removing now-vestigial "add" and "delete" statements (Vern Paxson, Corelight)
|
||||
|
||||
* script optimization support for "add" and "delete" being expressions (Vern Paxson, Corelight)
|
||||
|
||||
* "add" and "delete" are now expressions rather than statements (Vern Paxson, Corelight)
|
||||
|
||||
* bug fix for dealing with illegal types of initializers (Vern Paxson, Corelight)
|
||||
|
||||
* added a space when rendering some expressions so they're more readable (Vern Paxson, Corelight)
|
||||
|
||||
7.0.0-dev.292 | 2024-05-29 14:11:57 +0100
|
||||
|
||||
* Copy timestamp from file object (mvhensbergen)
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
7.0.0-dev.292
|
||||
7.0.0-dev.298
|
||||
|
|
84
src/Expr.cc
84
src/Expr.cc
|
@ -30,6 +30,11 @@
|
|||
namespace zeek::detail {
|
||||
|
||||
const char* expr_name(ExprTag t) {
|
||||
// Note that some of the names in the following have trailing spaces.
|
||||
// These are for unary operations that (1) are identified by names
|
||||
// rather than symbols, and (2) don't have custom ExprDescribe printers.
|
||||
// Adding the spaces here lets them leverage the UnaryExpr::ExprDescribe
|
||||
// method without it having to know about such expressions.
|
||||
static const char* expr_names[int(NUM_EXPRS)] = {
|
||||
"name",
|
||||
"const",
|
||||
|
@ -42,6 +47,8 @@ const char* expr_name(ExprTag t) {
|
|||
"-",
|
||||
"+",
|
||||
"-",
|
||||
"add ",
|
||||
"delete ",
|
||||
"+=",
|
||||
"-=",
|
||||
"*",
|
||||
|
@ -211,9 +218,13 @@ bool Expr::CanAdd() const { return false; }
|
|||
|
||||
bool Expr::CanDel() const { return false; }
|
||||
|
||||
void Expr::Add(Frame* /* f */) { Internal("Expr::Add called"); }
|
||||
TypePtr Expr::AddType() const { return nullptr; }
|
||||
|
||||
void Expr::Delete(Frame* /* f */) { Internal("Expr::Delete called"); }
|
||||
TypePtr Expr::DelType() const { return nullptr; }
|
||||
|
||||
ValPtr Expr::Add(Frame* /* f */) { Internal("Expr::Add called"); }
|
||||
|
||||
ValPtr Expr::Delete(Frame* /* f */) { Internal("Expr::Delete called"); }
|
||||
|
||||
ExprPtr Expr::MakeLvalue() {
|
||||
if ( ! IsError() )
|
||||
|
@ -416,8 +427,9 @@ bool NameExpr::CanDel() const {
|
|||
return GetType()->Tag() == TYPE_TABLE || GetType()->Tag() == TYPE_VECTOR;
|
||||
}
|
||||
|
||||
void NameExpr::Delete(Frame* f) {
|
||||
if ( auto v = Eval(f) ) {
|
||||
ValPtr NameExpr::Delete(Frame* f) {
|
||||
auto v = Eval(f);
|
||||
if ( v ) {
|
||||
if ( GetType()->Tag() == TYPE_TABLE )
|
||||
v->AsTableVal()->RemoveAll();
|
||||
else if ( GetType()->Tag() == TYPE_VECTOR )
|
||||
|
@ -425,6 +437,7 @@ void NameExpr::Delete(Frame* f) {
|
|||
else
|
||||
RuntimeError("delete unsupported");
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// This isn't in-lined to avoid needing to pull in ID.h.
|
||||
|
@ -1393,6 +1406,24 @@ void AddExpr::Canonicalize() {
|
|||
SwapOps();
|
||||
}
|
||||
|
||||
AggrAddExpr::AggrAddExpr(ExprPtr _op) : AggrAddDelExpr(EXPR_AGGR_ADD, std::move(_op)) {
|
||||
if ( ! op->IsError() && ! op->CanAdd() )
|
||||
ExprError("illegal add expression");
|
||||
|
||||
SetType(op->AddType());
|
||||
}
|
||||
|
||||
ValPtr AggrAddExpr::Eval(Frame* f) const { return op->Add(f); }
|
||||
|
||||
AggrDelExpr::AggrDelExpr(ExprPtr _op) : AggrAddDelExpr(EXPR_AGGR_DEL, std::move(_op)) {
|
||||
if ( ! op->IsError() && ! op->CanDel() )
|
||||
Error("illegal delete expression");
|
||||
|
||||
SetType(op->DelType());
|
||||
}
|
||||
|
||||
ValPtr AggrDelExpr::Eval(Frame* f) const { return op->Delete(f); }
|
||||
|
||||
// True if we should treat LHS += RHS as add-every-element-of-RHS-to-LHS.
|
||||
// False for the alternative, add-RHS-as-one-element-to-LHS.
|
||||
//
|
||||
|
@ -2496,46 +2527,52 @@ bool IndexExpr::CanDel() const {
|
|||
return op1->GetType()->Tag() == TYPE_TABLE;
|
||||
}
|
||||
|
||||
void IndexExpr::Add(Frame* f) {
|
||||
ValPtr IndexExpr::Add(Frame* f) {
|
||||
if ( IsError() )
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
auto v1 = op1->Eval(f);
|
||||
|
||||
if ( ! v1 )
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
auto v2 = op2->Eval(f);
|
||||
|
||||
if ( ! v2 )
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
bool iterators_invalidated = false;
|
||||
v1->AsTableVal()->Assign(std::move(v2), nullptr, true, &iterators_invalidated);
|
||||
|
||||
if ( iterators_invalidated )
|
||||
reporter->ExprRuntimeWarning(this, "possible loop/iterator invalidation");
|
||||
|
||||
// In the future we could return a value, such as v1, here.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void IndexExpr::Delete(Frame* f) {
|
||||
ValPtr IndexExpr::Delete(Frame* f) {
|
||||
if ( IsError() )
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
auto v1 = op1->Eval(f);
|
||||
|
||||
if ( ! v1 )
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
auto v2 = op2->Eval(f);
|
||||
|
||||
if ( ! v2 )
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
bool iterators_invalidated = false;
|
||||
v1->AsTableVal()->Remove(*v2, true, &iterators_invalidated);
|
||||
auto removed = v1->AsTableVal()->Remove(*v2, true, &iterators_invalidated);
|
||||
|
||||
if ( iterators_invalidated )
|
||||
reporter->ExprRuntimeWarning(this, "possible loop/iterator invalidation");
|
||||
|
||||
// In the future we could return a value, such as removed, here.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ExprPtr IndexExpr::MakeLvalue() {
|
||||
|
@ -2756,13 +2793,24 @@ void FieldExpr::Assign(Frame* f, ValPtr v) {
|
|||
if ( IsError() )
|
||||
return;
|
||||
|
||||
if ( auto op_v = op->Eval(f) ) {
|
||||
RecordVal* r = op_v->AsRecordVal();
|
||||
r->Assign(field, std::move(v));
|
||||
}
|
||||
Assign(op->Eval(f), v);
|
||||
}
|
||||
|
||||
void FieldExpr::Delete(Frame* f) { Assign(f, nullptr); }
|
||||
void FieldExpr::Assign(ValPtr lhs, ValPtr rhs) {
|
||||
if ( lhs )
|
||||
lhs->AsRecordVal()->Assign(field, std::move(rhs));
|
||||
}
|
||||
|
||||
ValPtr FieldExpr::Delete(Frame* f) {
|
||||
auto op_v = op->Eval(f);
|
||||
if ( ! op_v )
|
||||
return nullptr;
|
||||
|
||||
auto former = op_v->AsRecordVal()->GetField(field);
|
||||
Assign(op_v, nullptr);
|
||||
// In the future we could return a value, such as former, here.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ValPtr FieldExpr::Fold(Val* v) const {
|
||||
if ( const auto& result = v->AsRecordVal()->GetField(field) )
|
||||
|
|
54
src/Expr.h
54
src/Expr.h
|
@ -46,6 +46,8 @@ enum ExprTag : int {
|
|||
EXPR_NEGATE,
|
||||
EXPR_ADD,
|
||||
EXPR_SUB,
|
||||
EXPR_AGGR_ADD,
|
||||
EXPR_AGGR_DEL,
|
||||
EXPR_ADD_TO,
|
||||
EXPR_REMOVE_FROM,
|
||||
EXPR_TIMES,
|
||||
|
@ -204,8 +206,12 @@ public:
|
|||
virtual bool CanAdd() const;
|
||||
virtual bool CanDel() const;
|
||||
|
||||
virtual void Add(Frame* f); // perform add operation
|
||||
virtual void Delete(Frame* f); // perform delete operation
|
||||
// The types associated with those operations.
|
||||
virtual TypePtr AddType() const;
|
||||
virtual TypePtr DelType() const;
|
||||
|
||||
virtual ValPtr Add(Frame* f); // perform add operation
|
||||
virtual ValPtr Delete(Frame* f); // perform delete operation
|
||||
|
||||
// Return the expression converted to L-value form. If expr
|
||||
// cannot be used as an L-value, reports an error and returns
|
||||
|
@ -421,7 +427,7 @@ public:
|
|||
explicit NameExpr(IDPtr id, bool const_init = false);
|
||||
|
||||
bool CanDel() const override;
|
||||
void Delete(Frame* f) override;
|
||||
ValPtr Delete(Frame* f) override;
|
||||
|
||||
ID* Id() const { return id.get(); }
|
||||
const IDPtr& IdPtr() const;
|
||||
|
@ -700,6 +706,41 @@ protected:
|
|||
ExprPtr BuildSub(const ExprPtr& op1, const ExprPtr& op2);
|
||||
};
|
||||
|
||||
// A helper class that enables us to factor some common code.
|
||||
class AggrAddDelExpr : public UnaryExpr {
|
||||
public:
|
||||
explicit AggrAddDelExpr(ExprTag _tag, ExprPtr _e) : UnaryExpr(_tag, std::move(_e)) {}
|
||||
|
||||
bool IsPure() const override { return false; }
|
||||
|
||||
// Optimization-related:
|
||||
bool IsReduced(Reducer* c) const override { return HasReducedOps(c); }
|
||||
bool HasReducedOps(Reducer* c) const override { return op->HasReducedOps(c); }
|
||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||
};
|
||||
|
||||
class AggrAddExpr final : public AggrAddDelExpr {
|
||||
public:
|
||||
explicit AggrAddExpr(ExprPtr e);
|
||||
|
||||
// Optimization-related:
|
||||
ExprPtr Duplicate() override;
|
||||
|
||||
protected:
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
};
|
||||
|
||||
class AggrDelExpr final : public AggrAddDelExpr {
|
||||
public:
|
||||
explicit AggrDelExpr(ExprPtr e);
|
||||
|
||||
// Optimization-related:
|
||||
ExprPtr Duplicate() override;
|
||||
|
||||
protected:
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
};
|
||||
|
||||
class AddToExpr final : public BinaryExpr {
|
||||
public:
|
||||
AddToExpr(ExprPtr op1, ExprPtr op2);
|
||||
|
@ -976,8 +1017,8 @@ public:
|
|||
bool CanAdd() const override;
|
||||
bool CanDel() const override;
|
||||
|
||||
void Add(Frame* f) override;
|
||||
void Delete(Frame* f) override;
|
||||
ValPtr Add(Frame* f) override;
|
||||
ValPtr Delete(Frame* f) override;
|
||||
|
||||
void Assign(Frame* f, ValPtr v) override;
|
||||
ExprPtr MakeLvalue() override;
|
||||
|
@ -1077,7 +1118,7 @@ public:
|
|||
bool CanDel() const override;
|
||||
|
||||
void Assign(Frame* f, ValPtr v) override;
|
||||
void Delete(Frame* f) override;
|
||||
ValPtr Delete(Frame* f) override;
|
||||
|
||||
ExprPtr MakeLvalue() override;
|
||||
|
||||
|
@ -1085,6 +1126,7 @@ public:
|
|||
ExprPtr Duplicate() override;
|
||||
|
||||
protected:
|
||||
void Assign(ValPtr lhs, ValPtr rhs);
|
||||
ValPtr Fold(Val* v) const override;
|
||||
|
||||
void ExprDescribe(ODesc* d) const override;
|
||||
|
|
45
src/Stmt.cc
45
src/Stmt.cc
|
@ -39,8 +39,6 @@ const char* stmt_name(StmtTag t) {
|
|||
"next",
|
||||
"break",
|
||||
"return",
|
||||
"add",
|
||||
"delete",
|
||||
"list",
|
||||
"bodylist",
|
||||
"<init>",
|
||||
|
@ -904,49 +902,6 @@ TraversalCode SwitchStmt::Traverse(TraversalCallback* cb) const {
|
|||
HANDLE_TC_STMT_POST(tc);
|
||||
}
|
||||
|
||||
AddDelStmt::AddDelStmt(StmtTag t, ExprPtr arg_e) : ExprStmt(t, std::move(arg_e)) {}
|
||||
|
||||
bool AddDelStmt::IsPure() const { return false; }
|
||||
|
||||
TraversalCode AddDelStmt::Traverse(TraversalCallback* cb) const {
|
||||
TraversalCode tc = cb->PreStmt(this);
|
||||
HANDLE_TC_STMT_PRE(tc);
|
||||
|
||||
// Argument is stored in base class's "e" field.
|
||||
tc = e->Traverse(cb);
|
||||
HANDLE_TC_STMT_PRE(tc);
|
||||
|
||||
tc = cb->PostStmt(this);
|
||||
HANDLE_TC_STMT_POST(tc);
|
||||
}
|
||||
|
||||
AddStmt::AddStmt(ExprPtr arg_e) : AddDelStmt(STMT_ADD, std::move(arg_e)) {
|
||||
if ( ! e->CanAdd() )
|
||||
Error("illegal add statement");
|
||||
}
|
||||
|
||||
ValPtr AddStmt::Exec(Frame* f, StmtFlowType& flow) {
|
||||
RegisterAccess();
|
||||
flow = FLOW_NEXT;
|
||||
e->Add(f);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DelStmt::DelStmt(ExprPtr arg_e) : AddDelStmt(STMT_DELETE, std::move(arg_e)) {
|
||||
if ( e->IsError() )
|
||||
return;
|
||||
|
||||
if ( ! e->CanDel() )
|
||||
Error("illegal delete statement");
|
||||
}
|
||||
|
||||
ValPtr DelStmt::Exec(Frame* f, StmtFlowType& flow) {
|
||||
RegisterAccess();
|
||||
flow = FLOW_NEXT;
|
||||
e->Delete(f);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EventStmt::EventStmt(EventExprPtr arg_e) : ExprStmt(STMT_EVENT, arg_e), event_expr(std::move(arg_e)) {}
|
||||
|
||||
ValPtr EventStmt::Exec(Frame* f, StmtFlowType& flow) {
|
||||
|
|
36
src/Stmt.h
36
src/Stmt.h
|
@ -228,42 +228,6 @@ protected:
|
|||
std::vector<std::pair<ID*, int>> case_label_type_list;
|
||||
};
|
||||
|
||||
// Helper class. Added for script optimization, but it makes sense
|
||||
// in terms of factoring even without.
|
||||
class AddDelStmt : public ExprStmt {
|
||||
public:
|
||||
TraversalCode Traverse(TraversalCallback* cb) const override;
|
||||
|
||||
bool IsPure() const override;
|
||||
|
||||
// Optimization-related:
|
||||
StmtPtr DoReduce(Reducer* c) override;
|
||||
bool IsReduced(Reducer* c) const override;
|
||||
|
||||
protected:
|
||||
AddDelStmt(StmtTag t, ExprPtr arg_e);
|
||||
};
|
||||
|
||||
class AddStmt final : public AddDelStmt {
|
||||
public:
|
||||
explicit AddStmt(ExprPtr e);
|
||||
|
||||
ValPtr Exec(Frame* f, StmtFlowType& flow) override;
|
||||
|
||||
// Optimization-related:
|
||||
StmtPtr Duplicate() override;
|
||||
};
|
||||
|
||||
class DelStmt final : public AddDelStmt {
|
||||
public:
|
||||
explicit DelStmt(ExprPtr e);
|
||||
|
||||
ValPtr Exec(Frame* f, StmtFlowType& flow) override;
|
||||
|
||||
// Optimization-related:
|
||||
StmtPtr Duplicate() override;
|
||||
};
|
||||
|
||||
class EventStmt final : public ExprStmt {
|
||||
public:
|
||||
explicit EventStmt(EventExprPtr e);
|
||||
|
|
|
@ -18,8 +18,6 @@ enum StmtTag {
|
|||
STMT_NEXT,
|
||||
STMT_BREAK,
|
||||
STMT_RETURN,
|
||||
STMT_ADD,
|
||||
STMT_DELETE,
|
||||
STMT_LIST,
|
||||
STMT_EVENT_BODY_LIST,
|
||||
STMT_INIT,
|
||||
|
|
|
@ -2537,6 +2537,11 @@ TypePtr init_type(const detail::ExprPtr& init) {
|
|||
if ( init->Tag() != detail::EXPR_LIST ) {
|
||||
auto t = init->InitType();
|
||||
|
||||
if ( ! t ) {
|
||||
init->Error("not a valid initializer");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( (t->Tag() == TYPE_TABLE && cast_intrusive<TableType>(t)->IsUnspecifiedTable()) ||
|
||||
(t->Tag() == TYPE_VECTOR && cast_intrusive<VectorType>(t)->IsUnspecifiedVector()) ) {
|
||||
init->Error("empty constructor in untyped initialization");
|
||||
|
|
30
src/parse.y
30
src/parse.y
|
@ -37,7 +37,7 @@
|
|||
%token TOK_NO_TEST
|
||||
|
||||
%left ','
|
||||
%right '=' TOK_ADD_TO TOK_REMOVE_FROM
|
||||
%right '=' TOK_ADD_TO TOK_REMOVE_FROM TOK_ADD TOK_DELETE
|
||||
%right '?' ':'
|
||||
%left TOK_OR_OR
|
||||
%left TOK_AND_AND
|
||||
|
@ -508,6 +508,18 @@ expr:
|
|||
$$ = new CloneExpr({AdoptRef{}, $3});
|
||||
}
|
||||
|
||||
| TOK_ADD expr
|
||||
{
|
||||
set_location(@1, @2);
|
||||
$$ = new AggrAddExpr({AdoptRef{}, $2});
|
||||
}
|
||||
|
||||
| TOK_DELETE expr
|
||||
{
|
||||
set_location(@1, @2);
|
||||
$$ = new AggrDelExpr({AdoptRef{}, $2});
|
||||
}
|
||||
|
||||
| TOK_INCR expr
|
||||
{
|
||||
set_location(@1, @2);
|
||||
|
@ -1934,22 +1946,6 @@ stmt:
|
|||
script_coverage_mgr.AddStmt($$);
|
||||
}
|
||||
|
||||
| TOK_ADD expr ';' opt_no_test
|
||||
{
|
||||
set_location(@1, @3);
|
||||
$$ = new AddStmt({AdoptRef{}, $2});
|
||||
if ( ! $4 )
|
||||
script_coverage_mgr.AddStmt($$);
|
||||
}
|
||||
|
||||
| TOK_DELETE expr ';' opt_no_test
|
||||
{
|
||||
set_location(@1, @3);
|
||||
$$ = new DelStmt({AdoptRef{}, $2});
|
||||
if ( ! $4 )
|
||||
script_coverage_mgr.AddStmt($$);
|
||||
}
|
||||
|
||||
| TOK_LOCAL local_id opt_type init_class opt_init opt_attr ';' opt_no_test
|
||||
{
|
||||
set_location(@1, @7);
|
||||
|
|
|
@ -688,8 +688,6 @@ private:
|
|||
void GenIfStmt(const IfStmt* i);
|
||||
void GenWhileStmt(const WhileStmt* w);
|
||||
void GenReturnStmt(const ReturnStmt* r);
|
||||
void GenAddStmt(const ExprStmt* es);
|
||||
void GenDeleteStmt(const ExprStmt* es);
|
||||
void GenEventStmt(const EventStmt* ev);
|
||||
|
||||
void GenSwitchStmt(const SwitchStmt* sw);
|
||||
|
@ -757,6 +755,8 @@ private:
|
|||
|
||||
std::string GenNameExpr(const NameExpr* ne, GenType gt);
|
||||
std::string GenConstExpr(const ConstExpr* c, GenType gt);
|
||||
std::string GenAggrAdd(const Expr* e);
|
||||
std::string GenAggrDel(const Expr* e);
|
||||
std::string GenIncrExpr(const Expr* e, GenType gt, bool is_incr, bool top_level);
|
||||
std::string GenCondExpr(const Expr* e, GenType gt);
|
||||
std::string GenCallExpr(const CallExpr* c, GenType gt, bool top_level);
|
||||
|
|
|
@ -52,6 +52,9 @@ string CPPCompile::GenExpr(const Expr* e, GenType gt, bool top_level) {
|
|||
gen = GenExpr(e->GetOp1(), GEN_VAL_PTR) + "->Clone()";
|
||||
return GenericValPtrToGT(gen, e->GetType(), gt);
|
||||
|
||||
case EXPR_AGGR_ADD: return GenAggrAdd(e);
|
||||
case EXPR_AGGR_DEL: return GenAggrDel(e);
|
||||
|
||||
case EXPR_INCR:
|
||||
case EXPR_DECR: return GenIncrExpr(e, gt, e->Tag() == EXPR_INCR, top_level);
|
||||
|
||||
|
@ -183,6 +186,39 @@ string CPPCompile::GenConstExpr(const ConstExpr* c, GenType gt) {
|
|||
return NativeToGT(GenVal(c->ValuePtr()), t, gt);
|
||||
}
|
||||
|
||||
string CPPCompile::GenAggrAdd(const Expr* e) {
|
||||
auto op = e->GetOp1();
|
||||
auto aggr = GenExpr(op->GetOp1(), GEN_DONT_CARE);
|
||||
auto indices = GenExpr(op->GetOp2(), GEN_VAL_PTR);
|
||||
|
||||
return "add_element__CPP(" + aggr + ", index_val__CPP({" + indices + "}))";
|
||||
}
|
||||
|
||||
string CPPCompile::GenAggrDel(const Expr* e) {
|
||||
auto op = e->GetOp1();
|
||||
|
||||
if ( op->Tag() == EXPR_NAME ) {
|
||||
auto aggr_gen = GenExpr(op, GEN_VAL_PTR);
|
||||
|
||||
if ( op->GetType()->Tag() == TYPE_TABLE )
|
||||
return aggr_gen + "->RemoveAll()";
|
||||
else
|
||||
return aggr_gen + "->Resize(0)";
|
||||
}
|
||||
|
||||
auto aggr = op->GetOp1();
|
||||
auto aggr_gen = GenExpr(aggr, GEN_VAL_PTR);
|
||||
|
||||
if ( op->Tag() == EXPR_INDEX ) {
|
||||
auto indices = GenExpr(op->GetOp2(), GEN_VAL_PTR);
|
||||
return "remove_element__CPP(" + aggr_gen + ", index_val__CPP({" + indices + "}))";
|
||||
}
|
||||
|
||||
ASSERT(op->Tag() == EXPR_FIELD);
|
||||
auto field = GenField(aggr, op->AsFieldExpr()->Field());
|
||||
return aggr_gen + "->Remove(" + field + ")";
|
||||
}
|
||||
|
||||
string CPPCompile::GenIncrExpr(const Expr* e, GenType gt, bool is_incr, bool top_level) {
|
||||
// For compound operands (table indexing, record fields),
|
||||
// Zeek's interpreter will actually evaluate the operand
|
||||
|
|
|
@ -39,10 +39,6 @@ void CPPCompile::GenStmt(const Stmt* s) {
|
|||
|
||||
case STMT_RETURN: GenReturnStmt(s->AsReturnStmt()); break;
|
||||
|
||||
case STMT_ADD: GenAddStmt(static_cast<const ExprStmt*>(s)); break;
|
||||
|
||||
case STMT_DELETE: GenDeleteStmt(static_cast<const ExprStmt*>(s)); break;
|
||||
|
||||
case STMT_EVENT: GenEventStmt(static_cast<const EventStmt*>(s)); break;
|
||||
|
||||
case STMT_SWITCH: GenSwitchStmt(static_cast<const SwitchStmt*>(s)); break;
|
||||
|
@ -149,41 +145,6 @@ void CPPCompile::GenReturnStmt(const ReturnStmt* r) {
|
|||
}
|
||||
}
|
||||
|
||||
void CPPCompile::GenAddStmt(const ExprStmt* es) {
|
||||
auto op = es->StmtExpr();
|
||||
auto aggr = GenExpr(op->GetOp1(), GEN_DONT_CARE);
|
||||
auto indices = op->GetOp2();
|
||||
|
||||
Emit("add_element__CPP(%s, index_val__CPP({%s}));", aggr, GenExpr(indices, GEN_VAL_PTR));
|
||||
}
|
||||
|
||||
void CPPCompile::GenDeleteStmt(const ExprStmt* es) {
|
||||
auto op = es->StmtExpr();
|
||||
|
||||
if ( op->Tag() == EXPR_NAME ) {
|
||||
if ( op->GetType()->Tag() == TYPE_TABLE )
|
||||
Emit("%s->RemoveAll();", GenExpr(op, GEN_VAL_PTR));
|
||||
else
|
||||
Emit("%s->Resize(0);", GenExpr(op, GEN_VAL_PTR));
|
||||
return;
|
||||
}
|
||||
|
||||
auto aggr = op->GetOp1();
|
||||
auto aggr_gen = GenExpr(aggr, GEN_VAL_PTR);
|
||||
|
||||
if ( op->Tag() == EXPR_INDEX ) {
|
||||
auto indices = op->GetOp2();
|
||||
|
||||
Emit("remove_element__CPP(%s, index_val__CPP({%s}));", aggr_gen, GenExpr(indices, GEN_VAL_PTR));
|
||||
}
|
||||
|
||||
else {
|
||||
ASSERT(op->Tag() == EXPR_FIELD);
|
||||
auto field = GenField(aggr, op->AsFieldExpr()->Field());
|
||||
Emit("%s->Remove(%s);", aggr_gen, field);
|
||||
}
|
||||
}
|
||||
|
||||
void CPPCompile::GenEventStmt(const EventStmt* ev) {
|
||||
auto ev_s = ev->StmtExprPtr();
|
||||
auto ev_e = cast_intrusive<EventExpr>(ev_s);
|
||||
|
|
|
@ -38,16 +38,6 @@ TraversalCode CSE_ValidityChecker::PreStmt(const Stmt* s) {
|
|||
return TC_ABORTALL;
|
||||
}
|
||||
|
||||
if ( t == STMT_ADD || t == STMT_DELETE )
|
||||
in_aggr_mod_stmt = true;
|
||||
|
||||
return TC_CONTINUE;
|
||||
}
|
||||
|
||||
TraversalCode CSE_ValidityChecker::PostStmt(const Stmt* s) {
|
||||
if ( s->Tag() == STMT_ADD || s->Tag() == STMT_DELETE )
|
||||
in_aggr_mod_stmt = false;
|
||||
|
||||
return TC_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -120,6 +110,9 @@ TraversalCode CSE_ValidityChecker::PreExpr(const Expr* e) {
|
|||
}
|
||||
} break;
|
||||
|
||||
case EXPR_AGGR_ADD:
|
||||
case EXPR_AGGR_DEL: ++in_aggr_mod_expr; break;
|
||||
|
||||
case EXPR_APPEND_TO:
|
||||
// This doesn't directly change any identifiers, but does
|
||||
// alter an aggregate.
|
||||
|
@ -155,7 +148,7 @@ TraversalCode CSE_ValidityChecker::PreExpr(const Expr* e) {
|
|||
auto aggr = e->GetOp1();
|
||||
auto aggr_t = aggr->GetType();
|
||||
|
||||
if ( in_aggr_mod_stmt ) {
|
||||
if ( in_aggr_mod_expr > 0 ) {
|
||||
auto aggr_id = aggr->AsNameExpr()->Id();
|
||||
|
||||
if ( CheckID(aggr_id, true) || CheckAggrMod(aggr_t) )
|
||||
|
@ -174,6 +167,13 @@ TraversalCode CSE_ValidityChecker::PreExpr(const Expr* e) {
|
|||
return TC_CONTINUE;
|
||||
}
|
||||
|
||||
TraversalCode CSE_ValidityChecker::PostExpr(const Expr* e) {
|
||||
if ( have_start_e && (e->Tag() == EXPR_AGGR_ADD || e->Tag() == EXPR_AGGR_DEL) )
|
||||
--in_aggr_mod_expr;
|
||||
|
||||
return TC_CONTINUE;
|
||||
}
|
||||
|
||||
bool CSE_ValidityChecker::CheckID(const ID* id, bool ignore_orig) {
|
||||
for ( auto i : ids ) {
|
||||
if ( ignore_orig && i == ids.front() )
|
||||
|
|
|
@ -21,8 +21,8 @@ public:
|
|||
const Expr* end_e);
|
||||
|
||||
TraversalCode PreStmt(const Stmt*) override;
|
||||
TraversalCode PostStmt(const Stmt*) override;
|
||||
TraversalCode PreExpr(const Expr*) override;
|
||||
TraversalCode PostExpr(const Expr*) override;
|
||||
|
||||
// Returns the ultimate verdict re safety.
|
||||
bool IsValid() const {
|
||||
|
@ -99,10 +99,12 @@ protected:
|
|||
bool have_start_e = false;
|
||||
bool have_end_e = false;
|
||||
|
||||
// Whether analyzed expressions occur in the context of a statement
|
||||
// Whether analyzed expressions occur in the context of an expression
|
||||
// that modifies an aggregate ("add" or "delete"), which changes the
|
||||
// interpretation of the expressions.
|
||||
bool in_aggr_mod_stmt = false;
|
||||
//
|
||||
// A count to allow for nesting.
|
||||
int in_aggr_mod_expr = 0;
|
||||
};
|
||||
|
||||
// Used for debugging, to communicate which expression wasn't
|
||||
|
|
|
@ -723,6 +723,21 @@ ExprPtr AddExpr::BuildSub(const ExprPtr& op1, const ExprPtr& op2) {
|
|||
return with_location_of(make_intrusive<SubExpr>(op1, rhs), this);
|
||||
}
|
||||
|
||||
ExprPtr AggrAddDelExpr::Reduce(Reducer* c, StmtPtr& red_stmt) {
|
||||
if ( type )
|
||||
return UnaryExpr::Reduce(c, red_stmt);
|
||||
|
||||
if ( c->Optimizing() )
|
||||
op = c->UpdateExpr(op);
|
||||
|
||||
red_stmt = op->ReduceToSingletons(c);
|
||||
return ThisPtr();
|
||||
}
|
||||
|
||||
ExprPtr AggrAddExpr::Duplicate() { return SetSucc(new AggrAddExpr(op->Duplicate())); }
|
||||
|
||||
ExprPtr AggrDelExpr::Duplicate() { return SetSucc(new AggrDelExpr(op->Duplicate())); }
|
||||
|
||||
ExprPtr AddToExpr::Duplicate() {
|
||||
auto op1_d = op1->Duplicate();
|
||||
auto op2_d = op2->Duplicate();
|
||||
|
|
|
@ -157,17 +157,6 @@ TraversalCode ProfileFunc::PreStmt(const Stmt* s) {
|
|||
expr_switches.insert(sw);
|
||||
} break;
|
||||
|
||||
case STMT_ADD:
|
||||
case STMT_DELETE: {
|
||||
auto ad_stmt = static_cast<const AddDelStmt*>(s);
|
||||
auto ad_e = ad_stmt->StmtExpr();
|
||||
auto lhs = ad_e->GetOp1();
|
||||
if ( lhs )
|
||||
aggr_mods.insert(lhs->GetType().get());
|
||||
else
|
||||
aggr_mods.insert(ad_e->GetType().get());
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -339,6 +328,15 @@ TraversalCode ProfileFunc::PreExpr(const Expr* e) {
|
|||
}
|
||||
} break;
|
||||
|
||||
case EXPR_AGGR_ADD:
|
||||
case EXPR_AGGR_DEL: {
|
||||
auto lhs = e->GetOp1();
|
||||
if ( lhs )
|
||||
aggr_mods.insert(lhs->GetType().get());
|
||||
else
|
||||
aggr_mods.insert(e->GetType().get());
|
||||
} break;
|
||||
|
||||
case EXPR_CALL: {
|
||||
auto c = e->AsCallExpr();
|
||||
auto args = c->Args();
|
||||
|
|
|
@ -486,26 +486,6 @@ bool SwitchStmt::CouldReturn(bool ignore_break) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool AddDelStmt::IsReduced(Reducer* c) const { return e->HasReducedOps(c); }
|
||||
|
||||
StmtPtr AddDelStmt::DoReduce(Reducer* c) {
|
||||
if ( c->Optimizing() ) {
|
||||
e = c->OptExpr(e);
|
||||
return ThisPtr();
|
||||
}
|
||||
|
||||
auto red_e_stmt = e->ReduceToSingletons(c);
|
||||
|
||||
if ( red_e_stmt )
|
||||
return TransformMe(make_intrusive<StmtList>(red_e_stmt, ThisPtr()), c);
|
||||
else
|
||||
return ThisPtr();
|
||||
}
|
||||
|
||||
StmtPtr AddStmt::Duplicate() { return SetSucc(new AddStmt(e->Duplicate())); }
|
||||
|
||||
StmtPtr DelStmt::Duplicate() { return SetSucc(new DelStmt(e->Duplicate())); }
|
||||
|
||||
StmtPtr EventStmt::Duplicate() { return SetSucc(new EventStmt(e->Duplicate()->AsEventExprPtr())); }
|
||||
|
||||
StmtPtr EventStmt::DoReduce(Reducer* c) {
|
||||
|
|
|
@ -223,8 +223,6 @@ UDs UseDefs::PropagateUDs(const Stmt* s, UDs succ_UDs, const Stmt* succ_stmt, bo
|
|||
|
||||
case STMT_EVENT:
|
||||
case STMT_CHECK_ANY_LEN:
|
||||
case STMT_ADD:
|
||||
case STMT_DELETE:
|
||||
case STMT_RETURN: {
|
||||
auto e = static_cast<const ExprStmt*>(s)->StmtExpr();
|
||||
|
||||
|
@ -436,6 +434,19 @@ UDs UseDefs::ExprUDs(const Expr* e) {
|
|||
break;
|
||||
}
|
||||
|
||||
case EXPR_AGGR_ADD:
|
||||
case EXPR_AGGR_DEL: {
|
||||
auto op = e->GetOp1();
|
||||
if ( op->Tag() == EXPR_INDEX ) {
|
||||
AddInExprUDs(uds, op->GetOp1().get());
|
||||
auto rhs_UDs = ExprUDs(op->GetOp2().get());
|
||||
uds = UD_Union(uds, rhs_UDs);
|
||||
}
|
||||
else
|
||||
AddInExprUDs(uds, op.get());
|
||||
break;
|
||||
}
|
||||
|
||||
case EXPR_INCR:
|
||||
case EXPR_DECR: AddInExprUDs(uds, e->GetOp1()->AsRefExprPtr()->GetOp1().get()); break;
|
||||
|
||||
|
|
|
@ -137,8 +137,6 @@ private:
|
|||
const ZAMStmt CompileExpr(const ExprStmt* es);
|
||||
const ZAMStmt CompileIf(const IfStmt* is);
|
||||
const ZAMStmt CompileSwitch(const SwitchStmt* sw);
|
||||
const ZAMStmt CompileAdd(const AddStmt* as);
|
||||
const ZAMStmt CompileDel(const DelStmt* ds);
|
||||
const ZAMStmt CompileWhile(const WhileStmt* ws);
|
||||
const ZAMStmt CompileFor(const ForStmt* f);
|
||||
const ZAMStmt CompileReturn(const ReturnStmt* r);
|
||||
|
@ -186,6 +184,8 @@ private:
|
|||
|
||||
const ZAMStmt CompileIncrExpr(const IncrExpr* e);
|
||||
const ZAMStmt CompileAppendToExpr(const AppendToExpr* e);
|
||||
const ZAMStmt CompileAdd(const AggrAddExpr* e);
|
||||
const ZAMStmt CompileDel(const AggrDelExpr* e);
|
||||
const ZAMStmt CompileAddToExpr(const AddToExpr* e);
|
||||
const ZAMStmt CompileRemoveFromExpr(const RemoveFromExpr* e);
|
||||
const ZAMStmt CompileAssignExpr(const AssignExpr* e);
|
||||
|
|
|
@ -16,6 +16,10 @@ const ZAMStmt ZAMCompiler::CompileExpr(const Expr* e) {
|
|||
|
||||
case EXPR_APPEND_TO: return CompileAppendToExpr(static_cast<const AppendToExpr*>(e));
|
||||
|
||||
case EXPR_AGGR_ADD: return CompileAdd(static_cast<const AggrAddExpr*>(e));
|
||||
|
||||
case EXPR_AGGR_DEL: return CompileDel(static_cast<const AggrDelExpr*>(e));
|
||||
|
||||
case EXPR_ADD_TO: return CompileAddToExpr(static_cast<const AddToExpr*>(e));
|
||||
|
||||
case EXPR_REMOVE_FROM: return CompileRemoveFromExpr(static_cast<const RemoveFromExpr*>(e));
|
||||
|
@ -78,6 +82,56 @@ const ZAMStmt ZAMCompiler::CompileAppendToExpr(const AppendToExpr* e) {
|
|||
return n2 ? AppendToVV(n1, n2) : AppendToVC(n1, cc);
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileAdd(const AggrAddExpr* e) {
|
||||
auto op = e->GetOp1();
|
||||
auto aggr = op->GetOp1()->AsNameExpr();
|
||||
auto index_list = op->GetOp2();
|
||||
|
||||
if ( index_list->Tag() != EXPR_LIST )
|
||||
reporter->InternalError("non-list in \"add\"");
|
||||
|
||||
auto indices = index_list->AsListExprPtr();
|
||||
auto& exprs = indices->Exprs();
|
||||
|
||||
if ( exprs.length() == 1 ) {
|
||||
auto e1 = exprs[0];
|
||||
if ( e1->Tag() == EXPR_NAME )
|
||||
return AddStmt1VV(aggr, e1->AsNameExpr());
|
||||
else
|
||||
return AddStmt1VC(aggr, e1->AsConstExpr());
|
||||
}
|
||||
|
||||
return AddStmtVO(aggr, BuildVals(indices));
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileDel(const AggrDelExpr* e) {
|
||||
auto op = e->GetOp1();
|
||||
|
||||
if ( op->Tag() == EXPR_NAME ) {
|
||||
auto n = op->AsNameExpr();
|
||||
|
||||
if ( n->GetType()->Tag() == TYPE_TABLE )
|
||||
return ClearTableV(n);
|
||||
else
|
||||
return ClearVectorV(n);
|
||||
}
|
||||
|
||||
auto aggr = op->GetOp1()->AsNameExpr();
|
||||
|
||||
if ( op->Tag() == EXPR_FIELD ) {
|
||||
int field = op->AsFieldExpr()->Field();
|
||||
return DelFieldVi(aggr, field);
|
||||
}
|
||||
|
||||
auto index_list = op->GetOp2();
|
||||
|
||||
if ( index_list->Tag() != EXPR_LIST )
|
||||
reporter->InternalError("non-list in \"delete\"");
|
||||
|
||||
auto internal_ind = std::unique_ptr<OpaqueVals>(BuildVals(index_list->AsListExprPtr()));
|
||||
return DelTableVO(aggr, internal_ind.get());
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileAddToExpr(const AddToExpr* e) {
|
||||
auto op1 = e->GetOp1();
|
||||
auto t1 = op1->GetType()->Tag();
|
||||
|
|
|
@ -28,10 +28,6 @@ const ZAMStmt ZAMCompiler::CompileStmt(const Stmt* s) {
|
|||
|
||||
case STMT_SWITCH: return CompileSwitch(static_cast<const SwitchStmt*>(s));
|
||||
|
||||
case STMT_ADD: return CompileAdd(static_cast<const AddStmt*>(s));
|
||||
|
||||
case STMT_DELETE: return CompileDel(static_cast<const DelStmt*>(s));
|
||||
|
||||
case STMT_EVENT: {
|
||||
auto es = static_cast<const EventStmt*>(s);
|
||||
auto e = static_cast<const EventExpr*>(es->StmtExpr());
|
||||
|
@ -623,56 +619,6 @@ const ZAMStmt ZAMCompiler::TypeSwitch(const SwitchStmt* sw, const NameExpr* v, c
|
|||
return body_end;
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileAdd(const AddStmt* as) {
|
||||
auto e = as->StmtExprPtr();
|
||||
auto aggr = e->GetOp1()->AsNameExpr();
|
||||
auto index_list = e->GetOp2();
|
||||
|
||||
if ( index_list->Tag() != EXPR_LIST )
|
||||
reporter->InternalError("non-list in \"add\"");
|
||||
|
||||
auto indices = index_list->AsListExprPtr();
|
||||
auto& exprs = indices->Exprs();
|
||||
|
||||
if ( exprs.length() == 1 ) {
|
||||
auto e1 = exprs[0];
|
||||
if ( e1->Tag() == EXPR_NAME )
|
||||
return AddStmt1VV(aggr, e1->AsNameExpr());
|
||||
else
|
||||
return AddStmt1VC(aggr, e1->AsConstExpr());
|
||||
}
|
||||
|
||||
return AddStmtVO(aggr, BuildVals(indices));
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileDel(const DelStmt* ds) {
|
||||
auto e = ds->StmtExprPtr();
|
||||
|
||||
if ( e->Tag() == EXPR_NAME ) {
|
||||
auto n = e->AsNameExpr();
|
||||
|
||||
if ( n->GetType()->Tag() == TYPE_TABLE )
|
||||
return ClearTableV(n);
|
||||
else
|
||||
return ClearVectorV(n);
|
||||
}
|
||||
|
||||
auto aggr = e->GetOp1()->AsNameExpr();
|
||||
|
||||
if ( e->Tag() == EXPR_FIELD ) {
|
||||
int field = e->AsFieldExpr()->Field();
|
||||
return DelFieldVi(aggr, field);
|
||||
}
|
||||
|
||||
auto index_list = e->GetOp2();
|
||||
|
||||
if ( index_list->Tag() != EXPR_LIST )
|
||||
reporter->InternalError("non-list in \"delete\"");
|
||||
|
||||
auto internal_ind = std::unique_ptr<OpaqueVals>(BuildVals(index_list->AsListExprPtr()));
|
||||
return DelTableVO(aggr, internal_ind.get());
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileWhile(const WhileStmt* ws) {
|
||||
auto loop_condition = ws->Condition();
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||
error in <...>/wrong-delete-field.zeek, line 10: illegal delete statement (delete x$a)
|
||||
error in <...>/wrong-delete-field.zeek, line 10: illegal delete expression (delete x$a)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue