Example
The whole language in one short program — a module with a record, a tagged union, a function with per-platform native bodies, and a function that wires up state, a write-back and a return — and the complete canonical JSON it is stored as. It is the same program shown on the language page, and the form every other target renders from.
Contents
JSON is the canonical command form every module is stored in — the interchange the other targets render from, not a language you run. These pages describe that form.
- Introduction — what the JSON form is, and how to read the rest of this section.
- Capabilities — which high-level features are possible — deferred to whichever target this JSON renders to.
- Example — a full program using every keyword, in the canonical JSON form.
- Naming considerations — how Program's dotted names are stored, verbatim and un-munged.
- Object format — every node in the self-describing object form, keyword by keyword.
- Array format — every node in the compact tagged-array form, keyword by keyword.
- Project setup — there is no build; how a module file is stored, read and rendered onward.
- Reserved words — why the canonical form has none, and never escapes a name.
Every keyword, in one program
Each keyword has its own page under keywords; here they are all together.
MODULE App
TYPE Profile
FIELD Text name
FIELD Maths.Integer age
TYPE Status
OPTION App.Profile active
OPTION Text pending
FUNCTION Text Greet
INPUT Text name
NATIVE js "return 'Hi ' + name;"
NATIVE dart "return 'Hi ' + name;"
FUNCTION Text Welcome
INPUT BINDING App.Profile profile
HOLE Text row
INPUT Text line
STATE Maths.Integer count = 0
STATE LOCKED Network.Web.Response saved = null
REVERSE App.Profile submit
LET Network.Web.Response response = Network.Web.Client.Post profile
SET saved = response
LET Text label = Maths.Integer.ToString count
= label
The whole thing in canonical JSON
Stored form, not a rendered language — the exact tree every other target reads. Its declaration
nodes use the short tags M module, D data, U union,
N native, F function, P field/option; its run-body commands use
$ state, = let, > effect, S reverse,
# literal. Every node's canonical shape is detailed under
object format and
array format.
["M", "App", [
["D", "Profile", [], [
["P", "name", "Text"],
["P", "age", "Maths.Integer"]
]],
["U", "Status", [], [
["P", "active", "App.Profile"],
["P", "pending", "Text"]
]],
["N", "Greet", [], [
["name", "Text"]
], [
["js", "return 'Hi ' + name;"],
["dart", "return 'Hi ' + name;"]
], "Text"],
["F", "Welcome", [], [
["profile", "BINDING", "App.Profile"],
["H", "row", "Text", [ ["line", "Text"] ]]
], [
["$", "count", "Maths.Integer", 0],
["$", "saved", "Network.Web.Response", null, "LOCKED"],
["S", "submit", "App.Profile", [
["=", "response", "Network.Web.Response",
["Network.Web.Client.Post", [], ["profile"]]],
[">", "SET", [], ["saved", "response"]]
]],
["=", "label", "Text", ["Maths.Integer.ToString", [], ["count"]]],
["=", "", "Text", "label"]
], "Text"]
]]
The two-way HOLE input row uses an
["H", name, ret, [inputs]] entry — a parameter that is itself a body; the trailing
= label return is the body's final ["=", "", Type, expr] with an empty
name.
Namespacing
JSON is the canonical store every other target renders from, so it does no namespacing work at all: it keeps each name exactly as written. A full dotted name is held as one literal string, and splitting the namespace path from the final member is left entirely to each language plugin — see naming considerations.
Functions
A call is stored as its command string with the dotted name intact — "Network.Web.Client.Post", "Maths.Integer.ToString" — and the formatter pretty-prints it verbatim, never rewriting the name. That is the form every compiled target reads and then nests or joins its own way.
Data types
A value type is stored as its canonical token too — "Maths.Integer", "App.Profile", "Text" — so the round-trip back into Program is exact. It is each compiled target, not this store, that folds a built-in type to its own native type.