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