Dextrin.Schema.Compiler (Dextrin v0.2.0)

Copy Markdown View Source

Compiles a parsed .dxns document (an ordinary decoded DXN value — a .dxns file is valid .dxn, no new grammar; what makes it a schema document is purely the shape of the value it parses to: a map from name to type expression) into Dextrin.Schema.Compiled entries.

A struct schema is written %schema(N){field: type, ...} (DXN.md §4.4): the body lists the fields directly, and the order they are written in is the positional order .dxnb encodes them in. The header holds only the version; without one the schema is version 1. Each .dxns document describes one version of each schema it holds, and the registry keeps every version it is given (Dextrin.Registry).

%schema{}/%field{} are recognized here directly, as Dextrin.Struct{name: "schema" | "field"} opaque shapes straight out of Dextrin.decode/1 — they're never looked up in a registry, the same way built-in tags are recognized by name in Dextrin.Text.Actions rather than registered. This sidesteps an obvious bootstrapping question (doesn't parsing a .dxns file need a schema for its own schema/field structs?) the same way JSON Schema's own vocabulary is fixed tooling knowledge rather than itself validated against a schema.

An entry whose value isn't a %schema{} is a named type instead: a reusable name for some combination of the fixed type_expr vocabulary, e.g. PositiveInt: {:refine :integer {min: 1}} — the same move Clojure's Malli makes with [:map [:x :int]]-style plain data instead of a bespoke schema DSL. Purely data — no Elixir code, no registry callback — so any conformant reader in any language can resolve it the same way it already resolves refine/list-of/etc.

Summary

Functions

Compiles every entry of a decoded .dxns document into base_registry — a struct schema for each %schema(N){} entry, a named type_expr for every other entry.

Functions

compile(schema_doc, base_registry)

@spec compile(term(), Dextrin.Registry.t()) ::
  {:ok, Dextrin.Registry.t()} | {:error, Dextrin.Error.t()}

Compiles every entry of a decoded .dxns document into base_registry — a struct schema for each %schema(N){} entry, a named type_expr for every other entry.

A schema version already in base_registry is an error (schema/duplicate-version); any other problem with the document is a schema/compile error. Replacing a loaded version on purpose is Dextrin.Registry.replace_struct_schema/3.

Named types defined in this document may reference any type already known to base_registry (from an earlier compile/3 call), but not one declared alongside them in the same document — .dxns's own map type has no ordering guarantee to resolve forward references against, and no real usage yet justifies the dependency-resolution machinery a same-document case would need. A schema's fields, compiled afterwards, can freely use any named type from either source.