Coverage Report

Created: 2026-10-09 06:57

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
49.9k
bool IsSimpleIdentifier(const Expr& expr) {
47
49.9k
  return expr.has_ident_expr() && !expr.ident_expr().name().empty() &&
48
48.7k
         !absl::StartsWith(expr.ident_expr().name(), ".");
49
49.9k
}
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
182k
             absl::Span<Expr> arguments) -> absl::optional<Expr> {
57
182k
    ABSL_DCHECK(!target.has_value());
58
182k
    return (expander)(factory, arguments);
59
182k
  };
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
49.9k
             absl::Span<Expr> arguments) -> absl::optional<Expr> {
68
49.9k
    ABSL_DCHECK(target.has_value());
69
49.9k
    return (expander)(factory, *target, arguments);
70
49.9k
  };
71
12
}
72
73
absl::optional<Expr> ExpandHasMacro(MacroExprFactory& factory,
74
182k
                                    absl::Span<Expr> args) {
75
182k
  if (args.size() != 1) {
76
0
    return factory.ReportError("has() requires 1 arguments");
77
0
  }
78
182k
  if (!args[0].has_select_expr() || args[0].select_expr().test_only()) {
79
180k
    return factory.ReportErrorAt(args[0],
80
180k
                                 "has() argument must be a field selection");
81
180k
  }
82
2.03k
  return factory.NewPresenceTest(
83
2.03k
      args[0].mutable_select_expr().release_operand(),
84
2.03k
      args[0].mutable_select_expr().release_field());
85
182k
}
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
1.81k
                                    absl::Span<Expr> args) {
95
1.81k
  if (args.size() != 2) {
96
0
    return factory.ReportError("all() requires 2 arguments");
97
0
  }
98
1.81k
  if (!IsSimpleIdentifier(args[0])) {
99
514
    return factory.ReportErrorAt(
100
514
        args[0], "all() variable name must be a simple identifier");
101
514
  }
102
1.30k
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
103
133
    return factory.ReportErrorAt(
104
133
        args[1], absl::StrCat("all() variable name cannot be ",
105
133
                              kDeprecatedAccumulatorVariableName));
106
133
  }
107
1.16k
  auto init = factory.NewBoolConst(true);
108
1.16k
  auto condition =
109
1.16k
      factory.NewCall(CelOperator::NOT_STRICTLY_FALSE, factory.NewAccuIdent());
110
1.16k
  auto step = factory.NewCall(CelOperator::LOGICAL_AND, factory.NewAccuIdent(),
111
1.16k
                              std::move(args[1]));
112
1.16k
  auto result = factory.NewAccuIdent();
113
1.16k
  return factory.NewComprehension(args[0].ident_expr().name(),
114
1.16k
                                  std::move(target), factory.AccuVarName(),
115
1.16k
                                  std::move(init), std::move(condition),
116
1.16k
                                  std::move(step), std::move(result));
117
1.30k
}
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.05k
                                       absl::Span<Expr> args) {
127
1.05k
  if (args.size() != 2) {
128
0
    return factory.ReportError("exists() requires 2 arguments");
129
0
  }
130
1.05k
  if (!IsSimpleIdentifier(args[0])) {
131
91
    return factory.ReportErrorAt(
132
91
        args[0], "exists() variable name must be a simple identifier");
133
91
  }
134
967
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
135
114
    return factory.ReportErrorAt(
136
114
        args[1], absl::StrCat("exists() variable name cannot be ",
137
114
                              kDeprecatedAccumulatorVariableName));
138
114
  }
139
853
  auto init = factory.NewBoolConst(false);
140
853
  auto condition = factory.NewCall(
141
853
      CelOperator::NOT_STRICTLY_FALSE,
142
853
      factory.NewCall(CelOperator::LOGICAL_NOT, factory.NewAccuIdent()));
143
853
  auto step = factory.NewCall(CelOperator::LOGICAL_OR, factory.NewAccuIdent(),
144
853
                              std::move(args[1]));
145
853
  auto result = factory.NewAccuIdent();
146
853
  return factory.NewComprehension(args[0].ident_expr().name(),
147
853
                                  std::move(target), factory.AccuVarName(),
148
853
                                  std::move(init), std::move(condition),
149
853
                                  std::move(step), std::move(result));
150
967
}
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.25k
                                          Expr& target, absl::Span<Expr> args) {
161
6.25k
  if (args.size() != 2) {
162
0
    return factory.ReportError("exists_one() requires 2 arguments");
163
0
  }
164
6.25k
  if (!IsSimpleIdentifier(args[0])) {
165
386
    return factory.ReportErrorAt(
166
386
        args[0], "exists_one() variable name must be a simple identifier");
167
386
  }
168
5.86k
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
169
82
    return factory.ReportErrorAt(
170
82
        args[1], absl::StrCat("exists_one() variable name cannot be ",
171
82
                              kDeprecatedAccumulatorVariableName));
172
82
  }
173
5.78k
  auto init = factory.NewIntConst(0);
174
5.78k
  auto condition = factory.NewBoolConst(true);
175
5.78k
  auto accu_ident = factory.NewAccuIdent();
176
5.78k
  auto const_1 = factory.NewIntConst(1);
177
5.78k
  auto inc_step = factory.NewCall(CelOperator::ADD, std::move(accu_ident),
178
5.78k
                                  std::move(const_1));
179
180
5.78k
  auto step = factory.NewCall(CelOperator::CONDITIONAL, std::move(args[1]),
181
5.78k
                              std::move(inc_step), factory.NewAccuIdent());
182
5.78k
  accu_ident = factory.NewAccuIdent();
183
5.78k
  auto result = factory.NewCall(CelOperator::EQUALS, std::move(accu_ident),
184
5.78k
                                factory.NewIntConst(1));
185
5.78k
  return factory.NewComprehension(args[0].ident_expr().name(),
186
5.78k
                                  std::move(target), factory.AccuVarName(),
187
5.78k
                                  std::move(init), std::move(condition),
188
5.78k
                                  std::move(step), std::move(result));
189
5.86k
}
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
17.5k
                                     absl::Span<Expr> args) {
200
17.5k
  if (args.size() != 2) {
201
0
    return factory.ReportError("map() requires 2 arguments");
202
0
  }
203
17.5k
  if (!IsSimpleIdentifier(args[0])) {
204
662
    return factory.ReportErrorAt(
205
662
        args[0], "map() variable name must be a simple identifier");
206
662
  }
207
16.8k
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
208
138
    return factory.ReportErrorAt(
209
138
        args[1], absl::StrCat("map() variable name cannot be ",
210
138
                              kDeprecatedAccumulatorVariableName));
211
138
  }
212
16.7k
  auto init = factory.NewList();
213
16.7k
  auto condition = factory.NewBoolConst(true);
214
16.7k
  auto accu_ref = factory.NewAccuIdent();
215
16.7k
  auto accu_update =
216
16.7k
      factory.NewList(factory.NewListElement(std::move(args[1])));
217
16.7k
  auto step = factory.NewCall(CelOperator::ADD, std::move(accu_ref),
218
16.7k
                              std::move(accu_update));
219
16.7k
  return factory.NewComprehension(args[0].ident_expr().name(),
220
16.7k
                                  std::move(target), factory.AccuVarName(),
221
16.7k
                                  std::move(init), std::move(condition),
222
16.7k
                                  std::move(step), factory.NewAccuIdent());
223
16.8k
}
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
22.2k
                                     absl::Span<Expr> args) {
233
22.2k
  if (args.size() != 3) {
234
0
    return factory.ReportError("map() requires 3 arguments");
235
0
  }
236
22.2k
  if (!IsSimpleIdentifier(args[0])) {
237
192
    return factory.ReportErrorAt(
238
192
        args[0], "map() variable name must be a simple identifier");
239
192
  }
240
22.0k
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
241
145
    return factory.ReportErrorAt(
242
145
        args[1], absl::StrCat("map() variable name cannot be ",
243
145
                              kDeprecatedAccumulatorVariableName));
244
145
  }
245
21.9k
  auto init = factory.NewList();
246
21.9k
  auto condition = factory.NewBoolConst(true);
247
21.9k
  auto accu_ref = factory.NewAccuIdent();
248
21.9k
  auto accu_update =
249
21.9k
      factory.NewList(factory.NewListElement(std::move(args[2])));
250
21.9k
  auto step = factory.NewCall(CelOperator::ADD, std::move(accu_ref),
251
21.9k
                              std::move(accu_update));
252
21.9k
  step = factory.NewCall(CelOperator::CONDITIONAL, std::move(args[1]),
253
21.9k
                         std::move(step), factory.NewAccuIdent());
254
21.9k
  return factory.NewComprehension(args[0].ident_expr().name(),
255
21.9k
                                  std::move(target), factory.AccuVarName(),
256
21.9k
                                  std::move(init), std::move(condition),
257
21.9k
                                  std::move(step), factory.NewAccuIdent());
258
22.0k
}
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
1.03k
                                       absl::Span<Expr> args) {
268
1.03k
  if (args.size() != 2) {
269
0
    return factory.ReportError("filter() requires 2 arguments");
270
0
  }
271
1.03k
  if (!IsSimpleIdentifier(args[0])) {
272
79
    return factory.ReportErrorAt(
273
79
        args[0], "filter() variable name must be a simple identifier");
274
79
  }
275
953
  if (args[0].ident_expr().name() == kDeprecatedAccumulatorVariableName) {
276
73
    return factory.ReportErrorAt(
277
73
        args[1], absl::StrCat("filter() variable name cannot be ",
278
73
                              kDeprecatedAccumulatorVariableName));
279
73
  }
280
880
  auto name = args[0].ident_expr().name();
281
282
880
  auto init = factory.NewList();
283
880
  auto condition = factory.NewBoolConst(true);
284
880
  auto accu_ref = factory.NewAccuIdent();
285
880
  auto accu_update =
286
880
      factory.NewList(factory.NewListElement(std::move(args[0])));
287
880
  auto step = factory.NewCall(CelOperator::ADD, std::move(accu_ref),
288
880
                              std::move(accu_update));
289
880
  step = factory.NewCall(CelOperator::CONDITIONAL, std::move(args[1]),
290
880
                         std::move(step), factory.NewAccuIdent());
291
880
  return factory.NewComprehension(std::move(name), std::move(target),
292
880
                                  factory.AccuVarName(), std::move(init),
293
880
                                  std::move(condition), std::move(step),
294
880
                                  factory.NewAccuIdent());
295
953
}
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
33.5k
std::vector<Macro> Macro::AllMacros() {
486
33.5k
  return {HasMacro(),  AllMacro(),  ExistsMacro(), ExistsOneMacro(),
487
33.5k
          Map2Macro(), Map3Macro(), FilterMacro()};
488
33.5k
}
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
33.5k
const Macro& HasMacro() {
517
33.5k
  static const absl::NoDestructor<Macro> macro(MakeHasMacro());
518
33.5k
  return *macro;
519
33.5k
}
520
521
33.5k
const Macro& AllMacro() {
522
33.5k
  static const absl::NoDestructor<Macro> macro(MakeAllMacro());
523
33.5k
  return *macro;
524
33.5k
}
525
526
33.5k
const Macro& ExistsMacro() {
527
33.5k
  static const absl::NoDestructor<Macro> macro(MakeExistsMacro());
528
33.5k
  return *macro;
529
33.5k
}
530
531
33.5k
const Macro& ExistsOneMacro() {
532
33.5k
  static const absl::NoDestructor<Macro> macro(MakeExistsOneMacro());
533
33.5k
  return *macro;
534
33.5k
}
535
536
33.5k
const Macro& Map2Macro() {
537
33.5k
  static const absl::NoDestructor<Macro> macro(MakeMap2Macro());
538
33.5k
  return *macro;
539
33.5k
}
540
541
33.5k
const Macro& Map3Macro() {
542
33.5k
  static const absl::NoDestructor<Macro> macro(MakeMap3Macro());
543
33.5k
  return *macro;
544
33.5k
}
545
546
33.5k
const Macro& FilterMacro() {
547
33.5k
  static const absl::NoDestructor<Macro> macro(MakeFilterMacro());
548
33.5k
  return *macro;
549
33.5k
}
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