2. Foundations
Contents of DESL 0.1
A DESL specification is a JSON text (RFC 8259) encoded in UTF-8 without a byte-order mark, whose top-level value is an object. Its file extension SHOULD be .des. Duplicate keys within one JSON object are a specification error. Property order carries no meaning except where this document says so: arrays are ordered, and so are the values of an enumeration and the rules of constraints.
- A simple identifier (
$defs/SimpleId) matches^[A-Za-z_][A-Za-z0-9_]*$. Element type names, attribute names, parameter names, operation names and function names MUST be simple identifiers, so that they are valid CEL identifiers. - A qualified identifier (
$defs/QualifiedId) matches^[A-Za-z_][A-Za-z0-9_-]*(\.[A-Za-z_][A-Za-z0-9_-]*)*$and names languages and finding codes (knowledge.no-title). - Identifiers are case-sensitive. Two identifiers of one namespace MUST NOT differ only in case.
- A type reference (
$defs/TypeRef) names an element type of the metamodel; where the schema allows, a list of them ($defs/TypeRefs) is given. A reference to an undeclared name is a specification error.
Namespaces. Element types and enumerations share one namespace. Constraints, operations and functions each have their own.
Reserved names. These MUST NOT be the names of attributes of an element type or of the document, because they are members of every element or variables in CEL (sections 9.2 and 9.3): id, type, parent, slot, children, document, self, item, p, count, selection, and any name beginning with _ or $. An operation's parameters are read as members of p, so they may use these names. CEL's keywords (in, as, break, const, continue, else, for, function, if, import, let, loop, package, namespace, return, var, void, while, true, false, null) are excluded too. A body that stores a value under one of these keys maps it to another attribute name in its binding (FBL section 5.2) or in the type map (section 5.2).
A LocalizedText ($defs/LocalizedText) is a plain string or an object mapping BCP 47 language tags to strings. A runtime picks the best match for the user's locale (RFC 4647 lookup), then language.defaultLocale (default "en"), then the first entry. cel is not a language tag and MUST NOT be used as one.
A Message ($defs/Message) is a LocalizedText or a CEL value { "cel": …, "resultType"?, "doc"? } returning string or map(string, string) keyed by locale. It is the shape of every sentence and label shown to the user: constraint messages, operation labels, confirmations and reasons. In a Message position an object with a cel property MUST be read as CEL. A runtime MUST evaluate a CEL Message each time it presents it, and MUST show a runtime-worded default and log a diagnostic when it fails to evaluate. The labels of the language, types, attributes and enumeration values, and doc objects, stay LocalizedText.
A Reason ($defs/Reason) says why something is refused or unavailable. It is a Message, which always applies, or { "when": Expression, "message": Message, "doc"?: Doc }, which applies while when holds. Reasons are used as ordered lists: the applicable reason is the first that applies, and a runtime MUST show that one, and only that one, as the explanation, wherever the user is looking.
Every object of a specification MAY carry doc, a LocalizedText (its summary) or a Doc object ($defs/Doc):
| Property | Type | Meaning |
|---|---|---|
summary |
LocalizedText | One sentence of plain text, for tooltips and hover cards. |
description |
LocalizedText | A longer explanation in CommonMark. |
rationale |
LocalizedText | Why the object exists. |
examples |
{title, description, value}[] |
Illustrations; value is any JSON. |
seeAlso |
{title, href}[] |
Links: absolute URIs, or relative to the specification's location. |
tags |
string[] | Keywords. |
audience |
("user", "author", "developer")[] |
Intended readers; "author" is the tool engineer. |
since |
string | The language version the object appeared in. |
deprecated |
bool or {since, message, replacedBy} |
Marks the object deprecated. |
helpUrl |
string | A page with more help. |
A label is the short display name of an object. Without label, a runtime derives one from the identifier by splitting camel case and capitalising the first word only (activeView → "Active view").
Every dynamic value is CEL (section 9). A property of type Expression ($defs/Expression) is a string of CEL, or { "cel": …, "resultType"?, "doc"? }; when resultType is given, a validator MUST check that the expression's static type is assignable to it. In actions (section 8.2) every value is an Expression, so a string literal is written with CEL quotes: "'Untitled'".
Expressions have no side effects. A runtime MUST impose a cost limit using CEL's cost estimation, language.limits.celCost (default 1 000 000), and a validator SHOULD reject an expression whose worst-case estimate exceeds it. At run time, an expression that fails is handled by its position:
| Position | On an evaluation error |
|---|---|
A constraint's rule, when or severity |
Reported as a finding of the constraint, with its severity and the message "could not be evaluated: …"; never silently passes. |
A Message or a Reason's when |
The position's default text is shown, or the reason does not apply; a diagnostic is logged. |
| An operation's actions, or a confirmation | The whole transaction is rolled back and the error reported to the user. |
| A derived id (5.3.2) | std.missingId on the element, as section 5.3.4 says. |
Every expression is evaluated in one context (9.3), which determines its variables. A validator MUST type-check every expression in its context, with the attribute types of the metamodel.
Any object of a specification MAY contain properties whose names begin with x-. Their content is unconstrained. A conforming tool MUST ignore extension properties it does not understand and MUST keep them when it rewrites a specification.
desl (required) is the DESL version the specification is written in, as "major.minor"; DESL 0.1 is "0.1". A runtime MUST refuse a specification of a higher major version than it supports, and SHOULD read one of a newer minor version, ignoring what it does not know, with a warning.
language.version (required) is the version of the designer type, a SemVer 2.0.0 string. A change that can make existing documents invalid or change their meaning is a major change; adding optional constructs is a minor change; documentation and wording are patch changes.