12. The CEL environment
Contents of DISL 0.1
DISL uses CEL as specified at https://github.com/google/cel-spec, with these standard extensions REQUIRED: strings (charAt, indexOf, lowerAscii, replace, split, substring, trim, upperAscii, format, join, reverse, quote), math (math.greatest, math.least, math.ceil, math.floor, math.round, math.abs, math.sqrt, …), lists (distinct, flatten, range, slice, sort, sortBy), sets (sets.contains, sets.intersects, sets.equivalent), optional types (?., .?, optional.of, orValue), and the cel.bind macro. Comprehension macros all, exists, exists_one, map, filter and has are available as in core CEL.
| CEL type | Fields and methods |
|---|---|
Element (nodes, relations, ports, diagram) |
id (string), type (string), kind ("node", "relation", "port", "diagram"), every attribute as a field (typed from the metamodel; references resolve to Element or null), isA(typeName) → bool, isTagged(tag) → bool, view → ViewData (placement of the element in the current view, null in headless contexts), label() → string (value of labelAttribute). |
| Node-specific | parent → Element?, owner → Element (parent or diagram), slot → string, children → list(Element), childrenOfType(t), descendants(), ancestors(), ancestorsOfType(t), depth() → int, ports → list(Element), portsOfType(name), incoming → list(Element), outgoing → list(Element), incomingOf(relType), outgoingOf(relType), neighbors(), successors(relType), predecessors(relType), reachable(relType) → list(Element) (transitive successors, excluding self unless on a cycle), inCycle(relType) → bool. |
| Relation-specific | source → Element, target → Element, sourcePort, targetPort (Element?), other(e) → Element (the opposite end). |
| Port-specific | owner → Element, connections → list(Element), direction → string. |
| Diagram | nodes → list(Element) (model nodes, not view-only), relations, elements (both), nodesOfType(t), relationsOfType(t), elementById(id) → Element?, hasCycle(relType) → bool, viewOnly → list(Element) (in the current view), diagram attributes as fields. |
ViewData |
x, y, x2, y2, width, height (domain values, dyn: double, timestamp, duration or band id), bounds → Bounds (canvas units), collapsed, rotation, z, pinned, params (map). |
Bounds |
x, y, width, height, x2, y2 (canvas or domain units depending on the context, as documented there), center() → list(double), intersects(Bounds) → bool, contains(Bounds) → bool. |
Env |
now → timestamp, locale → string, mode → string (theme mode), zoom → double, user → map (id, name; empty unless the runtime is configured to expose it), viewpoint → string, readOnly → bool. |
Attribute types map to CEL types per 4.2; enum values are strings; structs are map(string, dyn) with statically known fields; many attributes are lists.
The context of an expression determines its variables. Validators type-check each expression in exactly one context.
| Context | Used by | Variables |
|---|---|---|
element |
derived attributes, labels, styles conditions, variants, visibility, tooltips, markers, notation Bindables, form.visible of embedded forms |
self, diagram, env |
compartmentItem |
itemText, itemIcon, itemStyle |
self, item, index, diagram, env |
shape |
GeomExpr in shapes, markers, handles, form regions | w, h, p, self, env; in markers additionally sw (stroke width) |
handle |
Handle.value, yValue |
as shape, plus px, py |
placement |
computed placement sources | self, diagram, env, parent, axis ({kind, min, max}) |
placementWrite |
placement write actions |
as placement, plus value (snapped domain value) |
snap |
CEL snap rules | value, axis, zoom, self, parent, diagram |
categories |
ordinal categories expressions |
diagram, env |
constraint |
invariant when, rule, message, target, severity, fix when |
self, diagram, env (env.now is fixed at the start of a validation run) |
gesture:<kind> |
gesture constraints | per 8.4 |
create |
attribute CEL defaults, tool initial, id expression |
diagram, env, parent, elementType, position |
form |
form visible, enabled, validate, options |
self, value (current field value), diagram, env |
hook |
hook when and actions |
self, old, event, diagram, env, plus let/as bindings |
operation |
operation enabled and actions |
self or selection, p, diagram, env, plus bindings |
template |
template attribute and position expressions | p, diagram, env, refs (map of created elements by ref) |
migration |
migration steps | element (raw record map), value, document (raw map), from, to (version strings) |
function |
user functions | parameters, plus diagram/env if declared in uses |
In addition to the members listed in 12.2, these global functions are available in all contexts unless noted:
| Function | Description |
|---|---|
l.isUnique() → bool |
All elements of the list differ. |
l.sum(), l.min(), l.max(), l.avg() |
Numeric aggregates (int/double/duration). |
l.count(x, pred) |
Macro: number of elements satisfying pred. |
l.indexOf(v) → int |
First index or −1. |
l.first(), l.last() |
optional element. |
snap(v, step) → double |
Round to the nearest multiple. snapFloor, snapCeil. |
snapTo(v, list) → double |
Nearest value from a list. |
clamp(v, lo, hi) |
Clamp a number. |
min(a, b, …), max(a, b, …) |
Smallest or largest of two to four numbers (aliases of math.least / math.greatest, convenient in geometry). |
m.with(m2) → map |
A copy of map m with the entries of m2 added or replaced (used in migrations and actions to build attribute maps). |
ordinal(value, enumName) → int |
Position of an enum value. |
enumLabel(enumName, value) → string, enumColor(...), enumIcon(...) |
Enum metadata. |
token(name) → string |
Resolved theme token (element, shape contexts). |
color(c).lighten(f), .darken(f), .alpha(f), .mix(c2, f), .contrastText() → string |
Color manipulation; contrastText returns a readable text color for a background. |
formatNumber(n, pattern) → string |
ICU number formatting in env.locale. |
formatDate(t, pattern) → string, formatDate(t, pattern, tz) |
LDML date formatting. |
formatDuration(d, style) → string |
"short" (3d 4h), "long", "iso". |
date(y, m, d) → timestamp, timestamp(string) (core) |
Construction. |
t.startOf(unit[, tz]), t.endOf(unit[, tz]), t.addUnits(n, unit[, tz]) |
Calendar arithmetic (units as in 5.5). |
workingDays(a, b, calendarId) → int, addWorkingDays(t, n, calendarId) → timestamp, isWorkingTime(t, calendarId) → bool |
Calendar functions using axis calendars. |
daysBetween(a, b) → int |
Calendar days. |
distance(p1, p2) → double |
Euclidean distance of points. |
lower(s), upper(s) |
Aliases of lowerAscii/upperAscii with Unicode case mapping. |
matchesGlob(s, glob) → bool |
Glob matching (safer than regex for users). |
diagram.nodesOfType(t, includeViewOnly) |
Include view-only elements. |
Implementations MUST provide cost estimates for all library functions; graph traversals (reachable, hasCycle, inCycle) have cost proportional to the number of relations of the given type and SHOULD be memoised per validation run.
Expressions in the contexts constraint, migration, create (except env.now), placement and snap MUST be deterministic given the DID definition. env.now is the only source of time and is fixed per evaluation run. Random functions do not exist. Iteration order of diagram.nodes and similar lists is the persistence order (11.7), so results are reproducible across tools.