forked from cel-expr/cel-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjump_step.cc
More file actions
135 lines (107 loc) · 3.86 KB
/
Copy pathjump_step.cc
File metadata and controls
135 lines (107 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "eval/eval/jump_step.h"
#include "absl/status/statusor.h"
#include "eval/eval/expression_step_base.h"
namespace google {
namespace api {
namespace expr {
namespace runtime {
namespace {
class JumpStep : public JumpStepBase {
public:
// Constructs FunctionStep that uses overloads specified.
JumpStep(absl::optional<int> jump_offset, int64_t expr_id)
: JumpStepBase(jump_offset, expr_id) {}
absl::Status Evaluate(ExecutionFrame* frame) const override {
return Jump(frame);
}
};
class CondJumpStep : public JumpStepBase {
public:
// Constructs FunctionStep that uses overloads specified.
CondJumpStep(bool jump_condition, bool leave_on_stack,
absl::optional<int> jump_offset, int64_t expr_id)
: JumpStepBase(jump_offset, expr_id),
jump_condition_(jump_condition),
leave_on_stack_(leave_on_stack) {}
absl::Status Evaluate(ExecutionFrame* frame) const override {
// Peek the top value
if (!frame->value_stack().HasEnough(1)) {
return absl::Status(absl::StatusCode::kInternal, "Value stack underflow");
}
CelValue value = frame->value_stack().Peek();
if (!leave_on_stack_) {
frame->value_stack().Pop(1);
}
if (value.IsBool() && jump_condition_ == value.BoolOrDie()) {
return Jump(frame);
}
return absl::OkStatus();
}
private:
const bool jump_condition_;
const bool leave_on_stack_;
};
class BoolCheckJumpStep : public JumpStepBase {
public:
// Checks if the top value is a boolean:
// - no-op if it is a boolean
// - jump to the label if it is an error value
// - jump to the label if it is unknown value
// - jump to the label if it is neither an error nor a boolean, pops it and
// pushes "no matching overload" error
BoolCheckJumpStep(absl::optional<int> jump_offset, int64_t expr_id)
: JumpStepBase(jump_offset, expr_id) {}
absl::Status Evaluate(ExecutionFrame* frame) const override {
// Peek the top value
if (!frame->value_stack().HasEnough(1)) {
return absl::Status(absl::StatusCode::kInternal, "Value stack underflow");
}
CelValue value = frame->value_stack().Peek();
if (value.IsError()) {
return Jump(frame);
}
if (value.IsUnknownSet()) {
return Jump(frame);
}
if (!value.IsBool()) {
CelValue error_value =
CreateNoMatchingOverloadError(frame->arena(), "<jump_condition>");
frame->value_stack().PopAndPush(error_value);
return Jump(frame);
}
return absl::OkStatus();
}
};
} // namespace
// Factory method for Conditional Jump step.
// Conditional Jump requires a boolean value to sit on the stack.
// It is compared to jump_condition, and if matched, jump is performed.
absl::StatusOr<std::unique_ptr<JumpStepBase>> CreateCondJumpStep(
bool jump_condition, bool leave_on_stack, absl::optional<int> jump_offset,
int64_t expr_id) {
std::unique_ptr<JumpStepBase> step = absl::make_unique<CondJumpStep>(
jump_condition, leave_on_stack, jump_offset, expr_id);
return std::move(step);
}
// Factory method for Jump step.
absl::StatusOr<std::unique_ptr<JumpStepBase>> CreateJumpStep(
absl::optional<int> jump_offset, int64_t expr_id) {
std::unique_ptr<JumpStepBase> step =
absl::make_unique<JumpStep>(jump_offset, expr_id);
return std::move(step);
}
// Factory method for Conditional Jump step.
// Conditional Jump requires a value to sit on the stack.
// If this value is an error or unknown, a jump is performed.
absl::StatusOr<std::unique_ptr<JumpStepBase>> CreateBoolCheckJumpStep(
absl::optional<int> jump_offset, int64_t expr_id) {
std::unique_ptr<JumpStepBase> step =
absl::make_unique<BoolCheckJumpStep>(jump_offset, expr_id);
return std::move(step);
}
// TODO(issues/41) Make sure Unknowns are properly supported by ternary
// operation.
} // namespace runtime
} // namespace expr
} // namespace api
} // namespace google