@@ -39,6 +39,8 @@ namespace cel {
3939
4040namespace {
4141
42+ constexpr absl::string_view kOptionalMapVar = " @target" ;
43+
4244using google::api::expr::common::CelOperator;
4345
4446bool IsSimpleIdentifier (const Expr& expr) {
@@ -315,20 +317,50 @@ absl::optional<Expr> ExpandOptMapMacro(MacroExprFactory& factory, Expr& target,
315317 }
316318 auto var_name = args[0 ].ident_expr ().name ();
317319
318- auto target_copy = factory.Copy (target);
319- std::vector<Expr> call_args;
320- call_args.reserve (3 );
321- call_args.push_back (factory.NewMemberCall (" hasValue" , std::move (target)));
320+ if (target.has_ident_expr ()) {
321+ auto target_copy = factory.Copy (target);
322+ std::vector<Expr> call_args;
323+ call_args.reserve (3 );
324+ call_args.push_back (factory.NewMemberCall (" hasValue" , std::move (target)));
325+ auto iter_range = factory.NewList ();
326+ auto accu_init = factory.NewMemberCall (" value" , std::move (target_copy));
327+ auto condition = factory.NewBoolConst (false );
328+ auto fold = factory.NewComprehension (
329+ " #unused" , std::move (iter_range), std::move (var_name),
330+ std::move (accu_init), std::move (condition), std::move (args[0 ]),
331+ std::move (args[1 ]));
332+ call_args.push_back (factory.NewCall (" optional.of" , std::move (fold)));
333+ call_args.push_back (factory.NewCall (" optional.none" ));
334+ return factory.NewCall (CelOperator::CONDITIONAL , std::move (call_args));
335+ }
336+
337+ // If the target is complex, use an internal bind expression to avoid
338+ // repeating it and blowing up the AST in the expansion
339+ auto tmp = factory.NewIdent (kOptionalMapVar );
340+ auto tmp_copy = factory.Copy (tmp);
341+
322342 auto iter_range = factory.NewList ();
323- auto accu_init = factory.NewMemberCall (" value" , std::move (target_copy ));
343+ auto accu_init = factory.NewMemberCall (" value" , std::move (tmp_copy ));
324344 auto condition = factory.NewBoolConst (false );
345+ auto loop_step = std::move (args[0 ]);
325346 auto fold = factory.NewComprehension (
326347 " #unused" , std::move (iter_range), std::move (var_name),
327- std::move (accu_init), std::move (condition), std::move (args[ 0 ] ),
348+ std::move (accu_init), std::move (condition), std::move (loop_step ),
328349 std::move (args[1 ]));
350+ std::vector<Expr> call_args;
351+ call_args.reserve (3 );
352+ call_args.push_back (factory.NewMemberCall (" hasValue" , std::move (tmp)));
329353 call_args.push_back (factory.NewCall (" optional.of" , std::move (fold)));
330354 call_args.push_back (factory.NewCall (" optional.none" ));
331- return factory.NewCall (CelOperator::CONDITIONAL , std::move (call_args));
355+ auto result = factory.NewCall (CelOperator::CONDITIONAL , std::move (call_args));
356+
357+ iter_range = factory.NewList ();
358+ accu_init = std::move (target);
359+ condition = factory.NewBoolConst (false );
360+ loop_step = factory.NewIdent (kOptionalMapVar );
361+ return factory.NewComprehension (
362+ " #unused" , std::move (iter_range), kOptionalMapVar , std::move (accu_init),
363+ std::move (condition), loop_step, std::move (result));
332364}
333365
334366Macro MakeOptMapMacro () {
@@ -354,19 +386,47 @@ absl::optional<Expr> ExpandOptFlatMapMacro(MacroExprFactory& factory,
354386 }
355387 auto var_name = args[0 ].ident_expr ().name ();
356388
357- auto target_copy = factory.Copy (target);
358- std::vector<Expr> call_args;
359- call_args.reserve (3 );
360- call_args.push_back (factory.NewMemberCall (" hasValue" , std::move (target)));
389+ if (target.has_ident_expr ()) {
390+ auto target_copy = factory.Copy (target);
391+ std::vector<Expr> call_args;
392+ call_args.reserve (3 );
393+ call_args.push_back (factory.NewMemberCall (" hasValue" , std::move (target)));
394+ auto iter_range = factory.NewList ();
395+ auto accu_init = factory.NewMemberCall (" value" , std::move (target_copy));
396+ auto condition = factory.NewBoolConst (false );
397+ call_args.push_back (factory.NewComprehension (
398+ " #unused" , std::move (iter_range), std::move (var_name),
399+ std::move (accu_init), std::move (condition), std::move (args[0 ]),
400+ std::move (args[1 ])));
401+ call_args.push_back (factory.NewCall (" optional.none" ));
402+ return factory.NewCall (CelOperator::CONDITIONAL , std::move (call_args));
403+ }
404+
405+ auto tmp = factory.NewIdent (kOptionalMapVar );
406+ auto tmp_copy = factory.Copy (tmp);
407+
361408 auto iter_range = factory.NewList ();
362- auto accu_init = factory.NewMemberCall (" value" , std::move (target_copy ));
409+ auto accu_init = factory.NewMemberCall (" value" , std::move (tmp_copy ));
363410 auto condition = factory.NewBoolConst (false );
364- call_args.push_back (factory.NewComprehension (
411+ auto loop_step = std::move (args[0 ]);
412+ auto inner = factory.NewComprehension (
365413 " #unused" , std::move (iter_range), std::move (var_name),
366- std::move (accu_init), std::move (condition), std::move (args[0 ]),
367- std::move (args[1 ])));
414+ std::move (accu_init), std::move (condition), std::move (loop_step),
415+ std::move (args[1 ]));
416+ std::vector<Expr> call_args;
417+ call_args.reserve (3 );
418+ call_args.push_back (factory.NewMemberCall (" hasValue" , std::move (tmp)));
419+ call_args.push_back (std::move (inner));
368420 call_args.push_back (factory.NewCall (" optional.none" ));
369- return factory.NewCall (CelOperator::CONDITIONAL , std::move (call_args));
421+ auto result = factory.NewCall (CelOperator::CONDITIONAL , std::move (call_args));
422+
423+ iter_range = factory.NewList ();
424+ accu_init = std::move (target);
425+ condition = factory.NewBoolConst (false );
426+ loop_step = factory.NewIdent (kOptionalMapVar );
427+ return factory.NewComprehension (
428+ " #unused" , std::move (iter_range), kOptionalMapVar , std::move (accu_init),
429+ std::move (condition), loop_step, std::move (result));
370430}
371431
372432Macro MakeOptFlatMapMacro () {
0 commit comments