Coverage Report

Created: 2023-05-25 06:18

/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