Skip to content

9. The CEL environment

Contents of DESL 0.2

9.1 Base language

DESL uses CEL as specified at https://github.com/google/cel-spec, with these standard extensions REQUIRED: strings (lowerAscii, upperAscii, trim, split, join, replace, indexOf, substring, format), lists (distinct, flatten, range, slice, sort, sortBy), optional types (?., .?, orValue) and the cel.bind macro. The macros all, exists, exists_one, map, filter and has are available as in core CEL. Strings order by Unicode code point, and sorts are stable.

9.2 Types

CEL type Members
Element id (string), type (string), every attribute as a field (typed by the metamodel; a reference resolves to an Element or null), isA(typeName) → bool, parent → Element? (null for the document's own elements), slot → string (the slot it is kept in, '' without one), children → list(Element) (in order), childrenOfType(t) → list(Element), ancestors() → list(Element) (the parent first), ancestorsOfType(t) → list(Element) (in the same order), positionIn(list) → int (9.4), label() → string (the value of its labelAttribute).
Document elements → list(Element) (every element, in document order), elementsOfType(t) → list(Element), elementById(id) → Element?, and the document's attributes as fields.

Attribute types map to CEL types as section 4.2 says; enumeration values are strings, their keys; many attributes are lists.

9.3 Contexts

The context of an expression determines its variables. A validator type-checks each expression in exactly one context.

Context Used by Variables
constraint a constraint's when, rule, severity, message and target self (an element, or the document for scope: "document"), document
identity the expression and ephemeral of an id rule (5.3.2) self, document; self.id is not readable, and the ids readable are those of self's ancestors
operation an operation's label, unavailable, confirm and actions self (for for naming types) or selection (for "selection"), document, p (not in label and unavailable), count in a confirmation, and the names create … as, let and forEach … as bind
function a function's body its parameters, and document when its uses lists it

9.4 Function library

Besides the members of 9.2, these are available in every context:

Function Description
e.positionIn(l) → int The zero-based position of element e in list l, comparing elements by identity, never by id, or −1. Lists of elements are in reading order (10.2), so positionIn works while ids are being computed and when ids are duplicated: self.positionIn(group) == 0 holds for the first of a group only.
uniqueName(name, names) → string name when no string of names equals it ignoring case; otherwise name + ' ' + string(n) for the smallest n ≥ 2 that no string of names equals ignoring case.
l.isUnique() → bool All items of the list differ.

Implementations MUST provide cost estimates for these functions.

9.5 Determinism

Expressions in the constraint and identity contexts MUST be deterministic given the document: they have no source of time, randomness or viewer state. Lists of elements are in document order, so results are the same in every host.

Referenced from