|
23 | 23 | #include "absl/status/statusor.h" |
24 | 24 | #include "common/expr.h" |
25 | 25 | #include "common/type.h" |
| 26 | +#include "common/value.h" |
26 | 27 | #include "eval/compiler/resolver.h" |
27 | 28 | #include "eval/eval/evaluator_core.h" |
28 | 29 | #include "eval/eval/expression_step_logic.h" |
29 | 30 | #include "eval/eval/function_step.h" |
| 31 | +#include "eval/eval/ident_step.h" |
30 | 32 | #include "internal/testing.h" |
31 | 33 | #include "runtime/function_registry.h" |
32 | 34 | #include "runtime/internal/issue_collector.h" |
@@ -539,5 +541,100 @@ TEST_F(ProgramBuilderTest, ExtractToRequiresFlatten) { |
539 | 541 | UniquePtrHolds(step_ptrs.a))); |
540 | 542 | } |
541 | 543 |
|
| 544 | +TEST_F(ProgramBuilderTest, IsInlinableAndMaybeInlineConstant) { |
| 545 | + Expr a; |
| 546 | + Expr b; |
| 547 | + ProgramBuilder program_builder; |
| 548 | + |
| 549 | + program_builder.EnterSubexpression(&a); |
| 550 | + program_builder.EnterSubexpression(&b); |
| 551 | + program_builder.AddStep(ExpressionStep::MakeConstant(cel::IntValue(42), 10)); |
| 552 | + program_builder.ExitSubexpression(&b); |
| 553 | + program_builder.ExitSubexpression(&a); |
| 554 | + |
| 555 | + Subexpression* subexpr_a = program_builder.GetSubexpression(&a); |
| 556 | + Subexpression* subexpr_b = program_builder.GetSubexpression(&b); |
| 557 | + ASSERT_TRUE(subexpr_a != nullptr); |
| 558 | + ASSERT_TRUE(subexpr_b != nullptr); |
| 559 | + |
| 560 | + // Unflattened direct constant step and nested single-child subexpression. |
| 561 | + EXPECT_TRUE(subexpr_b->IsInlinable()); |
| 562 | + EXPECT_TRUE(subexpr_a->IsInlinable()); |
| 563 | + |
| 564 | + std::optional<ExpressionStep> inlined_b = subexpr_b->MaybeInline(99); |
| 565 | + ASSERT_TRUE(inlined_b.has_value()); |
| 566 | + EXPECT_EQ(inlined_b->id(), 99); |
| 567 | + cel::Value val; |
| 568 | + ASSERT_TRUE(GetIfConstant(*inlined_b, val)); |
| 569 | + EXPECT_EQ(val.GetInt().NativeValue(), 42); |
| 570 | + |
| 571 | + // Flattened constant step remains inlinable. |
| 572 | + subexpr_a->Flatten(); |
| 573 | + EXPECT_TRUE(subexpr_a->IsInlinable()); |
| 574 | + std::optional<ExpressionStep> inlined_a = subexpr_a->MaybeInline(100); |
| 575 | + ASSERT_TRUE(inlined_a.has_value()); |
| 576 | + EXPECT_EQ(inlined_a->id(), 100); |
| 577 | + ASSERT_TRUE(GetIfConstant(*inlined_a, val)); |
| 578 | + EXPECT_EQ(val.GetInt().NativeValue(), 42); |
| 579 | +} |
| 580 | + |
| 581 | +TEST_F(ProgramBuilderTest, IsInlinableAndMaybeInlineIdentifier) { |
| 582 | + Expr a; |
| 583 | + ProgramBuilder program_builder; |
| 584 | + |
| 585 | + program_builder.EnterSubexpression(&a); |
| 586 | + program_builder.AddStep(ExpressionStep::MakeIdentifierStep(3, 7, 10)); |
| 587 | + program_builder.ExitSubexpression(&a); |
| 588 | + |
| 589 | + Subexpression* subexpr_a = program_builder.GetSubexpression(&a); |
| 590 | + ASSERT_TRUE(subexpr_a != nullptr); |
| 591 | + |
| 592 | + EXPECT_TRUE(subexpr_a->IsInlinable()); |
| 593 | + std::optional<ExpressionStep> inlined = subexpr_a->MaybeInline(55); |
| 594 | + ASSERT_TRUE(inlined.has_value()); |
| 595 | + EXPECT_EQ(inlined->id(), 55); |
| 596 | + const IdentStepInfo* ident_info = GetIfIdentStep(*inlined); |
| 597 | + ASSERT_TRUE(ident_info != nullptr); |
| 598 | + EXPECT_EQ(ident_info->ident_index, 3); |
| 599 | + EXPECT_EQ(ident_info->slot_index, 7); |
| 600 | + |
| 601 | + subexpr_a->Flatten(); |
| 602 | + EXPECT_TRUE(subexpr_a->IsInlinable()); |
| 603 | + std::optional<ExpressionStep> inlined_flat = subexpr_a->MaybeInline(56); |
| 604 | + ASSERT_TRUE(inlined_flat.has_value()); |
| 605 | + EXPECT_EQ(inlined_flat->id(), 56); |
| 606 | + ident_info = GetIfIdentStep(*inlined_flat); |
| 607 | + ASSERT_TRUE(ident_info != nullptr); |
| 608 | + EXPECT_EQ(ident_info->ident_index, 3); |
| 609 | + EXPECT_EQ(ident_info->slot_index, 7); |
| 610 | +} |
| 611 | + |
| 612 | +TEST_F(ProgramBuilderTest, NotInlinableWhenNonTrivial) { |
| 613 | + Expr a; |
| 614 | + Expr b; |
| 615 | + Expr c; |
| 616 | + ProgramBuilder program_builder; |
| 617 | + |
| 618 | + ASSERT_OK_AND_ASSIGN(SimpleTreeSteps step_ptrs, |
| 619 | + InitSimpleTree(a, b, c, program_builder)); |
| 620 | + (void)step_ptrs; |
| 621 | + |
| 622 | + Subexpression* subexpr_a = program_builder.GetSubexpression(&a); |
| 623 | + Subexpression* subexpr_b = program_builder.GetSubexpression(&b); |
| 624 | + ASSERT_TRUE(subexpr_a != nullptr); |
| 625 | + ASSERT_TRUE(subexpr_b != nullptr); |
| 626 | + |
| 627 | + // Single generic step is not inlinable. |
| 628 | + EXPECT_FALSE(subexpr_b->IsInlinable()); |
| 629 | + EXPECT_EQ(subexpr_b->MaybeInline(1), std::nullopt); |
| 630 | + |
| 631 | + // Multi-step subexpression is not inlinable (unflattened and flattened). |
| 632 | + EXPECT_FALSE(subexpr_a->IsInlinable()); |
| 633 | + EXPECT_EQ(subexpr_a->MaybeInline(1), std::nullopt); |
| 634 | + subexpr_a->Flatten(); |
| 635 | + EXPECT_FALSE(subexpr_a->IsInlinable()); |
| 636 | + EXPECT_EQ(subexpr_a->MaybeInline(1), std::nullopt); |
| 637 | +} |
| 638 | + |
542 | 639 | } // namespace |
543 | 640 | } // namespace google::api::expr::runtime |
0 commit comments