1. Introduction
Contents of FBL 0.17
Many ADP tools do not own the file their model lives in. A C4 diagram's model is a Structurizr workspace, a mind map's is a Freeplane .mm file, a Databricks job's is a bundle resource file, and even ADP's own formats (the timeline's .tml, the causal loop diagram's .cld) are meant to be read and edited by hand beside ADP. DISL's persistence layer (DISL §11) describes something else: a DID definition that a writer regenerates canonically. Before FBL, every such tool declared a required persistence plugin, which is code, and code has to be written once for each of the four ADP hosts.
FBL, the Format Binding Language, declares instead how such a file maps to a tool type's model in both directions:
- which files a tool claims, and how a host routes a file to it;
- how the file is read into elements, relations and attribute values, tolerating whatever it cannot read;
- how every change to the model is written back as named, minimal splices, so that everything the change does not concern stays byte for byte as it was, and so that every edit has an exact undo;
- where the view data a user places (positions) is kept: in an
.adpregistration beside the file, never in the file; - how several tool types read one file at once, and how a folder is read and watched as one subject;
- and, for the formats that are too intricate to declare, the contract a persistence plugin implements, so that plugins behave alike in every host.
A tool engineer writes an FBL document, *.fbl, holding one or more named bindings, and points a tool type's specification at one of them, or, for a tool type whose documents may be written in several formats, at one binding per format family:
{ "persistence": { "format": "fbl", "binding": "timeline.fbl#timeline" } }
{ "persistence": { "format": "fbl", "bindings": ["knowledge.fbl#yaml", "knowledge.fbl#json", "knowledge.fbl#xml"] } }
A host that opens a file first routes it to a binding (section 12), reads its registration if there is one (section 8), opens the body through the binding for the body's family (sections 4 and 5) and builds the model the tool type's specification describes. Every transaction the user commits is planned as splices (section 6), applied to the body's bytes and kept in the body's history for undo (section 7). Positions the user drags are written to the registration. Other tools can keep editing the body, and the host picks their changes up (section 7.3).
The same binding serves every host. The round-trip fixtures in fixtures/ (section 15.3) are the shared test: a host that passes them reads and writes bodies the way every other host does.
FBL serves every kind of tool. What it reads a body into, and the constructs it relies on, are defined by the specification language of the tool type's kind: DISL for a diagram, DESL for a designer. Each language defines them on its own; neither takes them from the other.
| Concern | For a diagram | For a designer |
|---|---|---|
| Metamodel, constraints, behaviour and presentation of a tool type | DISL | DESL |
| Element types, attributes, containment, references ("node type" and "relation type" in this document) | DISL §4 | DESL section 4 (element types; a designer has no relation types) |
A binding's type and attribute names mapped onto the metamodel (persistence.typeMap) |
DISL §11.2 | DESL section 5.2 |
| Id strategies, derived ids, ephemeral (unstable) ids | DISL §11.5 (persistence.ids) |
DESL section 5.3 (persistence.ids) |
Findings, their severities, codes and source locations; the built-in findings std.unparseable, std.unreadableEntry, std.missingId, std.duplicateId |
DISL §8.6, §8.7 | DESL sections 6.3, 6.5 |
std.pluginMissing, derived elements, computed containment |
DISL §8.7, §4.11 | none: DESL 0.1 has no plugins and no derived elements |
Reading order and positionIn |
DISL §8.6, §12.4 | DESL sections 10.2, 9.4 |
| The editing transaction | DISL §14.4 | DESL section 10.3 |
A tool type's origin, <vendor>/<type> |
DISL §3.2 (language.origin) |
DESL section 3.2 (language.origin) |
| Localized text and documentation objects | DISL §2.3, §2.4 | DESL sections 2.3, 2.4 |
| CEL, its cost limits and its determinism | DISL §2.5, §12 | DESL sections 2.5, 9 |
| Extension properties | DISL §2.8 | DESL section 2.6 |
| A document stored as ADP's own definition file | DID | DED |
| A model stored in a file or folder another tool owns | FBL | FBL |
The .adp registration, view data of such a model, routing |
FBL | FBL |
DISL's persistence layer names FBL with format: "fbl" and binding (DISL §11.2); DESL's with format: "fbl" and bindings (DESL section 5). With that format, DISL's writer settings (files, indent, newline, ordering, precision and the others DISL lists) do not apply: FBL writes by splices and keeps the file's own conventions.
- The file is the model. A body is the only store of its model. A host MUST NOT keep a second copy of the model anywhere (a cache is not a copy if it is rebuilt from the body).
- Touch only what changed. A save without an edit writes the bytes that were read. An edit changes only the bytes of its splices.
- Every write can be undone exactly, or is refused before it happens.
- Reading never fails on content. What cannot be read becomes a finding; what is not bound is kept.
- One answer in every host. Everything that decides bytes (spans, splices, formatting of new text) is specified here, so two hosts write the same bytes for the same edit.
- Declare what can be declared; contract the rest. A format FBL cannot declare is read by a plugin, but everything around the plugin (routing, registration, history, drift) is still FBL's.
- FBL is not a general grammar formalism. It covers the format families of section 4, which are the ones today's tools need (constitution principle V). (FBL 0.9) The
grammarfamily carries a grammar, but only to read one format's syntax as a tree that rules select from; what a node means is still the binding's rules, and an LALR(1) grammar in ATD's notation is all it admits. - FBL does not compute the model beyond reading it: which elements a view shows, derived elements and layouts are the specification language's.
- FBL does not merge concurrent edits. A body is edited by one host at a time; changes from anywhere else arrive as external changes (section 7.3).