/proc/self/cwd/parser/macro.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2021 Google LLC |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include "parser/macro.h" |
16 | | |
17 | | #include <cstdint> |
18 | | #include <utility> |
19 | | |
20 | | #include "absl/status/status.h" |
21 | | #include "absl/strings/str_cat.h" |
22 | | #include "absl/strings/str_format.h" |
23 | | #include "common/operators.h" |
24 | | #include "internal/lexis.h" |
25 | | #include "parser/source_factory.h" |
26 | | |
27 | | namespace cel { |
28 | | |
29 | | namespace { |
30 | | |
31 | | using google::api::expr::v1alpha1::Expr; |
32 | | using google::api::expr::common::CelOperator; |
33 | | |
34 | | absl::StatusOr<Macro> MakeMacro(absl::string_view name, size_t argument_count, |
35 | | MacroExpander expander, |
36 | 0 | bool is_receiver_style) { |
37 | 0 | if (!internal::LexisIsIdentifier(name)) { |
38 | 0 | return absl::InvalidArgumentError(absl::StrCat( |
39 | 0 | "Macro function name \"", name, "\" is not a valid identifier")); |
40 | 0 | } |
41 | 0 | if (!expander) { |
42 | 0 | return absl::InvalidArgumentError( |
43 | 0 | absl::StrCat("Macro expander for \"", name, "\" cannot be empty")); |
44 | 0 | } |
45 | 0 | return Macro(name, argument_count, std::move(expander), is_receiver_style); |
46 | 0 | } |
47 | | |
48 | | absl::StatusOr<Macro> MakeMacro(absl::string_view name, MacroExpander expander, |
49 | 0 | bool is_receiver_style) { |
50 | 0 | if (!internal::LexisIsIdentifier(name)) { |
51 | 0 | return absl::InvalidArgumentError(absl::StrCat( |
52 | 0 | "Macro function name \"", name, "\" is not a valid identifier")); |
53 | 0 | } |
54 | 0 | if (!expander) { |
55 | 0 | return absl::InvalidArgumentError( |
56 | 0 | absl::StrCat("Macro expander for \"", name, "\" cannot be empty")); |
57 | 0 | } |
58 | 0 | return Macro(name, std::move(expander), is_receiver_style); |
59 | 0 | } |
60 | | |
61 | | } // namespace |
62 | | |
63 | | absl::StatusOr<Macro> Macro::Global(absl::string_view name, |
64 | | size_t argument_count, |
65 | 0 | MacroExpander expander) { |
66 | 0 | return MakeMacro(name, argument_count, std::move(expander), false); |
67 | 0 | } |
68 | | |
69 | | absl::StatusOr<Macro> Macro::GlobalVarArg(absl::string_view name, |
70 | 0 | MacroExpander expander) { |
71 | 0 | return MakeMacro(name, std::move(expander), false); |
72 | 0 | } |
73 | | |
74 | | absl::StatusOr<Macro> Macro::Receiver(absl::string_view name, |
75 | | size_t argument_count, |
76 | 0 | MacroExpander expander) { |
77 | 0 | return MakeMacro(name, argument_count, std::move(expander), true); |
78 | 0 | } |
79 | | |
80 | | absl::StatusOr<Macro> Macro::ReceiverVarArg(absl::string_view name, |
81 | 0 | MacroExpander expander) { |
82 | 0 | return MakeMacro(name, std::move(expander), true); |
83 | 0 | } |
84 | | |
85 | 9.61k | std::vector<Macro> Macro::AllMacros() { |
86 | 9.61k | return { |
87 | | // The macro "has(m.f)" which tests the presence of a field, avoiding the |
88 | | // need to specify the field as a string. |
89 | 9.61k | Macro(CelOperator::HAS, 1, |
90 | 9.61k | [](const std::shared_ptr<SourceFactory>& sf, int64_t macro_id, |
91 | 9.61k | const Expr& target, const std::vector<Expr>& args) { |
92 | 551 | if (!args.empty() && args[0].has_select_expr()) { |
93 | 379 | const auto& sel_expr = args[0].select_expr(); |
94 | 379 | return sf->NewPresenceTestForMacro(macro_id, sel_expr.operand(), |
95 | 379 | sel_expr.field()); |
96 | 379 | } else { |
97 | | // error |
98 | 172 | return Expr(); |
99 | 172 | } |
100 | 551 | }), |
101 | | |
102 | | // The macro "range.all(var, predicate)", which is true if for all |
103 | | // elements |
104 | | // in range the predicate holds. |
105 | 9.61k | Macro( |
106 | 9.61k | CelOperator::ALL, 2, |
107 | 9.61k | [](const std::shared_ptr<SourceFactory>& sf, int64_t macro_id, |
108 | 9.61k | const Expr& target, const std::vector<Expr>& args) { |
109 | 1.21k | return sf->NewQuantifierExprForMacro(SourceFactory::QUANTIFIER_ALL, |
110 | 1.21k | macro_id, target, args); |
111 | 1.21k | }, |
112 | 9.61k | /* receiver style*/ true), |
113 | | |
114 | | // The macro "range.exists(var, predicate)", which is true if for at least |
115 | | // one element in range the predicate holds. |
116 | 9.61k | Macro( |
117 | 9.61k | CelOperator::EXISTS, 2, |
118 | 9.61k | [](const std::shared_ptr<SourceFactory>& sf, int64_t macro_id, |
119 | 9.61k | const Expr& target, const std::vector<Expr>& args) { |
120 | 420 | return sf->NewQuantifierExprForMacro( |
121 | 420 | SourceFactory::QUANTIFIER_EXISTS, macro_id, target, args); |
122 | 420 | }, |
123 | 9.61k | /* receiver style*/ true), |
124 | | |
125 | | // The macro "range.exists_one(var, predicate)", which is true if for |
126 | | // exactly one element in range the predicate holds. |
127 | 9.61k | Macro( |
128 | 9.61k | CelOperator::EXISTS_ONE, 2, |
129 | 9.61k | [](const std::shared_ptr<SourceFactory>& sf, int64_t macro_id, |
130 | 9.61k | const Expr& target, const std::vector<Expr>& args) { |
131 | 607 | return sf->NewQuantifierExprForMacro( |
132 | 607 | SourceFactory::QUANTIFIER_EXISTS_ONE, macro_id, target, args); |
133 | 607 | }, |
134 | 9.61k | /* receiver style*/ true), |
135 | | |
136 | | // The macro "range.map(var, function)", applies the function to the vars |
137 | | // in |
138 | | // the range. |
139 | 9.61k | Macro( |
140 | 9.61k | CelOperator::MAP, 2, |
141 | 9.61k | [](const std::shared_ptr<SourceFactory>& sf, int64_t macro_id, |
142 | 9.61k | const Expr& target, const std::vector<Expr>& args) { |
143 | 974 | return sf->NewMapForMacro(macro_id, target, args); |
144 | 974 | }, |
145 | 9.61k | /* receiver style*/ true), |
146 | | |
147 | | // The macro "range.map(var, predicate, function)", applies the function |
148 | | // to |
149 | | // the vars in the range for which the predicate holds true. The other |
150 | | // variables are filtered out. |
151 | 9.61k | Macro( |
152 | 9.61k | CelOperator::MAP, 3, |
153 | 9.61k | [](const std::shared_ptr<SourceFactory>& sf, int64_t macro_id, |
154 | 9.61k | const Expr& target, const std::vector<Expr>& args) { |
155 | 806 | return sf->NewMapForMacro(macro_id, target, args); |
156 | 806 | }, |
157 | 9.61k | /* receiver style*/ true), |
158 | | |
159 | | // The macro "range.filter(var, predicate)", filters out the variables for |
160 | | // which the |
161 | | // predicate is false. |
162 | 9.61k | Macro( |
163 | 9.61k | CelOperator::FILTER, 2, |
164 | 9.61k | [](const std::shared_ptr<SourceFactory>& sf, int64_t macro_id, |
165 | 9.61k | const Expr& target, const std::vector<Expr>& args) { |
166 | 851 | return sf->NewFilterExprForMacro(macro_id, target, args); |
167 | 851 | }, |
168 | 9.61k | /* receiver style*/ true), |
169 | 9.61k | }; |
170 | 9.61k | } |
171 | | |
172 | | } // namespace cel |