mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 08:38:20 +00:00
Lambdas selectively clone from the closure.
This commit is contained in:
parent
63117de050
commit
8257a644d3
6 changed files with 62 additions and 39 deletions
52
src/Frame.cc
52
src/Frame.cc
|
@ -126,7 +126,8 @@ void Frame::Clear()
|
||||||
Frame* Frame::Clone()
|
Frame* Frame::Clone()
|
||||||
{
|
{
|
||||||
Frame* f = new Frame(size, function, func_args);
|
Frame* f = new Frame(size, function, func_args);
|
||||||
|
f->Clear();
|
||||||
|
|
||||||
for ( int i = 0; i < size; ++i )
|
for ( int i = 0; i < size; ++i )
|
||||||
f->frame[i] = frame[i] ? frame[i]->Clone() : 0;
|
f->frame[i] = frame[i] ? frame[i]->Clone() : 0;
|
||||||
|
|
||||||
|
@ -138,6 +139,19 @@ Frame* Frame::Clone()
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Frame* Frame::SelectiveClone(id_list* selection)
|
||||||
|
{
|
||||||
|
Frame* other = new Frame(size, function, func_args);
|
||||||
|
|
||||||
|
loop_over_list(*selection, i)
|
||||||
|
{
|
||||||
|
ID* current = (*selection)[i];
|
||||||
|
other->frame[current->Offset()] = this->frame[current->Offset()];
|
||||||
|
}
|
||||||
|
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
void Frame::SetTrigger(Trigger* arg_trigger)
|
void Frame::SetTrigger(Trigger* arg_trigger)
|
||||||
{
|
{
|
||||||
ClearTrigger();
|
ClearTrigger();
|
||||||
|
@ -211,6 +225,30 @@ Frame* ClosureFrame::Clone()
|
||||||
return cf;
|
return cf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Frame* ClosureFrame::SelectiveClone(id_list* choose)
|
||||||
|
{
|
||||||
|
id_list us;
|
||||||
|
// and
|
||||||
|
id_list them;
|
||||||
|
|
||||||
|
loop_over_list(*choose, i)
|
||||||
|
{
|
||||||
|
ID* we = (*choose)[i];
|
||||||
|
if (closure_contains(we))
|
||||||
|
us.append(we);
|
||||||
|
else
|
||||||
|
them.append(we);
|
||||||
|
}
|
||||||
|
|
||||||
|
Frame* me = this->closure->SelectiveClone(&us);
|
||||||
|
// and
|
||||||
|
Frame* you = this->body->SelectiveClone(&them);
|
||||||
|
|
||||||
|
ClosureFrame* who = new ClosureFrame(me, you, nullptr);
|
||||||
|
who->closure_elements = this->closure_elements;
|
||||||
|
|
||||||
|
return who;
|
||||||
|
}
|
||||||
|
|
||||||
// Each ClosureFrame knows all of the outer IDs that are used inside of it. This is known at
|
// Each ClosureFrame knows all of the outer IDs that are used inside of it. This is known at
|
||||||
// parse time. These leverage that. If frame_1 encloses frame_2 then the location of a lookup
|
// parse time. These leverage that. If frame_1 encloses frame_2 then the location of a lookup
|
||||||
|
@ -225,13 +263,10 @@ Val* ClosureFrame::GatherFromClosure(const Frame* start, const ID* id)
|
||||||
{
|
{
|
||||||
const ClosureFrame* conductor = dynamic_cast<const ClosureFrame*>(start);
|
const ClosureFrame* conductor = dynamic_cast<const ClosureFrame*>(start);
|
||||||
|
|
||||||
auto closure_contains = [] (const ClosureFrame* cf, const ID* i)
|
|
||||||
{ return cf->closure_elements.find(i->Name()) != cf->closure_elements.end(); };
|
|
||||||
|
|
||||||
if ( ! conductor )
|
if ( ! conductor )
|
||||||
return start->NthElement(id->Offset());
|
return start->NthElement(id->Offset());
|
||||||
|
|
||||||
if (closure_contains(conductor, id))
|
if (conductor->closure_contains(id))
|
||||||
return ClosureFrame::GatherFromClosure(conductor->closure, id);
|
return ClosureFrame::GatherFromClosure(conductor->closure, id);
|
||||||
|
|
||||||
return conductor->NthElement(id->Offset());
|
return conductor->NthElement(id->Offset());
|
||||||
|
@ -241,13 +276,12 @@ void ClosureFrame::SetInClosure(Frame* start, const ID* id, Val* val)
|
||||||
{
|
{
|
||||||
ClosureFrame* conductor = dynamic_cast<ClosureFrame*>(start);
|
ClosureFrame* conductor = dynamic_cast<ClosureFrame*>(start);
|
||||||
|
|
||||||
auto closure_contains = [] (const ClosureFrame* cf, const ID* i)
|
|
||||||
{ return cf->closure_elements.find(i->Name()) != cf->closure_elements.end(); };
|
|
||||||
|
|
||||||
if ( ! conductor )
|
if ( ! conductor )
|
||||||
start->SetElement(id->Offset(), val);
|
start->SetElement(id->Offset(), val);
|
||||||
else if (closure_contains(conductor, id))
|
|
||||||
|
else if (conductor->closure_contains(id))
|
||||||
ClosureFrame::SetInClosure(conductor->closure, id, val);
|
ClosureFrame::SetInClosure(conductor->closure, id, val);
|
||||||
|
|
||||||
else
|
else
|
||||||
conductor->Frame::SetElement(id->Offset(), val);
|
conductor->Frame::SetElement(id->Offset(), val);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ public:
|
||||||
// Deep-copies values.
|
// Deep-copies values.
|
||||||
virtual Frame* Clone();
|
virtual Frame* Clone();
|
||||||
// Only deep-copies values corresponding to requested IDs.
|
// Only deep-copies values corresponding to requested IDs.
|
||||||
Frame* SelectiveClone(id_list* selection);
|
virtual Frame* SelectiveClone(id_list* selection);
|
||||||
|
|
||||||
// If the frame is run in the context of a trigger condition evaluation,
|
// If the frame is run in the context of a trigger condition evaluation,
|
||||||
// the trigger needs to be registered.
|
// the trigger needs to be registered.
|
||||||
|
@ -112,6 +112,7 @@ public:
|
||||||
Val* GetElement(ID* id) const override;
|
Val* GetElement(ID* id) const override;
|
||||||
void SetElement(const ID* id, Val* v) override;
|
void SetElement(const ID* id, Val* v) override;
|
||||||
Frame* Clone() override;
|
Frame* Clone() override;
|
||||||
|
Frame* SelectiveClone(id_list* selection) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Frame* closure;
|
Frame* closure;
|
||||||
|
@ -123,6 +124,9 @@ private:
|
||||||
// Moves through the closure frames and associates val with id.
|
// Moves through the closure frames and associates val with id.
|
||||||
static void SetInClosure(Frame* start, const ID* id, Val* val);
|
static void SetInClosure(Frame* start, const ID* id, Val* val);
|
||||||
|
|
||||||
|
bool closure_contains(const ID* i) const
|
||||||
|
{ return this->closure_elements.find(i->Name()) != this->closure_elements.end(); }
|
||||||
|
|
||||||
// Hashes c style strings. The strings need to be null-terminated.
|
// Hashes c style strings. The strings need to be null-terminated.
|
||||||
struct const_char_hasher {
|
struct const_char_hasher {
|
||||||
size_t operator()(const char* in) const
|
size_t operator()(const char* in) const
|
||||||
|
|
18
src/Func.cc
18
src/Func.cc
|
@ -488,23 +488,7 @@ void BroFunc::SetClosureFrame(Frame* f)
|
||||||
reporter->InternalError
|
reporter->InternalError
|
||||||
("Tried to override closure for BroFunc %s.", this->Name());
|
("Tried to override closure for BroFunc %s.", this->Name());
|
||||||
|
|
||||||
this->closure = f ? f->Clone() : nullptr;
|
this->closure = f ? f->SelectiveClone(this->outer_ids.get()) : nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
void BroFunc::ShiftOffsets(int shift, std::shared_ptr<id_list> idl)
|
|
||||||
{
|
|
||||||
id_list* tmp = idl.get();
|
|
||||||
if (! idl || shift == 0)
|
|
||||||
{
|
|
||||||
// Nothing to do here.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loop_over_list(*tmp, i)
|
|
||||||
{
|
|
||||||
ID* id = (*tmp)[i];
|
|
||||||
id->SetOffset(id->Offset() + shift);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* BroFunc::DoClone()
|
Val* BroFunc::DoClone()
|
||||||
|
|
|
@ -421,7 +421,6 @@ TraversalCode OuterIDBindingFinder::PreExpr(const Expr* expr)
|
||||||
|
|
||||||
const NameExpr* e = static_cast<const NameExpr*>(expr);
|
const NameExpr* e = static_cast<const NameExpr*>(expr);
|
||||||
|
|
||||||
// TODO: Do we need to capture these as well?
|
|
||||||
if ( e->Id()->IsGlobal() )
|
if ( e->Id()->IsGlobal() )
|
||||||
return TC_CONTINUE;
|
return TC_CONTINUE;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
expect: 3
|
expect: 4
|
||||||
3
|
4
|
||||||
expect: 5
|
expect: 8
|
||||||
5
|
8
|
||||||
expect: 5
|
expect: 8
|
||||||
5
|
8
|
||||||
expect: T
|
expect: T
|
||||||
T
|
T
|
||||||
expect: T
|
expect: T
|
||||||
|
|
|
@ -1,24 +1,26 @@
|
||||||
# @TEST-EXEC: zeek -b %INPUT >out
|
# @TEST-EXEC: zeek -b %INPUT >out
|
||||||
# @TEST-EXEC: btest-diff out
|
# @TEST-EXEC: btest-diff out
|
||||||
|
|
||||||
|
global numberone : count = 1;
|
||||||
|
|
||||||
function make_count_upper (start : count) : function(step : count) : count
|
function make_count_upper (start : count) : function(step : count) : count
|
||||||
{
|
{
|
||||||
return function(step : count) : count
|
return function(step : count) : count
|
||||||
{ return (start += step); };
|
{ return (start += (step + numberone)); };
|
||||||
}
|
}
|
||||||
|
|
||||||
event zeek_init()
|
event zeek_init()
|
||||||
{
|
{
|
||||||
# basic
|
# basic
|
||||||
local one = make_count_upper(1);
|
local one = make_count_upper(1);
|
||||||
print "expect: 3";
|
print "expect: 4";
|
||||||
print one(2);
|
print one(2);
|
||||||
|
|
||||||
# multiple instances
|
# multiple instances
|
||||||
local two = make_count_upper(one(1));
|
local two = make_count_upper(one(1));
|
||||||
print "expect: 5";
|
print "expect: 8";
|
||||||
print two(1);
|
print two(1);
|
||||||
print "expect: 5";
|
print "expect: 8";
|
||||||
print one(1);
|
print one(1);
|
||||||
|
|
||||||
# deep copies
|
# deep copies
|
||||||
|
@ -26,7 +28,7 @@ event zeek_init()
|
||||||
print "expect: T";
|
print "expect: T";
|
||||||
print c(1) == one(1);
|
print c(1) == one(1);
|
||||||
print "expect: T";
|
print "expect: T";
|
||||||
print c(1) == two(2);
|
print c(1) == two(3);
|
||||||
|
|
||||||
# a little more complicated ...
|
# a little more complicated ...
|
||||||
local cat_dog = 100;
|
local cat_dog = 100;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue