Skip to content

10. Processing model

Contents of DESL 0.2

10.1 Loading a DESL specification

  1. Parse the JSON; reject duplicate keys.
  2. Check the version: desl major version supported.
  3. Validate against desl.schema.json#/$defs/Specification.
  4. Resolve names: every type, enumeration, operation and function named exists; every type the surface names is an element type of the metamodel, and every attribute it names is an attribute of the type it is named for; columns.options.type and cells.items are among the children of the columns' and the cells' types; each value type's key is an attribute of the cells' type, or of the items' type with many; every binding in persistence.bindings exists, and every rule type in it names an element type or a key of typeMap. (DESL 0.2) For a hierarchy surface: every type a role names is an element type and every attribute it names an attribute of that type, the levels' type contains itself and the entries' type, each label attribute is on every type of its on, and collapsed is on the levels' and the entries' types. Every type a mentions facet names is an element type. A counter rule's mark is a string attribute of the document. Every key of persistence.settings is a block every binding declares in registration.blocks, a list's type, key and value are a type and its attributes, and a state's attribute is an attribute of each type of its of.
  5. Check what the schema cannot: reserved attribute names (2.2), a positional create into an unordered parent (8.2), identity expressions that read other ids (5.3.2), functions that call themselves (3.3), and every other MUST of this document.
  6. Compile CEL: parse and type-check every expression in its context (9.3), and estimate its cost against language.limits.celCost.

A validator reports every problem with the JSON Pointer of its location, a severity (error makes the specification unusable; warning does not) and a message.

10.2 Opening a document

A host opens a document as FBL section 14.2 says, with the binding of section 5.1 its claims choose, and builds the model in this order:

  1. read the elements in reading order: the order of their first bytes in the body, which is document order; report std.unreadableEntry, std.missingId and std.duplicateId as they occur;
  2. give an element without a usable id a new id under missing: "assign", held in memory and written with the next edit, or treat it as ephemeral under missing: "ephemeral", and treat every second and later holder of a duplicated id as ephemeral (5.3.4);
  3. compute the derived ids (5.3.2), parents before children, letting references follow;
  4. evaluate the constraints with live timing and lay out the surface.

Unknown content is kept: an entry the binding cannot read stays in the body, byte for byte, and is reported (6.5).

10.3 The editing transaction

Every gesture, operation or quick change of a cell is one transaction:

  1. apply the operation's actions to a working state of the model (8.2);
  2. recompute derived ids, and rewrite every reference to an id that changed (5.3.2);
  3. check the constraints with enforcement prevent: a violation rolls the transaction back, and its message is the refusal (6.4);
  4. plan the changes as one edit of the body, by the binding's splices (FBL section 6.4); an edit FBL refuses rolls the transaction back with FBL's refusal;
  5. commit, as one undo step, and evaluate the live constraints.

Transactions are atomic: all of their effects apply or none. Undo and redo restore the body as it was before and after the step, and the model is read from it again. A step that changes two documents is one transaction over both (5.4).

10.4 Saving

A body is written by FBL's splices (FBL section 6.6), keeping every byte the transaction did not change. With blockSaveOn: "error", a host MUST ask before writing a document that has errors, and MUST still let it be written.

Referenced from