Extension-defined literals
GEDCOM is a native Standard (Lite) parser, inherited by Pro:
Extension-defined literals
Native formats in 0.75.0
GEDCOM is a native Standard (Lite) parser, inherited by Pro:
family = gedcom"""0 HEAD
1 GEDC
2 VERS 7.0
0 @I1@ INDI
1 NAME Ada /Example/
0 TRLR
"""
Do not import pkg:grid/gedcom: native tags are selected by the engine assembly
and require no extension installation or WASM engine. The implementation is in
grid-genealogy-core; see the
native example and
format catalog and edition contracts.
PARSE_GEDCOM(text) invokes the same native reader. Keep GEDCOM level numbers
at the start of each line. Native constants run without the parser service;
recompilation needs the selected native binding. Native provenance acceptance
is tracked separately from the extension contract below.
Package-defined tags
General-purpose extensions remain separate from the native format program.
For an installed package that declares the non-built-in tag custom:
USE "pkg:example/records@1.0.0" EXPOSING (custom)
records = custom"payload"
custom"...", custom"""...""", and <custom>...</custom> select the same
parser. Ordinary quotes decode Grid escapes. Triple quotes and angle blocks
retain their payload verbatim. Angle blocks end at the first matching closing
tag, ignoring case. Custom literals have no implicit interpolation. The explicit
template tag parameter selects a separate template compiler when the package
supplies one; see Reactive templates.
USE "pkg:example/records@1.0.0" AS records exposes records.custom.
Installation alone does not activate a package tag. Conflicting imports and
built-in/native tag replacements are refused. Compilation never downloads a
missing package. Existing built-in literal semantics remain unchanged.
The builtin executable lua tag is provided by the runtime and needs no
package import. It returns a checked scalar through extension execution;
Executable language tags describes that
separate invocation contract. Qualified imported tags retain this guide's
explicit resolution rules.
Package literal compilation and distribution
Parsing, formatting, and syntax-tree inspection retain opaque literal source; they do not invoke the package. Explicit compilation invokes the installed, verified parser before semantic analysis and lowers the result to native constants. Compilation fails if the package or execution service is unavailable.
A compiled model runs without its literal parser package. Editing and recompiling the literal requires the exact package again. If the model also calls ordinary extension functions, those calls retain their normal runtime dependency. The compiled model carries inert parser and expansion provenance, including the manifest, artifact, source and result digests.
Expansion caches use the verified parser identity and decoded payload. The host currently retains the lazy parser service for one compilation; repeated payloads within that compilation share results. Embedders may retain an injected service across compilations. Results are never reused for a different admitted contract or artifact identity.
Package contract
For reactive templates, add "templateExport": "compile_template" to the
literal declaration. This is a separate scalar export with the same pure,
exact, capability-free, one-string contract as the constant parser. Its result
signature is result_type(grid_extension_core::templates::plan_type()).
Declare format-specific delimiter defaults alongside the export:
{"name":"card","parserExport":"parse","templateExport":"compile_template",
"templateDelimiters":{"open":"[[","close":"]]"}}
With this declaration, <card template>Hello [[Name]]</card> uses the package's
defaults. The start and end tag attributes override either default for one
literal. Without templateDelimiters, the defaults are {{ and }}. Both
strings must contain 1–64 UTF-8 bytes and no control characters. Declaring
defaults requires templateExport. This metadata is part of the manifest's
identity and is available before parsing expression holes; reading it does not
execute the package. Syntax inspection of imported implicit defaults needs the
package declaration. Compilation refuses a syntax tree parsed using different
defaults; reparse with the declaration or spell both attributes explicitly.
The input string is JSON: {"version":1,"chunks":["Hello ","!"]}. Slot zero
lies between chunks zero and one. Expressions and delimiters are not sent to
the package. For each request, return one TemplatePlan inside the normal
values result envelope:
{
"version": 1,
"nodes": [
{"kind":"constant","text":"\"Hello \"","slot":-1,"children":[],"keys":[]},
{"kind":"slot","text":"","slot":0,"children":[],"keys":[]},
{"kind":"constant","text":"\"!\"","slot":-1,"children":[],"keys":[]},
{"kind":"text","text":"","slot":-1,"children":[0,1,2],"keys":[]}
],
"root": 3
}
constant holds a JSON scalar; slot references a numbered expression;
text concatenates children; array constructs a sequence; object pairs
static keys with children; tag applies ordinary scalar TYPE_TAG semantics;
document materializes a JSON-compatible native value with the document tag in
text, including custom format tags. Both have one child. Document construction
preserves arrays and records, propagates errors, and rejects values requiring
an explicit projection, such as native trees. Every child precedes its parent, every non-root node has exactly
one parent, and the root is the last node. Every input slot must appear. Repeat
a slot by emitting another slot node, not by sharing an intermediate subtree.
Unused fields must be empty, with slot set to -1 outside slot nodes.
Plans allow at most 4,096 slots, 128 construction levels, one million nodes, and 64 MiB of plan data. The existing package execution, source and result budgets apply as well. Unknown operations, cycles, detached nodes, missing slots, duplicate object keys and excess resources fail compilation. No node may emit Grid source or request an arbitrary runtime function. Template diagnostics are checked against the encoded request and currently reported at the enclosing template span.
Cache identity includes the admitted template export and encoded static request. Expansion provenance records package, artifact, request, and result digests. Formatting and syntax inspection never call either package export.
Manifest schema 3 adds an optional declaration:
"literals": [{ "name": "custom", "parserExport": "parse" }]
Schema 1 and 2 packages continue to work. Omitted/empty literal declarations do
not change their manifest digest. Literal names are identifiers; qualification
comes from USE, not from the package's public tag name.
Manifest schema 4 adds optional editor metadata to a literal:
"literals": [{
"name": "custom",
"parserExport": "parse",
"editor": { "languageId": "gedcom", "tokensExport": "tokens" }
}]
languageId names an editor language the payload may be delegated to for
highlighting; an id the editor does not know renders plain. tokensExport
names a pure, exactly deterministic, capability-free export that takes the
decoded payload and returns { version: 1, tokens: [{ start, end, category }] }
with sorted, non-overlapping half-open UTF-8 byte spans and categories from the
language service's semantic-token legend. Editor metadata never changes
parsing, formatting or execution, and an omitted editor object leaves the
manifest digest unchanged. A language server may run the admitted
parserExport and tokensExport only in a trusted workspace, under the
package's existing budgets; analysis in an untrusted workspace runs no guest.
The referenced scalar export must be pure and exactly deterministic, require
no capabilities, and accept one required string. Its result signature uses the
schema constructed by grid_extension_core::literals::result_type(T):
{
version: 1,
values: [parsedValue],
diagnostics: [{ severity, code, message, start, end }]
}
values has exactly one item on success, including success with warnings; it
is empty when an error diagnostic exists. start and end are half-open UTF-8
byte offsets into the decoded payload. They must lie on character boundaries.
The compiler maps them through the enclosing Grid literal's escapes.
T can contain strings, booleans, numbers, integers, blanks through nullable
fields, arrays and closed objects. Handles, Frames, and ambient capabilities
are refused. Existing GRDX array encoding is version 1.2; generated native
bindings support borrowed arrays of objects without introducing a guest ABI.
The existing runtime enforces fuel, timeout, memory and output budgets. Input
is capped at 16 MiB and expansion at one million value nodes, subject to the
stricter existing schema depth and export output limits. A module also caps cumulative expansions at one million nodes and 64 MiB of
encoded native values. The compiler rechecks
results from injected services. Execution errors fail compilation rather than
leaving executable parser calls in the model. Embedders can inject
CancellableLiteralCompiler; core-WASM execution observes cancellation on the
existing engine epoch, and cancellation becomes a compilation diagnostic.
Native GEDCOM result
The native reader imports UTF-8 GEDCOM 5.5.1 and 7.0. family contains people,
families, names, events, sources, citations, notes, links, nodes,
edges, and the complete ordered records index. Each raw record retains its
ID, parent, tag, value, original line and source offsets. Unknown/custom tags
remain in that index even when they have no specialized projection.
Dates such as ABT 1900 remain expressions, not fabricated exact dates.
Relationship edges retain the asserted GEDCOM kind and pedigree qualifier;
families remain graph entities. No biological parentage is inferred. Isolated
people remain in nodes. Dangling references produce warnings and retained
links but no unusable graph edge. The warning highlights the original pointer,
including in quoted literals. Up to 64 reference warnings appear individually.
Above that limit the first 63 remain, followed by a warning with the number
omitted. All authored links stay available for inspection.
Revision 2 accepts LF, CRLF, and CR record endings and keeps original byte
offsets. In GEDCOM 7, @VOID@ explicitly records an absent target and produces
no dangling-reference warning. A citation’s texts array retains each
DATA.TEXT passage, continuations, media type and language in order.
text exposes the first passage. Header SOUR identifies the producing
software and stays in the raw records. GEDCOM 7 specification
The scope excludes GEDCOM export, legacy encoding conversion, GEDZIP, media retrieval and pedigree rendering. This is a record importer, not a claim of complete GEDCOM validation or byte-identical export.
Construct a native graph
The native reader emits one node per person and family, even when no edge references
that entity. Every resolved relationship assertion contributes an edge. Family
nodes retain multiple unions, and the pedigree property preserves explicit
child relationship qualifiers. The status, adoption, and eventId fields
retain the asserted status, adopting parent designation, and owning event record.
Revision 3 projects family pointers under an individual’s birth (BIRT),
christening (CHR), adoption (ADOP) and child-sealing ordinance (SLGC).
For these event-scoped links, eventId identifies the row in events. The editor resolves
these pointers within the same literal. Oppositely directed assertions are separate
records; they do not imply a biological relationship.
GRAPH accepts a closed literal object with nodes and edges arrays of
records. Node records use id; edge records use id, from, and to.
Other scalar fields become properties. The constructor builds a directed graph.
An empty edge array is valid, so a document containing only isolated people
still produces a graph.
graph ancestry = GRAPH(gedcom"""0 HEAD
1 GEDC
2 VERS 7.0
0 @I1@ INDI
1 NAME Isolated /Example/
0 TRLR
""")
node_count = ancestry.NODE_COUNT()
Pass the literal directly to this constructor. Named or computed record objects
are not constant-folded into a graph: that would discard their live dependency.
The existing Frame/range constructor remains the route for changing sources.
For record queries, bind the literal separately and use ordinary accessors,
for example family.people[1].name. Repeated native payloads can reuse the frozen binding's cache when the parser contract and limits match.
Native literal compilation selects the linked reader on first use. A source
containing only native literals does not initialize the package compiler.
Rust embedders can return a request-owned cancellation flag from
ModuleResolver::native_literal_cancellation. A cancelled native expansion
reports GRID_PARSER_CANCELLED, including on a cached read. Separate compile
requests can share the same cache and use different flags. Parser warnings
keep their payload-relative byte spans so they map to each occurrence in
source. A malformed parser response is rejected before cache insertion.
See examples/native-formats/gedcom-family.grid for the complete model.
The older examples/extensions/gedcom directory is a historical WASM prototype.