9. The CEL environment
Contents of DESL 0.2
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.
| 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.
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 |
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.
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.