Skip to content

12. The CEL environment

Contents of DISL 0.1

12.1 Base language

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.

12.2 DISL types

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.

12.3 Contexts

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

12.4 DISL function library

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.

12.5 Determinism

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.

Referenced from