Wit

Data model

The value system that data-defs, records, collections, captures, and load all share: six value kinds, their JSON mapping, access paths, conditions, and text coercion. Source: packages/parser/src/ast.ts.

The six DataValue kinds

DataValue kinds
KindLiteral formStandalone render
stringValueprose or a quoted stringescaped text
numberValue42 or 3.14the number as text
booleanValuetrue or falsetrue or false as text
nullValueempty in a table cell
recorda brace mapa wit-record table
collectiona bracket lista wit-collection list
#title: Field notes          ~ stringValue
#count: 42                    ~ numberValue
#draft: true                  ~ booleanValue
#note: null                   ~ nullValue
#site: { name - Docs, year - 2026 }   ~ record
#tags: [ ref, spec, wit ]     ~ collection

Records carry an ordered fields list of key/value pairs; collections carry an ordered items list. Data-def records need the hyphen delimiter; the colon form is call-site only.

Access paths

A dotted lookup selects a field. Access is fuzzy: camelCase, snake_case, and spaced keys all match.

#person: { firstName - Ada, role - Author }

Name is @person.first_name → Name is Ada

Iteration

(each @collection as item) … (end) binds each element to item. Inside the loop, reference it with @item (a bare reference), or @item.field for a record field — not ::item:: (that is capture interpolation, a different mechanism).

source
#hands: [ { name - Marlow }, { name - Singleton } ]

@ul
(each @hands as item) @li @item.name li@ (end)
ul@
result

  • Marlow
  • Singleton

Iterating a non-collection raises E_NOT_ITERABLE. Fixture: 13-iteration/*.

Conditions

The test in an (if …) is either existence or a comparison.

Condition forms
FormTrue when
if paththe path resolves to a value
if path is Xthe value equals X — identity
if path equals Xthe value equals X — comparison
(if @author) By @author.name (end)
(if @status is shipped) Live (else) Draft (end)
Fixture:

12-conditionals/*.

JSON to Wit mapping

The only shape that crosses the load seam.

JSON to Wit
JSONWit value
objectrecord
arraycollection
stringstringValue
numbernumberValue
booleanbooleanValue
null or undefinednullValue

Text coercion

When a value is placed in text (a table cell or inline), it is coerced: number and boolean → their string form; nullValue → an empty string.

typedValue

A capture param carries a shape-probed typedValue when it looks like a collection, record, or scalar literal; pure prose keeps only its string value. This is what lets |rows @ref| and typed captures work — the table renderer reads typedValue.

See also

Syntax

· Tables · Config · Limitations.