Coverage Report

Created: 2026-09-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/parser/macro.cc
Line
Count
Source
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 <cstddef>
18
#include <functional>
19
#include <memory>
20
#include <string>
21
#include <utility>
22
#include <vector>
23
24
#include "absl/base/no_destructor.h"
25
#include "absl/log/absl_check.h"
26
#include "absl/status/status.h"
27
#include "absl/status/statusor.h"
28
#include "absl/strings/match.h"
29
#include "absl/strings/str_cat.h"
30
#include "absl/strings/string_view.h"
31
#include "absl/types/optional.h"
32
#include "absl/types/span.h"
33
#include "common/expr.h"
34
#include "common/operators.h"
35
#include "internal/lexis.h"
36
#include "parser/macro_expr_factory.h"
37
38
namespace cel {
39
40
namespace {
41
42
constexpr absl::string_view kOptionalMapVar = "@target";
43
44
using google::api::expr::common::CelOperator;
45
46
43.3k
bool IsSimpleIdentifier(const Expr& expr) {
47
43.3k
  return expr.has_ident_expr() && !expr.ident_expr().name().empty() &&
48
41.5k
         !absl::StartsWith(expr.ident_expr().name(), ".");
49
43.3k
}
50
51
2
inline MacroExpander ToMacroExpander(GlobalMacroExpander expander) {
52
2
  ABSL_DCHECK(expander);
53
2
  return [expander = std::move(expander)](
54
2
             MacroExprFactory& factory,
55
2
             absl::optional<std::reference_wrapper<Expr>> target,
56
26.4k
             absl::Span<Expr> arguments) -> absl::optional<Expr> {
57
26.4k
    ABSL_DCHECK(!target.has_value());
58
26.4k
    return (expander)(factory, arguments);
59
26.4k
  };
60
2
}
61
62
12
inline MacroExpander ToMacroExpander(ReceiverMacroExpander expander) {
63
12
  ABSL_DCHECK(expander);
64
12
  return [expander = std::move(expander)](
65
12
             MacroExprFactory& factory,
66
12
             absl::optional<std::reference_wrapper<Expr>> target,
67
43.3k
             absl::Span<Expr> arguments) -> absl::optional<Expr> {
68
43.3k
    ABSL_DCHECK(target.has_value());
69
43.3k
    return (expander)(factory, *target, arguments);
70
43.3k
  };
71
12
}
72
73
absl::optional<Expr> ExpandHasMacro(MacroExprFactory& factory,
74
26.4k
                                    absl::Span<Expr> args) {
75
26.4k
  if (args.size() != 1) {
76
0
    return factory.ReportError("has() requires 1 arguments");
77
0
  }
78
26.4k
  if (!args[0].has_select_expr() || args[0].select_expr().test_only()) {
79
19.7k
    return factory.ReportErrorAt(args[0],
80
19.7k
                                 "has() argument must be a field selection");
81
19.7k
  }
82
6.61k
  return factory.NewPresenceTest(
83
6.61k
      args[0].mutable_select_expr().release_operand(),
84
6.61k
      args[0].mutable_select_expr().release_field());
85
26.4k
}
86
87
2
Macro MakeHasMacro() {
88
2
  auto macro_or_status = Macro::Global(CelOperator::HAS, 1, ExpandHasMacro);
89
2
  ABSL_CHECK_OK(macro_or_status);  // Crash OK
90
2
  return std::move(*macro_or_status);
91
2
}
92
93
absl::optional<Expr> ExpandAllMacro(MacroExprFactory& factory, Expr& target,
94
2.03k
                                    absl::Span<Expr> args) {
95
2.03k
  if (args.size() != 2) {
96
0
    return factory.ReportError("all() requires 2 arguments");
97
0
  }
98
2.03k
  if (!IsSimpleIdentifier(args[0])) {
99
878
    return factory.ReportErrorAt(
100
878
        args[0], "all() variable name must be a simple identifier");
101
878
  }
102
1.16k
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
103
157
    return factory.ReportErrorAt(
104
157
        args[1], absl::StrCat("all() variable name cannot be ",
105
157
                              kDeprecatedAccumulatorVariableName));
106
157
  }
107
1.00k
  auto init = factory.NewBoolConst(true);
108
1.00k
  auto condition =
109
1.00k
      factory.NewCall(CelOperator::NOT_STRICTLY_FALSE, factory.NewAccuIdent());
110
1.00k
  auto step = factory.NewCall(CelOperator::LOGICAL_AND, factory.NewAccuIdent(),
111
1.00k
                              std::move(args[1]));
112
1.00k
  auto result = factory.NewAccuIdent();
113
1.00k
  return factory.NewComprehension(args[0].ident_expr().name(),
114
1.00k
                                  std::move(target), factory.AccuVarName(),
115
1.00k
                                  std::move(init), std::move(condition),
116
1.00k
                                  std::move(step), std::move(result));
117
1.16k
}
118
119
2
Macro MakeAllMacro() {
120
2
  auto status_or_macro = Macro::Receiver(CelOperator::ALL, 2, ExpandAllMacro);
121
2
  ABSL_CHECK_OK(status_or_macro);  // Crash OK
122
2
  return std::move(*status_or_macro);
123
2
}
124
125
absl::optional<Expr> ExpandExistsMacro(MacroExprFactory& factory, Expr& target,
126
1.44k
                                       absl::Span<Expr> args) {
127
1.44k
  if (args.size() != 2) {
128
0
    return factory.ReportError("exists() requires 2 arguments");
129
0
  }
130
1.44k
  if (!IsSimpleIdentifier(args[0])) {
131
350
    return factory.ReportErrorAt(
132
350
        args[0], "exists() variable name must be a simple identifier");
133
350
  }
134
1.09k
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
135
111
    return factory.ReportErrorAt(
136
111
        args[1], absl::StrCat("exists() variable name cannot be ",
137
111
                              kDeprecatedAccumulatorVariableName));
138
111
  }
139
979
  auto init = factory.NewBoolConst(false);
140
979
  auto condition = factory.NewCall(
141
979
      CelOperator::NOT_STRICTLY_FALSE,
142
979
      factory.NewCall(CelOperator::LOGICAL_NOT, factory.NewAccuIdent()));
143
979
  auto step = factory.NewCall(CelOperator::LOGICAL_OR, factory.NewAccuIdent(),
144
979
                              std::move(args[1]));
145
979
  auto result = factory.NewAccuIdent();
146
979
  return factory.NewComprehension(args[0].ident_expr().name(),
147
979
                                  std::move(target), factory.AccuVarName(),
148
979
                                  std::move(init), std::move(condition),
149
979
                                  std::move(step), std::move(result));
150
1.09k
}
151
152
2
Macro MakeExistsMacro() {
153
2
  auto status_or_macro =
154
2
      Macro::Receiver(CelOperator::EXISTS, 2, ExpandExistsMacro);
155
2
  ABSL_CHECK_OK(status_or_macro);  // Crash OK
156
2
  return std::move(*status_or_macro);
157
2
}
158
159
absl::optional<Expr> ExpandExistsOneMacro(MacroExprFactory& factory,
160
6.30k
                                          Expr& target, absl::Span<Expr> args) {
161
6.30k
  if (args.size() != 2) {
162
0
    return factory.ReportError("exists_one() requires 2 arguments");
163
0
  }
164
6.30k
  if (!IsSimpleIdentifier(args[0])) {
165
337
    return factory.ReportErrorAt(
166
337
        args[0], "exists_one() variable name must be a simple identifier");
167
337
  }
168
5.96k
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
169
201
    return factory.ReportErrorAt(
170
201
        args[1], absl::StrCat("exists_one() variable name cannot be ",
171
201
                              kDeprecatedAccumulatorVariableName));
172
201
  }
173
5.76k
  auto init = factory.NewIntConst(0);
174
5.76k
  auto condition = factory.NewBoolConst(true);
175
5.76k
  auto accu_ident = factory.NewAccuIdent();
176
5.76k
  auto const_1 = factory.NewIntConst(1);
177
5.76k
  auto inc_step = factory.NewCall(CelOperator::ADD, std::move(accu_ident),
178
5.76k
                                  std::move(const_1));
179
180
5.76k
  auto step = factory.NewCall(CelOperator::CONDITIONAL, std::move(args[1]),
181
5.76k
                              std::move(inc_step), factory.NewAccuIdent());
182
5.76k
  accu_ident = factory.NewAccuIdent();
183
5.76k
  auto result = factory.NewCall(CelOperator::EQUALS, std::move(accu_ident),
184
5.76k
                                factory.NewIntConst(1));
185
5.76k
  return factory.NewComprehension(args[0].ident_expr().name(),
186
5.76k
                                  std::move(target), factory.AccuVarName(),
187
5.76k
                                  std::move(init), std::move(condition),
188
5.76k
                                  std::move(step), std::move(result));
189
5.96k
}
190
191
2
Macro MakeExistsOneMacro() {
192
2
  auto status_or_macro =
193
2
      Macro::Receiver(CelOperator::EXISTS_ONE, 2, ExpandExistsOneMacro);
194
2
  ABSL_CHECK_OK(status_or_macro);  // Crash OK
195
2
  return std::move(*status_or_macro);
196
2
}
197
198
absl::optional<Expr> ExpandMap2Macro(MacroExprFactory& factory, Expr& target,
199
18.9k
                                     absl::Span<Expr> args) {
200
18.9k
  if (args.size() != 2) {
201
0
    return factory.ReportError("map() requires 2 arguments");
202
0
  }
203
18.9k
  if (!IsSimpleIdentifier(args[0])) {
204
291
    return factory.ReportErrorAt(
205
291
        args[0], "map() variable name must be a simple identifier");
206
291
  }
207
18.7k
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
208
121
    return factory.ReportErrorAt(
209
121
        args[1], absl::StrCat("map() variable name cannot be ",
210
121
                              kDeprecatedAccumulatorVariableName));
211
121
  }
212
18.5k
  auto init = factory.NewList();
213
18.5k
  auto condition = factory.NewBoolConst(true);
214
18.5k
  auto accu_ref = factory.NewAccuIdent();
215
18.5k
  auto accu_update =
216
18.5k
      factory.NewList(factory.NewListElement(std::move(args[1])));
217
18.5k
  auto step = factory.NewCall(CelOperator::ADD, std::move(accu_ref),
218
18.5k
                              std::move(accu_update));
219
18.5k
  return factory.NewComprehension(args[0].ident_expr().name(),
220
18.5k
                                  std::move(target), factory.AccuVarName(),
221
18.5k
                                  std::move(init), std::move(condition),
222
18.5k
                                  std::move(step), factory.NewAccuIdent());
223
18.7k
}
224
225
2
Macro MakeMap2Macro() {
226
2
  auto status_or_macro = Macro::Receiver(CelOperator::MAP, 2, ExpandMap2Macro);
227
2
  ABSL_CHECK_OK(status_or_macro);  // Crash OK
228
2
  return std::move(*status_or_macro);
229
2
}
230
231
absl::optional<Expr> ExpandMap3Macro(MacroExprFactory& factory, Expr& target,
232
13.8k
                                     absl::Span<Expr> args) {
233
13.8k
  if (args.size() != 3) {
234
0
    return factory.ReportError("map() requires 3 arguments");
235
0
  }
236
13.8k
  if (!IsSimpleIdentifier(args[0])) {
237
199
    return factory.ReportErrorAt(
238
199
        args[0], "map() variable name must be a simple identifier");
239
199
  }
240
13.6k
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
241
158
    return factory.ReportErrorAt(
242
158
        args[1], absl::StrCat("map() variable name cannot be ",
243
158
                              kDeprecatedAccumulatorVariableName));
244
158
  }
245
13.4k
  auto init = factory.NewList();
246
13.4k
  auto condition = factory.NewBoolConst(true);
247
13.4k
  auto accu_ref = factory.NewAccuIdent();
248
13.4k
  auto accu_update =
249
13.4k
      factory.NewList(factory.NewListElement(std::move(args[2])));
250
13.4k
  auto step = factory.NewCall(CelOperator::ADD, std::move(accu_ref),
251
13.4k
                              std::move(accu_update));
252
13.4k
  step = factory.NewCall(CelOperator::CONDITIONAL, std::move(args[1]),
253
13.4k
                         std::move(step), factory.NewAccuIdent());
254
13.4k
  return factory.NewComprehension(args[0].ident_expr().name(),
255
13.4k
                                  std::move(target), factory.AccuVarName(),
256
13.4k
                                  std::move(init), std::move(condition),
257
13.4k
                                  std::move(step), factory.NewAccuIdent());
258
13.6k
}
259
260
2
Macro MakeMap3Macro() {
261
2
  auto status_or_macro = Macro::Receiver(CelOperator::MAP, 3, ExpandMap3Macro);
262
2
  ABSL_CHECK_OK(status_or_macro);  // Crash OK
263
2
  return std::move(*status_or_macro);
264
2
}
265
266
absl::optional<Expr> ExpandFilterMacro(MacroExprFactory& factory, Expr& target,
267
796
                                       absl::Span<Expr> args) {
268
796
  if (args.size() != 2) {
269
0
    return factory.ReportError("filter() requires 2 arguments");
270
0
  }
271
796
  if (!IsSimpleIdentifier(args[0])) {
272
81
    return factory.ReportErrorAt(
273
81
        args[0], "filter() variable name must be a simple identifier");
274
81
  }
275
715
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
276
96
    return factory.ReportErrorAt(
277
96
        args[1], absl::StrCat("filter() variable name cannot be ",
278
96
                              kDeprecatedAccumulatorVariableName));
279
96
  }
280
619
  auto name = args[0].ident_expr().name();
281
282
619
  auto init = factory.NewList();
283
619
  auto condition = factory.NewBoolConst(true);
284
619
  auto accu_ref = factory.NewAccuIdent();
285
619
  auto accu_update =
286
619
      factory.NewList(factory.NewListElement(std::move(args[0])));
287
619
  auto step = factory.NewCall(CelOperator::ADD, std::move(accu_ref),
288
619
                              std::move(accu_update));
289
619
  step = factory.NewCall(CelOperator::CONDITIONAL, std::move(args[1]),
290
619
                         std::move(step), factory.NewAccuIdent());
291
619
  return factory.NewComprehension(std::move(name), std::move(target),
292
619
                                  factory.AccuVarName(), std::move(init),
293
619
                                  std::move(condition), std::move(step),
294
619
                                  factory.NewAccuIdent());
295
715
}
296
297
2
Macro MakeFilterMacro() {
298
2
  auto status_or_macro =
299
2
      Macro::Receiver(CelOperator::FILTER, 2, ExpandFilterMacro);
300
2
  ABSL_CHECK_OK(status_or_macro);  // Crash OK
301
2
  return std::move(*status_or_macro);
302
2
}
303
304
absl::optional<Expr> ExpandOptMapMacro(MacroExprFactory& factory, Expr& target,
305
0
                                       absl::Span<Expr> args) {
306
0
  if (args.size() != 2) {
307
0
    return factory.ReportError("optMap() requires 2 arguments");
308
0
  }
309
0
  if (!IsSimpleIdentifier(args[0])) {
310
0
    return factory.ReportErrorAt(
311
0
        args[0], "optMap() variable name must be a simple identifier");
312
0
  }
313
0
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
314
0
    return factory.ReportErrorAt(
315
0
        args[1], absl::StrCat("optMap() variable name cannot be ",
316
0
                              kDeprecatedAccumulatorVariableName));
317
0
  }
318
0
  auto var_name = args[0].ident_expr().name();
319
320
0
  if (target.has_ident_expr()) {
321
0
    auto target_copy = factory.Copy(target);
322
0
    std::vector<Expr> call_args;
323
0
    call_args.reserve(3);
324
0
    call_args.push_back(factory.NewMemberCall("hasValue", std::move(target)));
325
0
    auto iter_range = factory.NewList();
326
0
    auto accu_init = factory.NewMemberCall("value", std::move(target_copy));
327
0
    auto condition = factory.NewBoolConst(false);
328
0
    auto fold = factory.NewComprehension(
329
0
        "#unused", std::move(iter_range), std::move(var_name),
330
0
        std::move(accu_init), std::move(condition), std::move(args[0]),
331
0
        std::move(args[1]));
332
0
    call_args.push_back(factory.NewCall("optional.of", std::move(fold)));
333
0
    call_args.push_back(factory.NewCall("optional.none"));
334
0
    return factory.NewCall(CelOperator::CONDITIONAL, std::move(call_args));
335
0
  }
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
0
  auto tmp = factory.NewIdent(kOptionalMapVar);
340
0
  auto tmp_copy = factory.Copy(tmp);
341
342
0
  auto iter_range = factory.NewList();
343
0
  auto accu_init = factory.NewMemberCall("value", std::move(tmp_copy));
344
0
  auto condition = factory.NewBoolConst(false);
345
0
  auto loop_step = std::move(args[0]);
346
0
  auto fold = factory.NewComprehension(
347
0
      "#unused", std::move(iter_range), std::move(var_name),
348
0
      std::move(accu_init), std::move(condition), std::move(loop_step),
349
0
      std::move(args[1]));
350
0
  std::vector<Expr> call_args;
351
0
  call_args.reserve(3);
352
0
  call_args.push_back(factory.NewMemberCall("hasValue", std::move(tmp)));
353
0
  call_args.push_back(factory.NewCall("optional.of", std::move(fold)));
354
0
  call_args.push_back(factory.NewCall("optional.none"));
355
0
  auto result = factory.NewCall(CelOperator::CONDITIONAL, std::move(call_args));
356
357
0
  iter_range = factory.NewList();
358
0
  accu_init = std::move(target);
359
0
  condition = factory.NewBoolConst(false);
360
0
  loop_step = factory.NewIdent(kOptionalMapVar);
361
0
  return factory.NewComprehension(
362
0
      "#unused", std::move(iter_range), kOptionalMapVar, std::move(accu_init),
363
0
      std::move(condition), loop_step, std::move(result));
364
0
}
365
366
0
Macro MakeOptMapMacro() {
367
0
  auto status_or_macro = Macro::Receiver("optMap", 2, ExpandOptMapMacro);
368
0
  ABSL_CHECK_OK(status_or_macro);  // Crash OK
369
0
  return std::move(*status_or_macro);
370
0
}
371
372
absl::optional<Expr> ExpandOptFlatMapMacro(MacroExprFactory& factory,
373
                                           Expr& target,
374
0
                                           absl::Span<Expr> args) {
375
0
  if (args.size() != 2) {
376
0
    return factory.ReportError("optFlatMap() requires 2 arguments");
377
0
  }
378
0
  if (!IsSimpleIdentifier(args[0])) {
379
0
    return factory.ReportErrorAt(
380
0
        args[0], "optFlatMap() variable name must be a simple identifier");
381
0
  }
382
0
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
383
0
    return factory.ReportErrorAt(
384
0
        args[1], absl::StrCat("optFlatMap() variable name cannot be ",
385
0
                              kDeprecatedAccumulatorVariableName));
386
0
  }
387
0
  auto var_name = args[0].ident_expr().name();
388
389
0
  if (target.has_ident_expr()) {
390
0
    auto target_copy = factory.Copy(target);
391
0
    std::vector<Expr> call_args;
392
0
    call_args.reserve(3);
393
0
    call_args.push_back(factory.NewMemberCall("hasValue", std::move(target)));
394
0
    auto iter_range = factory.NewList();
395
0
    auto accu_init = factory.NewMemberCall("value", std::move(target_copy));
396
0
    auto condition = factory.NewBoolConst(false);
397
0
    call_args.push_back(factory.NewComprehension(
398
0
        "#unused", std::move(iter_range), std::move(var_name),
399
0
        std::move(accu_init), std::move(condition), std::move(args[0]),
400
0
        std::move(args[1])));
401
0
    call_args.push_back(factory.NewCall("optional.none"));
402
0
    return factory.NewCall(CelOperator::CONDITIONAL, std::move(call_args));
403
0
  }
404
405
0
  auto tmp = factory.NewIdent(kOptionalMapVar);
406
0
  auto tmp_copy = factory.Copy(tmp);
407
408
0
  auto iter_range = factory.NewList();
409
0
  auto accu_init = factory.NewMemberCall("value", std::move(tmp_copy));
410
0
  auto condition = factory.NewBoolConst(false);
411
0
  auto loop_step = std::move(args[0]);
412
0
  auto inner = factory.NewComprehension(
413
0
      "#unused", std::move(iter_range), std::move(var_name),
414
0
      std::move(accu_init), std::move(condition), std::move(loop_step),
415
0
      std::move(args[1]));
416
0
  std::vector<Expr> call_args;
417
0
  call_args.reserve(3);
418
0
  call_args.push_back(factory.NewMemberCall("hasValue", std::move(tmp)));
419
0
  call_args.push_back(std::move(inner));
420
0
  call_args.push_back(factory.NewCall("optional.none"));
421
0
  auto result = factory.NewCall(CelOperator::CONDITIONAL, std::move(call_args));
422
423
0
  iter_range = factory.NewList();
424
0
  accu_init = std::move(target);
425
0
  condition = factory.NewBoolConst(false);
426
0
  loop_step = factory.NewIdent(kOptionalMapVar);
427
0
  return factory.NewComprehension(
428
0
      "#unused", std::move(iter_range), kOptionalMapVar, std::move(accu_init),
429
0
      std::move(condition), loop_step, std::move(result));
430
0
}
431
432
0
Macro MakeOptFlatMapMacro() {
433
0
  auto status_or_macro =
434
0
      Macro::Receiver("optFlatMap", 2, ExpandOptFlatMapMacro);
435
0
  ABSL_CHECK_OK(status_or_macro);  // Crash OK
436
0
  return std::move(*status_or_macro);
437
0
}
438
439
}  // namespace
440
441
absl::StatusOr<Macro> Macro::Global(absl::string_view name,
442
                                    size_t argument_count,
443
2
                                    GlobalMacroExpander expander) {
444
2
  if (!expander) {
445
0
    return absl::InvalidArgumentError(
446
0
        absl::StrCat("macro expander for `", name, "` cannot be empty"));
447
0
  }
448
2
  return Make(name, argument_count, ToMacroExpander(std::move(expander)),
449
2
              /*receiver_style=*/false, /*var_arg_style=*/false);
450
2
}
451
452
absl::StatusOr<Macro> Macro::GlobalVarArg(absl::string_view name,
453
0
                                          GlobalMacroExpander expander) {
454
0
  if (!expander) {
455
0
    return absl::InvalidArgumentError(
456
0
        absl::StrCat("macro expander for `", name, "` cannot be empty"));
457
0
  }
458
0
  return Make(name, 0, ToMacroExpander(std::move(expander)),
459
0
              /*receiver_style=*/false,
460
0
              /*var_arg_style=*/true);
461
0
}
462
463
absl::StatusOr<Macro> Macro::Receiver(absl::string_view name,
464
                                      size_t argument_count,
465
12
                                      ReceiverMacroExpander expander) {
466
12
  if (!expander) {
467
0
    return absl::InvalidArgumentError(
468
0
        absl::StrCat("macro expander for `", name, "` cannot be empty"));
469
0
  }
470
12
  return Make(name, argument_count, ToMacroExpander(std::move(expander)),
471
12
              /*receiver_style=*/true, /*var_arg_style=*/false);
472
12
}
473
474
absl::StatusOr<Macro> Macro::ReceiverVarArg(absl::string_view name,
475
0
                                            ReceiverMacroExpander expander) {
476
0
  if (!expander) {
477
0
    return absl::InvalidArgumentError(
478
0
        absl::StrCat("macro expander for `", name, "` cannot be empty"));
479
0
  }
480
0
  return Make(name, 0, ToMacroExpander(std::move(expander)),
481
0
              /*receiver_style=*/true,
482
0
              /*var_arg_style=*/true);
483
0
}
484
485
35.6k
std::vector<Macro> Macro::AllMacros() {
486
35.6k
  return {HasMacro(),  AllMacro(),  ExistsMacro(), ExistsOneMacro(),
487
35.6k
          Map2Macro(), Map3Macro(), FilterMacro()};
488
35.6k
}
489
490
std::string Macro::Key(absl::string_view name, size_t argument_count,
491
14
                       bool receiver_style, bool var_arg_style) {
492
14
  if (var_arg_style) {
493
0
    return absl::StrCat(name, ":*:", receiver_style ? "true" : "false");
494
0
  }
495
14
  return absl::StrCat(name, ":", argument_count, ":",
496
14
                      receiver_style ? "true" : "false");
497
14
}
498
499
absl::StatusOr<Macro> Macro::Make(absl::string_view name, size_t argument_count,
500
                                  MacroExpander expander, bool receiver_style,
501
14
                                  bool var_arg_style) {
502
14
  if (!internal::LexisIsIdentifier(name)) {
503
0
    return absl::InvalidArgumentError(absl::StrCat(
504
0
        "macro function name `", name, "` is not a valid identifier"));
505
0
  }
506
14
  if (!expander) {
507
0
    return absl::InvalidArgumentError(
508
0
        absl::StrCat("macro expander for `", name, "` cannot be empty"));
509
0
  }
510
14
  return Macro(std::make_shared<Rep>(
511
14
      std::string(name),
512
14
      Key(name, argument_count, receiver_style, var_arg_style), argument_count,
513
14
      std::move(expander), receiver_style, var_arg_style));
514
14
}
515
516
35.6k
const Macro& HasMacro() {
517
35.6k
  static const absl::NoDestructor<Macro> macro(MakeHasMacro());
518
35.6k
  return *macro;
519
35.6k
}
520
521
35.6k
const Macro& AllMacro() {
522
35.6k
  static const absl::NoDestructor<Macro> macro(MakeAllMacro());
523
35.6k
  return *macro;
524
35.6k
}
525
526
35.6k
const Macro& ExistsMacro() {
527
35.6k
  static const absl::NoDestructor<Macro> macro(MakeExistsMacro());
528
35.6k
  return *macro;
529
35.6k
}
530
531
35.6k
const Macro& ExistsOneMacro() {
532
35.6k
  static const absl::NoDestructor<Macro> macro(MakeExistsOneMacro());
533
35.6k
  return *macro;
534
35.6k
}
535
536
35.6k
const Macro& Map2Macro() {
537
35.6k
  static const absl::NoDestructor<Macro> macro(MakeMap2Macro());
538
35.6k
  return *macro;
539
35.6k
}
540
541
35.6k
const Macro& Map3Macro() {
542
35.6k
  static const absl::NoDestructor<Macro> macro(MakeMap3Macro());
543
35.6k
  return *macro;
544
35.6k
}
545
546
35.6k
const Macro& FilterMacro() {
547
35.6k
  static const absl::NoDestructor<Macro> macro(MakeFilterMacro());
548
35.6k
  return *macro;
549
35.6k
}
550
551
0
const Macro& OptMapMacro() {
552
0
  static const absl::NoDestructor<Macro> macro(MakeOptMapMacro());
553
0
  return *macro;
554
0
}
555
556
0
const Macro& OptFlatMapMacro() {
557
0
  static const absl::NoDestructor<Macro> macro(MakeOptFlatMapMacro());
558
0
  return *macro;
559
0
}
560
561
}  // namespace cel