liveBook · Manning

Reference object

As explained in Building User-Friendly DSLs

A structured object whose reference field identifies an AST object without making that target part of the source object's containment hierarchy.

A reference object encodes a reference relation inside an AST setting. Its shape is `{ ref: <target AST object> }`: the `ref` field points to the target, while the target remains outside the source object's containment hierarchy. Unlike a contained AST object, following this link does not make the target a child to traverse into. section 3.4 section 3.3.1

In JavaScript, an encoded AST object has `concept` and `settings` fields, whereas a reference object has a `ref` field. A reliable recognizer first excludes null and arrays, then checks for `ref`; a complete reference relation additionally requires `ref` to be an AST object. section 3.2.2

Use a reference object when a setting must name another AST object without containing it:

  • Read the target through `settings["attribute"].ref` after confirming that the setting exists. section 3.4 section 6.1.2
  • Create the wrapper when a user chooses a target, assigning `{ ref: selectedAstObject }` rather than assigning the target directly. section 6.1.2
  • During depth-first tree traversal, inspect `value.ref` but do not traverse into it; traverse only containment relations and array items. section 3.3.1
  • For JSON persistence, replace the in-memory target with its ID as `{ refId: target.id }`, avoiding object-reference cycles. section 7.2

Referencing a rental attribute

An `Attribute Reference` used as a data attribute's initial value stores its chosen target in the `attribute` setting. The projection reads the referenced attribute's name through `settings["attribute"].ref.settings["name"]`. Before a selection exists, it guards against an undefined setting; once selected, it creates `{ ref: matchingAttribute }`, so later changes to that target remain visible through the reference. section 6.1.2

Listing 7.15 Transforming an AST into a cycle-free “almost-AST”
const serialize = (value) => {
    if (isAstObject(value)) {
        const serializedAstObject = {
            id: value.id,
            concept: value.concept,
            settings: {}
        }
        for (const propertyName in value.settings) {
            serializedAstObject.settings[propertyName] =
                 serialize(value.settings[propertyName])
        }
        return serializedAstObject
    }
    if (isAstReferenceObject(value)) {
        return ({  #1
            refId: isAstObject(value.ref)    #2
                     ? value.ref.id
                     : undefined
        })
    }
    if (Array.isArray(value)) {
        return value.map(serialize)
    }
    return value
}
module.exports.serialize = serialize

This serializer distinguishes AST objects, reference objects, arrays, and simple values, converting each reference target into a `refId` while recursively copying only contained structure. section 7.2

References complicate persistence because JavaScript object references are not directly representable in JSON and can create cycles. Give AST objects IDs, serialize each reference as `refId`, and later use that identifier to reconnect the reference to its target when reconstructing the AST. section 7.2

How Building User-Friendly DSLs covers it

How deep it goes
Defines the object shape, recognition helpers, traversal treatment, editing behavior, and ID-based serialization.
Examples
Uses an Attribute Reference targeting a rental attribute and a serializer that converts `ref` into `refId`.
What it assumes
Builds from JavaScript objects, arrays, `typeof`, and property access while defining AST-specific reference structure.
What you can do after
Apply it via JavaScript helpers to create, recognize, follow, traverse, and serialize AST references.
How it connects
Connects reference relations with AST objects, containment relations, depth-first tree traversal, JSON serialization, and IDs.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Building User-Friendly DSLs. The section links point to the parts of the book it draws on.