Interop & Migration

Migration from Pre-v5

A boundary-first migration guide from private pre-v5 and legacy site forms to current canonical Topaz.

Pre-v5 material is provenance, not a compatibility promise. v5.0 and v5.1 were private design generations; the synchronized public language/toolchain line was chosen at v5.2. Migrate by preserving intended behavior while rewriting source into the current canonical grammar, then let the current checker expose every unresolved boundary.

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 --language-version 5.6, 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 named historical package/source transitions; it is not a general pre-v5 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.

Continue reading