CEL.Checked (CEL v0.2.0)

Copy Markdown View Source

A type-checked CEL expression, from CEL.check/2.

The struct is opaque. Inspect it with:

  • type/1 and type/2 — the type of the expression, or of one subexpression by id, as a CEL.Type.t/0.
  • position/2 — where a subexpression is in the source.
  • expr/1 — the expression as a tree of CEL.Expr nodes.
  • references/1 — the variable paths it reads and the custom functions it calls, with their arguments when they are constants or variable paths.
  • to_proto/1 — the standard cel.expr.CheckedExpr map, for exchange with other CEL implementations.

Evaluate it by bundling it with its environment: CEL.Program.new/2.

Summary

Types

A call's argument: a constant, a variable path, or anything else.

A call to a non-operator function.

The id of a subexpression, as in CEL.Expr nodes.

A place in the source: offset counts code points from the start, line and column are 1-based and count code points too.

What references/1 returns.

t()

A type-checked expression; see the module docs.

A variable path an expression reads, such as req.user.id.

Functions

Returns a read-only view of the expression as a tree of CEL.Expr nodes.

Where the expression with the given id is in the source, or nil if the parser recorded no position for it.

Returns what the expression reads: variable field paths and non-operator function calls with their arguments, in evaluation order.

The expression as a standard cel.expr.CheckedExpr map (the generated protobuf shape), for exchange with other CEL implementations.

The type of the whole expression.

The type of the expression with the given id, or nil if the checker did not type it (such as a comprehension's variable name).

Types

arg()

@type arg() :: {:const, CEL.Value.t()} | {:var, String.t(), [String.t()]} | :dynamic

A call's argument: a constant, a variable path, or anything else.

call()

@type call() :: %{
  function: String.t(),
  overload_id: String.t(),
  expr_id: expr_id(),
  target: arg() | nil,
  args: [arg()]
}

A call to a non-operator function.

expr_id()

@type expr_id() :: non_neg_integer()

The id of a subexpression, as in CEL.Expr nodes.

position()

@type position() :: %{
  offset: non_neg_integer(),
  line: pos_integer(),
  column: pos_integer()
}

A place in the source: offset counts code points from the start, line and column are 1-based and count code points too.

references()

@type references() :: %{vars: [var_read()], calls: [call()]}

What references/1 returns.

t()

@type t() :: %CEL.Checked{
  enums: term(),
  expr: term(),
  expr_version: term(),
  ops: term(),
  root_type: term(),
  source_info: term(),
  types: term()
}

A type-checked expression; see the module docs.

var_read()

@type var_read() :: %{name: String.t(), path: [String.t()], expr_id: expr_id()}

A variable path an expression reads, such as req.user.id.

Functions

expr(checked)

@spec expr(t()) :: CEL.Expr.t()

Returns a read-only view of the expression as a tree of CEL.Expr nodes.

position(checked, id)

@spec position(t(), expr_id()) :: position() | nil

Where the expression with the given id is in the source, or nil if the parser recorded no position for it.

The position is the start of a literal, name, function call or message literal; the operator of an operator such as a + b or a[0]; and the . of a field selection or method call. Expressions a macro expands to share the macro's position.

checked = CEL.check!("1 +

x", CEL.Env.build(vars: [x: :int]))

[_one, x] = CEL.Checked.expr(checked).args

CEL.Checked.position(checked, x.id)
#=> %{offset: 6, line: 2, column: 3}

references(checked)

@spec references(t()) :: references()

Returns what the expression reads: variable field paths and non-operator function calls with their arguments, in evaluation order.

A variable read is the longest field selection rooted at a variable, so req.user.id is one read with path ["user", "id"], not three. Variables a macro binds are resolved to what they stand for: a cel.bind or optMap variable to its value, and a comprehension variable to its range followed by "*" for "any element", so l.exists(i, i.score > 1) reads l and l.*.score. Locals bound to anything other than a variable read are not reported.

Operators (_==_, @in, ...), macros and enum constructors are not reported as calls. A call's expr_id is the one a custom function receives through eval_context: [:call].

to_proto(checked)

@spec to_proto(t()) :: map()

The expression as a standard cel.expr.CheckedExpr map (the generated protobuf shape), for exchange with other CEL implementations.

type(checked)

@spec type(t()) :: CEL.Type.t()

The type of the whole expression.

type(checked, id)

@spec type(t(), expr_id()) :: CEL.Type.t() | nil

The type of the expression with the given id, or nil if the checker did not type it (such as a comprehension's variable name).