Call parent constructor from LambdaExpr.

This commit is contained in:
Zeke Medley 2019-07-01 10:36:21 -07:00
parent f47390f66a
commit 409f27955b
10 changed files with 37 additions and 51 deletions

@ -1 +1 @@
Subproject commit f9b347738f1edff486d64fe8c8fdfea2e6c98996
Subproject commit 539c2d82534345c62ba9a20c2e98ea5cbdea9c7e

2
doc

@ -1 +1 @@
Subproject commit d57b3ad38b2b1ecfd9f1d51699b5fcb785178bf7
Subproject commit 69a337c5c7958014566f138bfbce9ce95db47b3d

View file

@ -30,7 +30,7 @@ const char* expr_name(BroExprTag t)
"=", "~", "[]", "$", "?$", "[=]",
"table()", "set()", "vector()",
"$=", "in", "<<>>",
"()", "event", "schedule",
"()", "function()", "event", "schedule",
"coerce", "record_coerce", "table_coerce",
"sizeof", "flatten", "cast", "is", "[:]="
};
@ -4323,7 +4323,7 @@ void CallExpr::ExprDescribe(ODesc* d) const
}
LambdaExpr::LambdaExpr(std::unique_ptr<function_ingredients> ingredients,
std::shared_ptr<id_list> outer_ids)
std::shared_ptr<id_list> outer_ids) : Expr(EXPR_LAMBDA)
{
this->ingredients = std::move(ingredients);
this->outer_ids = std::move(outer_ids);
@ -4333,6 +4333,7 @@ LambdaExpr::LambdaExpr(std::unique_ptr<function_ingredients> ingredients,
Val* LambdaExpr::Eval(Frame* f) const
{
reporter->Warning("eval lambda");
BroFunc* lamb = new BroFunc(
ingredients->id,
ingredients->body,
@ -4347,10 +4348,8 @@ Val* LambdaExpr::Eval(Frame* f) const
void LambdaExpr::ExprDescribe(ODesc* d) const
{
d->Add("Lambda Expression");
d->Add("{");
d->Add(expr_name(Tag()));
ingredients->body->Describe(d);
d->Add("}");
}
TraversalCode LambdaExpr::Traverse(TraversalCallback* cb) const

View file

@ -43,6 +43,7 @@ typedef enum {
EXPR_IN,
EXPR_LIST,
EXPR_CALL,
EXPR_LAMBDA,
EXPR_EVENT,
EXPR_SCHEDULE,
EXPR_ARITH_COERCE,
@ -952,15 +953,11 @@ protected:
};
// Class to handle the creation of anonymous functions with closures.
// Facts:
// - LambdaExpr creates a new BroFunc on every call to Eval.
// - LambdaExpr must be given all the information to create a BroFunc on
// construction except for the closure.
// - The closure for created BroFuncs is the frame that the LambdaExpr is
// evaluated in.
/**
* Class that represents an anonymous function expression in Zeek.
* On evaluation, captures the frame that it is evaluated in. This becomes
* the closure for the instance of the function that it creates.
*/
class LambdaExpr : public Expr {
public:
LambdaExpr(std::unique_ptr<function_ingredients> ingredients,

View file

@ -217,7 +217,7 @@ ClosureFrame::~ClosureFrame()
Val* ClosureFrame::GetElement(ID* id) const
{
if ( ClosureContains(id) )
if ( CaptureContains(id) )
return ClosureFrame::GatherFromClosure(this, id);
return this->NthElement(id->Offset());
@ -225,7 +225,7 @@ Val* ClosureFrame::GetElement(ID* id) const
void ClosureFrame::SetElement(const ID* id, Val* v)
{
if ( ClosureContains(id) )
if ( CaptureContains(id) )
ClosureFrame::SetInClosure(this, id, v);
else
this->Frame::SetElement(id->Offset(), v);
@ -250,7 +250,7 @@ Frame* ClosureFrame::SelectiveClone(id_list* choose)
loop_over_list(*choose, i)
{
ID* we = (*choose)[i];
if ( ClosureContains(we) )
if ( CaptureContains(we) )
us.append(we);
else
them.append(we);
@ -282,7 +282,7 @@ Val* ClosureFrame::GatherFromClosure(const Frame* start, const ID* id)
if ( ! conductor )
return start->NthElement(id->Offset());
if (conductor->ClosureContains(id))
if (conductor->CaptureContains(id))
return ClosureFrame::GatherFromClosure(conductor->closure, id);
return conductor->NthElement(id->Offset());
@ -295,14 +295,14 @@ void ClosureFrame::SetInClosure(Frame* start, const ID* id, Val* val)
if ( ! conductor )
start->SetElement(id->Offset(), val);
else if (conductor->ClosureContains(id))
else if (conductor->CaptureContains(id))
ClosureFrame::SetInClosure(conductor->closure, id, val);
else
conductor->Frame::SetElement(id->Offset(), val);
}
bool ClosureFrame::ClosureContains(const ID* i) const
bool ClosureFrame::CaptureContains(const ID* i) const
{
const char* target = i->Name();
return std::any_of(closure_elements.begin(), closure_elements.end(),

View file

@ -18,7 +18,8 @@ class Val;
class Frame : public BroObj {
public:
Frame(int size, const BroFunc* func, const val_list *fn_args);
// The constructed frame becomes a view of the input frame. No copying is done.
// Constructs a copy or view of other. If a view is constructed the
// destructor will not change other's state on deletion.
Frame(const Frame* other, bool is_view = false);
~Frame() override;
@ -95,19 +96,11 @@ protected:
};
// Class that allows for lookups in both a closure frame and a regular frame
// according to a list of outer IDs passed into the constructor.
// Facts:
// - A ClosureFrame is created from two frames: a closure and a regular frame.
// - ALL operations except Get/SetElement operations operate on the regular frame.
// - A ClosureFrame requires a list of outside ID's captured by the closure.
// - Get/Set operations on those IDs will be performed on the closure frame.
// ClosureFrame allows functions that generate functions to be passed between
// different sized frames and still properly capture their closures. It also allows for
// cleaner handling of closures.
/**
* Class that allows for actions in both a regular frame and a closure frame
* according to a list of outer IDs captured in the closure passed into the
* constructor.
*/
class ClosureFrame : public Frame {
public:
ClosureFrame(Frame* closure, Frame* body,
@ -122,14 +115,12 @@ private:
Frame* closure;
Frame* body;
// Searches the start frame and all sub-frame's closures for a value corresponding
// to the id. Returns it when its found. Will fail with little grace if the value
// does not actually exist in any of the sub-frames.
// Both of these assume that it has already been verified that id is
// in the start frame.
static Val* GatherFromClosure(const Frame* start, const ID* id);
// Moves through the closure frames and associates val with id.
static void SetInClosure(Frame* start, const ID* id, Val* val);
bool ClosureContains(const ID* i) const;
bool CaptureContains(const ID* i) const;
std::vector<const char*> closure_elements;
};

View file

@ -530,7 +530,7 @@ std::unique_ptr<function_ingredients> gather_function_ingredients(Stmt* body)
ingredients->priority = get_func_priotity(attrs);
ingredients->body = body;
return std::move(ingredients);
return ingredients;
}
Val* internal_val(const char* name)
@ -555,7 +555,7 @@ std::shared_ptr<id_list> gather_outer_ids(Scope* scope, Stmt* body)
for ( size_t i = 0; i < cb.outer_id_references.size(); ++i )
idl->append(cb.outer_id_references[i]->Id());
return std::move(idl);
return idl;
}
Val* internal_const_val(const char* name)

View file

@ -26,8 +26,7 @@ extern void add_type(ID* id, BroType* t, attr_list* attr);
extern void begin_func(ID* id, const char* module_name, function_flavor flavor,
int is_redef, FuncType* t, attr_list* attrs = nullptr);
extern void end_func(Stmt* body);
extern std::unique_ptr<function_ingredients>
gather_function_ingredients(Stmt* body);
extern std::unique_ptr<function_ingredients> gather_function_ingredients(Stmt* body);
extern std::shared_ptr<id_list> gather_outer_ids(Scope* scope, Stmt* body);
extern Val* internal_val(const char* name);

View file

@ -31,7 +31,7 @@ expect: client
client
expect: client
client
expect: unknown-22. outside-5
expect: unknown-33. outside-5
unknown-33. outside-5
expect: unknown-11. outside-4
@ -42,5 +42,5 @@ expect: client
client
expect: client
client
expect: unknown-22. outside-5
expect: unknown-33. outside-5
unknown-33. outside-5

View file

@ -102,7 +102,7 @@ event zeek_init()
print "expect: client";
print dogs[3];
print "expect: unknown-22. outside-5";
print "expect: unknown-33. outside-5";
print dogs[33];
print "";
@ -126,7 +126,7 @@ event zeek_init()
print "expect: client";
print dogs_also[3];
print "expect: unknown-22. outside-5";
print "expect: unknown-33. outside-5";
print dogs_also[33];