Tagged multi-schema storage with checked access and reassignment.


Variant

Construct with a schema list in tuple form, for example (Int32 Nat8) Variant.

Variant

(alternatives -- variant) Constructs an owning tagged-storage object, selects tag 0, and initializes that alternative according to its lifetime rules.
  • Use a nonempty List or Tuple of alternative-schema objects, such as (Int32 Nat8). Their schemas and views describe the alternatives; their stored prototype values are not copied into the payload.
  • Named Struct fields are also accepted and are indexed by ordinal.
  • The object owns its active alternative. INIT selects tag 0 and initializes that alternative; normal destruction runs the destruction operation for the alternative selected by its valid tag.

Remarks

  • A managed prototype with an INIT operation initializes according to that operation rather than copying its stored value. An INIT field without a managed lifetime does not change initialization.
  • Alternatives need supported storage size and alignment. Direct Text and Code alternatives are not supported. An accessed alternative must not be Meta.

Fields

Layout

Methods

rawInit

(--) Initializes the alternative selected by the current valid tag without changing that tag.

Remarks

  • Use only when that alternative's storage is not already live; initializing over a live owned value can lose its resources.

rawDestroy

(--) Destroys the alternative selected by the current valid tag without changing that tag.

Remarks

  • Do not destroy the alternative twice; restore a valid initialized state before normal destruction of the Variant.

getTag

(-- tag) Returns the current zero-based alternative ordinal as an Int32 object.
  • The result is an object, not a reference.

setTag

(key --) Changes the active alternative when key differs from the stored tag.
  • key must be an Int32. It accepts a known or unknown key and does not check the range; an unsupported key is stored without initializing an alternative.
  • When key equals the current tag, the existing payload is unchanged. Otherwise the old alternative is destroyed, key is stored, and the new alternative is initialized.

getUnchecked

(key -- ref) Returns a borrowed typed view of storage for key without checking the stored tag.
  • key must be an Int32 ordinal.
  • No tag check is performed; the caller must ensure that the requested alternative is valid to access. An unknown key requires uniform alternative schemas. Unknown-key bounds are the caller's responsibility. Use visit to dispatch typed access to heterogeneous alternatives when the tag is unknown.

get

(key -- ref) Returns the selected storage view after checking that key equals the stored tag.
  • A known mismatch is a compile-time error, Wrong tag in Tagged Union!, in either DEBUG mode.
  • An unknown mismatch reports Wrong tag in Tagged Union! and exits with status 2 when DEBUG is enabled. With -ndebug, the runtime tag check is omitted.
  • The caller must still ensure that the requested alternative is valid to access.
  • The same Int32 ordinal and knownness requirements as getUnchecked apply.

assign

(value key --) Selects key and assigns value to that alternative.
  • value must have the selected alternative's schema. Assignment requires the relevant copy/move support and follows the input view's rules; a mutable managed input can be moved from, while an immutable input is copied.
  • A tag change destroys the old alternative before initializing and assigning the new one.

visitInternal

(... branches offset -- ...) Applies visit's dispatch rules starting at the specified known Int32 field offset in branches.
  • offset must identify the start of the intended remaining key/callable sequence, its final fallback, or the end of the collection. branches 0 visitInternal is equivalent to branches visit.

visit

(... branches -- ...) Dispatches the branch selected by the active tag.
  • branches is one Struct containing alternating Int32 keys and call-supported branch objects, optionally followed by one fallback. Keys used to access heterogeneous alternatives must be known.
  • The first matching key wins. Its branch receives the payload view that get would return for its key on top of the caller's remaining stack. The fallback receives no payload.
  • If no key matches and no fallback exists, nothing is called; an empty collection is a no-op.
  • Branch calls may consume the carried stack and return additional objects. A Block branch has a call boundary.
  • When match comparisons decide dispatch during compilation, only the selected path is processed. An unknown tag or branch key requires every possible branch and fallback/no-match path to compile and produce compatible output counts and schemas, including reference schemas.
  • A fallback may be needed to produce outputs even when the listed keys cover the intended runtime tag range; the no-match path is not inferred as impossible.

equal

(other -- cond) Compares variants with matching alternative-list schemas and active payloads.
  • Prototype values do not matter. A schema mismatch is a compile-time error, Variants' supported types differ.
  • A non-iterable Dict without equal fails with Built-in text, tuple, Iter, or Iterable expected.
  • Different active tags return FALSE. Matching tags compare the active payloads using library = dispatch, including iterable and equal-method adapters; the builtin = covers Cond and numeric Variant payloads; direct Text alternatives are unsupported.
  • Payload equality must be supported for every alternative whose comparison is processed. Unknown tags can require comparison support for alternatives that are not active at run time.

Assign, switch tag, and compare

"String"  use
"Variant" use
"control" use

{} Int32 {} [
  v0: (Int32 Nat8) Variant;
  v1: (Int32 Nat8) Variant;
  ("tag0=" v0.getTag LF) printList
  7n8 1 @v0.assign
  7n8 1 @v1.assign
  ("tag1=" v0.getTag LF
    "value1=" 1 @v0.get LF
    "equal0=" @v1 @v0.equal LF) printList
  123 0 @v1.assign
  ("tag2=" v1.getTag LF
    "value2=" 0 @v1.get LF
    "equal1=" @v1 @v0.equal LF) printList
  0
] "main" exportFunction

Expected Output

tag0=0
tag1=1
value1=7
equal0=TRUE
tag2=0
value2=123
equal1=FALSE

visit branch dispatch

"String"  use
"Variant" use
"control" use

{} Int32 {} [
  v: (Int32 Nat8) Variant;
  7n8 1 @v.assign
  (0 [x:; ("int=" x LF) printList]
    1 [x:; ("nat=" x LF) printList]
    [("default" LF) printList]) @v.visit
  0
] "main" exportFunction

Expected Output

nat=7

Lifetime and whole-object transfer


Access and reference stability


Module helper

getHeapUsedSize

(variant -- size) Attempts to report the active payload's heap usage as Natx.
  • When usable, the result accounts for the active alternative only.

Known issue: an active scalar or String payload fails compilation with The only predicate named «getHeapUsedSize» did not match. Importing memory does not repair the Variant overload. This helper requires a visible getHeapUsedSize overload for every alternative whose branch is processed; an unknown tag can require all alternatives; do not rely on this entry for heap accounting of scalar or String values.

See also