v0.4.0
Breaking Changes
-
Expressiontype restructured. The publicExpressiontype is now a
struct with two fields —kind: ExprKindandannotations: AnnotationSet
— rather than a flat enum. All match arms that previously destructured
Expression::Variant { ... }must be updated toExprKind::Variant { ... }
and applied toexpr.kind. Convenience constructors onExpression
(Expression::integer,Expression::variable, etc.) remain available. -
Serde format changed to adjacently-tagged. The JSON wire format now uses
{ "kind": "VariantName", "value": <payload> }throughout. The previous
externally-tagged format ({ "VariantName": <payload> }) and bare-string
unit variants (e.g."Nabla") are no longer emitted or accepted. Any stored
JSON or hardcoded deserializers must be updated. Seedocs/WIRE-FORMAT.md
and the migration guide below.
Added
-
AnnotationSetsubstrate. EachExpressionnode now carries an
AnnotationSet— an ordered string-to-string metadata map. The field is
omitted from JSON when empty and defaults to empty on deserialization, so
existing documents round-trip without modification. The substrate is passed
through unchanged by thales v0.9.0; semantic consumption is planned for
thales v0.10.0. -
Golden fixtures and variant stability tests.
tests/fixtures/serde/
contains one canonical JSON file perExprKindvariant (53 total) plus a
variant_manifest.txt. CI verifies that round-tripping each fixture produces
bit-identical output, locking the wire format against accidental drift. -
docs/WIRE-FORMAT.md. Normative wire-format reference covering all 53
variants, theAnnotationSetfield, all nested enum kind values, and the
stability guarantee.
Migration Guide
Rust match arms. Replace Expression::Add { left, right } with:
// before
match expr {
Expression::Binary { op, left, right } => { ... }
Expression::Nabla => { ... }
}
// after
match expr.kind {
ExprKind::Binary { op, left, right } => { ... }
ExprKind::Nabla => { ... }
}JSON format. Every node that previously serialized as
{ "VariantName": payload } now serializes as
{ "kind": "VariantName", "value": payload }. Unit variants that previously
serialized as the bare string "Nabla" now serialize as { "kind": "Nabla" }.
// before (externally tagged)
{ "Binary": { "op": "Add", "left": { "Integer": 1 }, "right": { "Integer": 2 } } }
// after (adjacently tagged)
{
"kind": "Binary",
"value": {
"op": { "kind": "Add" },
"left": { "kind": "Integer", "value": 1 },
"right": { "kind": "Integer", "value": 2 }
}
}Swift consumers that decoded the JSON via hand-written Decodable structs must
update their CodingKeys and decoding logic to match the new shape. See
docs/WIRE-FORMAT.md for the new adjacently-tagged layout.