| 695 | } |
| 696 | |
| 697 | absl::Status StackMachineImpl::Evaluate(ExecutionFrame* frame) const { |
| 698 | // Default empty. |
| 699 | AttributeTrail attribute_trail; |
| 700 | // TODO(uncreated-issue/51): add support for variable qualifiers and string literal |
| 701 | // variable names. |
| 702 | constexpr size_t kStackInputs = 1; |
| 703 | |
| 704 | // For now, we expect the operand to be top of stack. |
| 705 | const Value& operand = frame->value_stack().Peek(); |
| 706 | |
| 707 | if (operand->Is<ErrorValue>() || operand->Is<UnknownValue>()) { |
| 708 | // Just forward the error which is already top of stack. |
| 709 | return absl::OkStatus(); |
| 710 | } |
| 711 | |
| 712 | if (frame->enable_attribute_tracking()) { |
| 713 | // Compute the attribute trail then check for any marked values. |
| 714 | // When possible, this is computed at plan time based on the optimized |
| 715 | // select arguments. |
| 716 | // TODO(uncreated-issue/51): add support variable qualifiers |
| 717 | attribute_trail = GetAttributeTrail(frame); |
| 718 | CEL_ASSIGN_OR_RETURN(absl::optional<Value> value, |
| 719 | CheckForMarkedAttributes(*frame, attribute_trail)); |
| 720 | if (value.has_value()) { |
| 721 | frame->value_stack().Pop(kStackInputs); |
| 722 | frame->value_stack().Push(std::move(value).value(), |
| 723 | std::move(attribute_trail)); |
| 724 | return absl::OkStatus(); |
| 725 | } |
| 726 | } |
| 727 | |
| 728 | if (!operand->Is<StructValue>()) { |
| 729 | return absl::InvalidArgumentError( |
| 730 | "Expected struct type for select optimization."); |
| 731 | } |
| 732 | |
| 733 | CEL_ASSIGN_OR_RETURN(Value result, |
| 734 | impl_.ApplySelect(*frame, operand.GetStruct())); |
| 735 | |
| 736 | frame->value_stack().Pop(kStackInputs); |
| 737 | frame->value_stack().Push(std::move(result), std::move(attribute_trail)); |
| 738 | return absl::OkStatus(); |
| 739 | } |
| 740 | |
| 741 | class RecursiveImpl : public DirectExpressionStep { |
| 742 | public: |