xref: /aosp_15_r20/external/googleapis/google/api/expr/v1alpha1/syntax.proto (revision d5c09012810ac0c9f33fe448fb6da8260d444cc9)
1// Copyright 2023 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//     http://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
15syntax = "proto3";
16
17package google.api.expr.v1alpha1;
18
19import "google/protobuf/duration.proto";
20import "google/protobuf/struct.proto";
21import "google/protobuf/timestamp.proto";
22
23option cc_enable_arenas = true;
24option go_package = "google.golang.org/genproto/googleapis/api/expr/v1alpha1;expr";
25option java_multiple_files = true;
26option java_outer_classname = "SyntaxProto";
27option java_package = "com.google.api.expr.v1alpha1";
28
29// A representation of the abstract syntax of the Common Expression Language.
30
31// An expression together with source information as returned by the parser.
32message ParsedExpr {
33  // The parsed expression.
34  Expr expr = 2;
35
36  // The source info derived from input that generated the parsed `expr`.
37  SourceInfo source_info = 3;
38}
39
40// An abstract representation of a common expression.
41//
42// Expressions are abstractly represented as a collection of identifiers,
43// select statements, function calls, literals, and comprehensions. All
44// operators with the exception of the '.' operator are modelled as function
45// calls. This makes it easy to represent new operators into the existing AST.
46//
47// All references within expressions must resolve to a
48// [Decl][google.api.expr.v1alpha1.Decl] provided at type-check for an
49// expression to be valid. A reference may either be a bare identifier `name` or
50// a qualified identifier `google.api.name`. References may either refer to a
51// value or a function declaration.
52//
53// For example, the expression `google.api.name.startsWith('expr')` references
54// the declaration `google.api.name` within a
55// [Expr.Select][google.api.expr.v1alpha1.Expr.Select] expression, and the
56// function declaration `startsWith`.
57message Expr {
58  // An identifier expression. e.g. `request`.
59  message Ident {
60    // Required. Holds a single, unqualified identifier, possibly preceded by a
61    // '.'.
62    //
63    // Qualified names are represented by the
64    // [Expr.Select][google.api.expr.v1alpha1.Expr.Select] expression.
65    string name = 1;
66  }
67
68  // A field selection expression. e.g. `request.auth`.
69  message Select {
70    // Required. The target of the selection expression.
71    //
72    // For example, in the select expression `request.auth`, the `request`
73    // portion of the expression is the `operand`.
74    Expr operand = 1;
75
76    // Required. The name of the field to select.
77    //
78    // For example, in the select expression `request.auth`, the `auth` portion
79    // of the expression would be the `field`.
80    string field = 2;
81
82    // Whether the select is to be interpreted as a field presence test.
83    //
84    // This results from the macro `has(request.auth)`.
85    bool test_only = 3;
86  }
87
88  // A call expression, including calls to predefined functions and operators.
89  //
90  // For example, `value == 10`, `size(map_value)`.
91  message Call {
92    // The target of an method call-style expression. For example, `x` in
93    // `x.f()`.
94    Expr target = 1;
95
96    // Required. The name of the function or method being called.
97    string function = 2;
98
99    // The arguments.
100    repeated Expr args = 3;
101  }
102
103  // A list creation expression.
104  //
105  // Lists may either be homogenous, e.g. `[1, 2, 3]`, or heterogeneous, e.g.
106  // `dyn([1, 'hello', 2.0])`
107  message CreateList {
108    // The elements part of the list.
109    repeated Expr elements = 1;
110
111    // The indices within the elements list which are marked as optional
112    // elements.
113    //
114    // When an optional-typed value is present, the value it contains
115    // is included in the list. If the optional-typed value is absent, the list
116    // element is omitted from the CreateList result.
117    repeated int32 optional_indices = 2;
118  }
119
120  // A map or message creation expression.
121  //
122  // Maps are constructed as `{'key_name': 'value'}`. Message construction is
123  // similar, but prefixed with a type name and composed of field ids:
124  // `types.MyType{field_id: 'value'}`.
125  message CreateStruct {
126    // Represents an entry.
127    message Entry {
128      // Required. An id assigned to this node by the parser which is unique
129      // in a given expression tree. This is used to associate type
130      // information and other attributes to the node.
131      int64 id = 1;
132
133      // The `Entry` key kinds.
134      oneof key_kind {
135        // The field key for a message creator statement.
136        string field_key = 2;
137
138        // The key expression for a map creation statement.
139        Expr map_key = 3;
140      }
141
142      // Required. The value assigned to the key.
143      //
144      // If the optional_entry field is true, the expression must resolve to an
145      // optional-typed value. If the optional value is present, the key will be
146      // set; however, if the optional value is absent, the key will be unset.
147      Expr value = 4;
148
149      // Whether the key-value pair is optional.
150      bool optional_entry = 5;
151    }
152
153    // The type name of the message to be created, empty when creating map
154    // literals.
155    string message_name = 1;
156
157    // The entries in the creation expression.
158    repeated Entry entries = 2;
159  }
160
161  // A comprehension expression applied to a list or map.
162  //
163  // Comprehensions are not part of the core syntax, but enabled with macros.
164  // A macro matches a specific call signature within a parsed AST and replaces
165  // the call with an alternate AST block. Macro expansion happens at parse
166  // time.
167  //
168  // The following macros are supported within CEL:
169  //
170  // Aggregate type macros may be applied to all elements in a list or all keys
171  // in a map:
172  //
173  // *  `all`, `exists`, `exists_one` -  test a predicate expression against
174  //    the inputs and return `true` if the predicate is satisfied for all,
175  //    any, or only one value `list.all(x, x < 10)`.
176  // *  `filter` - test a predicate expression against the inputs and return
177  //    the subset of elements which satisfy the predicate:
178  //    `payments.filter(p, p > 1000)`.
179  // *  `map` - apply an expression to all elements in the input and return the
180  //    output aggregate type: `[1, 2, 3].map(i, i * i)`.
181  //
182  // The `has(m.x)` macro tests whether the property `x` is present in struct
183  // `m`. The semantics of this macro depend on the type of `m`. For proto2
184  // messages `has(m.x)` is defined as 'defined, but not set`. For proto3, the
185  // macro tests whether the property is set to its default. For map and struct
186  // types, the macro tests whether the property `x` is defined on `m`.
187  message Comprehension {
188    // The name of the iteration variable.
189    string iter_var = 1;
190
191    // The range over which var iterates.
192    Expr iter_range = 2;
193
194    // The name of the variable used for accumulation of the result.
195    string accu_var = 3;
196
197    // The initial value of the accumulator.
198    Expr accu_init = 4;
199
200    // An expression which can contain iter_var and accu_var.
201    //
202    // Returns false when the result has been computed and may be used as
203    // a hint to short-circuit the remainder of the comprehension.
204    Expr loop_condition = 5;
205
206    // An expression which can contain iter_var and accu_var.
207    //
208    // Computes the next value of accu_var.
209    Expr loop_step = 6;
210
211    // An expression which can contain accu_var.
212    //
213    // Computes the result.
214    Expr result = 7;
215  }
216
217  // Required. An id assigned to this node by the parser which is unique in a
218  // given expression tree. This is used to associate type information and other
219  // attributes to a node in the parse tree.
220  int64 id = 2;
221
222  // Required. Variants of expressions.
223  oneof expr_kind {
224    // A literal expression.
225    Constant const_expr = 3;
226
227    // An identifier expression.
228    Ident ident_expr = 4;
229
230    // A field selection expression, e.g. `request.auth`.
231    Select select_expr = 5;
232
233    // A call expression, including calls to predefined functions and operators.
234    Call call_expr = 6;
235
236    // A list creation expression.
237    CreateList list_expr = 7;
238
239    // A map or message creation expression.
240    CreateStruct struct_expr = 8;
241
242    // A comprehension expression.
243    Comprehension comprehension_expr = 9;
244  }
245}
246
247// Represents a primitive literal.
248//
249// Named 'Constant' here for backwards compatibility.
250//
251// This is similar as the primitives supported in the well-known type
252// `google.protobuf.Value`, but richer so it can represent CEL's full range of
253// primitives.
254//
255// Lists and structs are not included as constants as these aggregate types may
256// contain [Expr][google.api.expr.v1alpha1.Expr] elements which require
257// evaluation and are thus not constant.
258//
259// Examples of literals include: `"hello"`, `b'bytes'`, `1u`, `4.2`, `-2`,
260// `true`, `null`.
261message Constant {
262  // Required. The valid constant kinds.
263  oneof constant_kind {
264    // null value.
265    google.protobuf.NullValue null_value = 1;
266
267    // boolean value.
268    bool bool_value = 2;
269
270    // int64 value.
271    int64 int64_value = 3;
272
273    // uint64 value.
274    uint64 uint64_value = 4;
275
276    // double value.
277    double double_value = 5;
278
279    // string value.
280    string string_value = 6;
281
282    // bytes value.
283    bytes bytes_value = 7;
284
285    // protobuf.Duration value.
286    //
287    // Deprecated: duration is no longer considered a builtin cel type.
288    google.protobuf.Duration duration_value = 8 [deprecated = true];
289
290    // protobuf.Timestamp value.
291    //
292    // Deprecated: timestamp is no longer considered a builtin cel type.
293    google.protobuf.Timestamp timestamp_value = 9 [deprecated = true];
294  }
295}
296
297// Source information collected at parse time.
298message SourceInfo {
299  // An extension that was requested for the source expression.
300  message Extension {
301    // Version
302    message Version {
303      // Major version changes indicate different required support level from
304      // the required components.
305      int64 major = 1;
306
307      // Minor version changes must not change the observed behavior from
308      // existing implementations, but may be provided informationally.
309      int64 minor = 2;
310    }
311
312    // CEL component specifier.
313    enum Component {
314      // Unspecified, default.
315      COMPONENT_UNSPECIFIED = 0;
316
317      // Parser. Converts a CEL string to an AST.
318      COMPONENT_PARSER = 1;
319
320      // Type checker. Checks that references in an AST are defined and types
321      // agree.
322      COMPONENT_TYPE_CHECKER = 2;
323
324      // Runtime. Evaluates a parsed and optionally checked CEL AST against a
325      // context.
326      COMPONENT_RUNTIME = 3;
327    }
328
329    // Identifier for the extension. Example: constant_folding
330    string id = 1;
331
332    // If set, the listed components must understand the extension for the
333    // expression to evaluate correctly.
334    //
335    // This field has set semantics, repeated values should be deduplicated.
336    repeated Component affected_components = 2;
337
338    // Version info. May be skipped if it isn't meaningful for the extension.
339    // (for example constant_folding might always be v0.0).
340    Version version = 3;
341  }
342
343  // The syntax version of the source, e.g. `cel1`.
344  string syntax_version = 1;
345
346  // The location name. All position information attached to an expression is
347  // relative to this location.
348  //
349  // The location could be a file, UI element, or similar. For example,
350  // `acme/app/AnvilPolicy.cel`.
351  string location = 2;
352
353  // Monotonically increasing list of code point offsets where newlines
354  // `\n` appear.
355  //
356  // The line number of a given position is the index `i` where for a given
357  // `id` the `line_offsets[i] < id_positions[id] < line_offsets[i+1]`. The
358  // column may be derivd from `id_positions[id] - line_offsets[i]`.
359  repeated int32 line_offsets = 3;
360
361  // A map from the parse node id (e.g. `Expr.id`) to the code point offset
362  // within the source.
363  map<int64, int32> positions = 4;
364
365  // A map from the parse node id where a macro replacement was made to the
366  // call `Expr` that resulted in a macro expansion.
367  //
368  // For example, `has(value.field)` is a function call that is replaced by a
369  // `test_only` field selection in the AST. Likewise, the call
370  // `list.exists(e, e > 10)` translates to a comprehension expression. The key
371  // in the map corresponds to the expression id of the expanded macro, and the
372  // value is the call `Expr` that was replaced.
373  map<int64, Expr> macro_calls = 5;
374
375  // A list of tags for extensions that were used while parsing or type checking
376  // the source expression. For example, optimizations that require special
377  // runtime support may be specified.
378  //
379  // These are used to check feature support between components in separate
380  // implementations. This can be used to either skip redundant work or
381  // report an error if the extension is unsupported.
382  repeated Extension extensions = 6;
383}
384
385// A specific position in source.
386message SourcePosition {
387  // The soucre location name (e.g. file name).
388  string location = 1;
389
390  // The UTF-8 code unit offset.
391  int32 offset = 2;
392
393  // The 1-based index of the starting line in the source text
394  // where the issue occurs, or 0 if unknown.
395  int32 line = 3;
396
397  // The 0-based index of the starting position within the line of source text
398  // where the issue occurs.  Only meaningful if line is nonzero.
399  int32 column = 4;
400}
401