Compatibility

Legacy Syntax Migration

A focused guide for adapting genuinely old source forms to current canonical Topaz.

Legacy material is provenance, not a compatibility promise. Preserve intended behavior while rewriting source into the current canonical grammar, then let the current checker expose every unresolved boundary. Compatible product-version changes do not need a migration guide.

1. Inventory before rewriting

Record entry files, module roots, inputs, outputs, faults, host effects, and golden transcripts. Separate actual Topaz from Rust-, JavaScript-, or framework-shaped examples. Do not infer semantics from an old page merely because a form looks familiar; consult the current SPEC and canonical examples.

2. Normalize the recurring forms

  • Rewrite mut let as let mut, [T] as Array<T>, and old function-type spellings as (T) -> U.
  • Use ..rest in list patterns, ...args: T for variadic parameters, lambdas for anonymous functions, and self only in the admitted receiver declaration.
  • Replace string indexing/.length with scalar APIs; use typed registry templates and {expr} interpolation.
  • Keep recoverable failure in Result, absence in Option/nullable shapes, runtime faults loud, and cleanup in defer/admitted using.
  • Rewrite modules to the current import and export forms. Foreign tokens remain at a labeled build or conversion boundary.

3. Keep historical code historical

This is a legacy spelling and must stay in a text fence, never a canonical Topaz fence:

mut let names: [string] = ["Ada"]
let first = names[0]

The current shape makes mutation, collection type, and bounds behavior explicit:

TOPAZ
let mut names: Array<string> = ["Ada"]
let first: Option<string> = names.get(0)
print("{first}")

4. Rebuild the proof, not just the parse

Run topaz check, then execute reference fixtures with run. Build only the targets you intend to ship and compare declared observables. Recheck module initialization, iteration order, scalar string positions, numeric faults, resource cleanup, and host-profile boundaries. Parsing alone does not prove migrated behavior.

5. Know the automation boundary

The CLI migration command covers only explicitly supported package/source transitions; it is not a general semantic translator. Long-form guides may contain framework APIs and foreign grammar that no automatic rewrite can validate. Compare the example in Classic, then adapt it using the current language.

Migration exit gate

A migration is closed when the current checker passes, required outputs are recaptured, admitted backends agree over the declared tests, no Hard Stop remains in canonical fences, current docs links replace legacy authority, and every unsupported behavior has a loud disposition.