From f032885085b0c7c894f72f9fc7f5722637599eba Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 26 Mar 2020 15:48:18 -0700 Subject: [PATCH] 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; }); --- src/Var.cc | 10 ------- src/parse.y | 23 +++++++-------- .../Baseline/language.lambda-record-field/out | 1 + .../scripts.base.frameworks.input.reread/out | 28 +++++++++---------- .../btest/language/lambda-record-field.zeek | 13 +++++++++ 5 files changed, 40 insertions(+), 35 deletions(-) create mode 100644 testing/btest/Baseline/language.lambda-record-field/out create mode 100644 testing/btest/language/lambda-record-field.zeek diff --git a/src/Var.cc b/src/Var.cc index c447517b53..d49323b7f3 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -476,16 +476,6 @@ void end_func(IntrusivePtr body) { auto ingredients = std::make_unique(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, diff --git a/src/parse.y b/src/parse.y index 7f379d44ec..dd22fbee04 100644 --- a/src/parse.y +++ b/src/parse.y @@ -57,7 +57,7 @@ %type init_class %type opt_init %type TOK_CONSTANT -%type expr opt_expr init anonymous_function index_slice opt_deprecated +%type expr opt_expr init anonymous_function lambda_body index_slice opt_deprecated %type event %type stmt stmt_list func_body for_head %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( - IntrusivePtr{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(IntrusivePtr{NewRef{}, current_scope()}, IntrusivePtr{AdoptRef{}, $5}); + auto ingredients = std::make_unique(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 { diff --git a/testing/btest/Baseline/language.lambda-record-field/out b/testing/btest/Baseline/language.lambda-record-field/out new file mode 100644 index 0000000000..31e0fce560 --- /dev/null +++ b/testing/btest/Baseline/language.lambda-record-field/out @@ -0,0 +1 @@ +helloworld diff --git a/testing/btest/Baseline/scripts.base.frameworks.input.reread/out b/testing/btest/Baseline/scripts.base.frameworks.input.reread/out index 19d323afcb..13adcdd31d 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.input.reread/out +++ b/testing/btest/Baseline/scripts.base.frameworks.input.reread/out @@ -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; diff --git a/testing/btest/language/lambda-record-field.zeek b/testing/btest/language/lambda-record-field.zeek new file mode 100644 index 0000000000..bcb7e1bc75 --- /dev/null +++ b/testing/btest/language/lambda-record-field.zeek @@ -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"); + }