Lambdas selectively clone from the closure.

This commit is contained in:
Zeke Medley 2019-06-21 12:02:41 -07:00
parent 63117de050
commit 8257a644d3
6 changed files with 62 additions and 39 deletions

View file

@ -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);
} }

View file

@ -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

View file

@ -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()

View file

@ -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;

View file

@ -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

View file

@ -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;