Change record field anonymous functions to use lambda expressions

There was an alternate syntax to assign anonymous functions to record
fields that was never migrated to use the new lambda expression
machinery (and so didn't allow referencing variables in outer scope):

    type myrec: record {
        foo: function(a: string);
    };

    local o = "o";
    local mr = myrec($foo(a: string) = { print a + o; });
This commit is contained in:
Jon Siwek 2020-03-26 15:48:18 -07:00
parent 66156b4eee
commit f032885085
5 changed files with 40 additions and 35 deletions

View file

@ -476,16 +476,6 @@ void end_func(IntrusivePtr<Stmt> body)
{
auto ingredients = std::make_unique<function_ingredients>(pop_scope(), std::move(body));
if ( streq(ingredients->id->Name(), "anonymous-function") )
{
OuterIDBindingFinder cb(ingredients->scope.get());
ingredients->body->Traverse(&cb);
for ( size_t i = 0; i < cb.outer_id_references.size(); ++i )
cb.outer_id_references[i]->Error(
"referencing outer function IDs not supported");
}
if ( ingredients->id->HasVal() )
ingredients->id->ID_Val()->AsFunc()->AddBody(
ingredients->body,

View file

@ -57,7 +57,7 @@
%type <ic> init_class
%type <expr> opt_init
%type <val> TOK_CONSTANT
%type <expr> expr opt_expr init anonymous_function index_slice opt_deprecated
%type <expr> expr opt_expr init anonymous_function lambda_body index_slice opt_deprecated
%type <event_expr> event
%type <stmt> stmt stmt_list func_body for_head
%type <type> type opt_type enum_body
@ -504,7 +504,7 @@ expr:
$$ = new FieldAssignExpr($2, {AdoptRef{}, $4});
}
| '$' TOK_ID func_params '='
| '$' TOK_ID func_params '='
{
func_hdr_location = @1;
func_id = current_scope()->GenerateTemporary("anonymous-function");
@ -512,11 +512,9 @@ expr:
begin_func(func_id, current_module.c_str(), FUNC_FLAVOR_FUNCTION,
0, {AdoptRef{}, $3});
}
func_body
lambda_body
{
$$ = new FieldAssignExpr($2,
make_intrusive<ConstExpr>(
IntrusivePtr<Val>{NewRef{}, func_id->ID_Val()}));
$$ = new FieldAssignExpr($2, IntrusivePtr{AdoptRef{}, $6});
Unref(func_id);
}
@ -1237,9 +1235,7 @@ func_body:
}
;
anonymous_function:
TOK_FUNCTION begin_func
lambda_body:
'{'
{
saved_in_init.push_back(in_init);
@ -1254,20 +1250,25 @@ anonymous_function:
'}'
{
set_location(@1, @7);
set_location(@1, @5);
// Code duplication here is sad but needed. end_func actually instantiates the function
// and associates it with an ID. We perform that association later and need to return
// a lambda expression.
// Gather the ingredients for a BroFunc from the current scope
auto ingredients = std::make_unique<function_ingredients>(IntrusivePtr{NewRef{}, current_scope()}, IntrusivePtr{AdoptRef{}, $5});
auto ingredients = std::make_unique<function_ingredients>(IntrusivePtr{NewRef{}, current_scope()}, IntrusivePtr{AdoptRef{}, $3});
id_list outer_ids = gather_outer_ids(pop_scope().get(), ingredients->body.get());
$$ = new LambdaExpr(std::move(ingredients), std::move(outer_ids));
}
;
anonymous_function:
TOK_FUNCTION begin_func lambda_body
{ $$ = $3; }
;
begin_func:
func_params
{

View file

@ -0,0 +1 @@
helloworld

View file

@ -39,7 +39,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -134,7 +134,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -241,7 +241,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -468,7 +468,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -593,7 +593,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -718,7 +718,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -843,7 +843,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -968,7 +968,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -1198,7 +1198,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -1251,7 +1251,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -1304,7 +1304,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -1357,7 +1357,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -1410,7 +1410,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;
@ -1463,7 +1463,7 @@ print A::outfile, Left;
print A::outfile, A::left;
print A::outfile, Right;
print A::outfile, A::right;
}, pred=anonymous-function
}, pred=lambda_<10906653936191056190>
{
print A::outfile, ============PREDICATE============;
print A::outfile, A::typ;

View file

@ -0,0 +1,13 @@
# @TEST-EXEC: zeek -b %INPUT >out
# @TEST-EXEC: btest-diff out
type myrec: record {
foo: function(a: string);
};
event zeek_init()
{
local w = "world";
local mr = myrec($foo(a: string) = { print a + w; });
mr$foo("hello");
}