Tagged multi-schema storage with checked access and reassignment.
Construct with a schema list in tuple form, for example (Int32 Nat8) Variant.
VARIANT: variant marker field.typeList: list of supported schemas.maxSize: greatest storage size among the supported schemas.maxAlignment: greatest alignment among the supported schemas.typeTag: zero-based key of the currently active schema.memory: aligned storage for the current active value.filler: remaining bytes needed to reach the maximum storage size.rawInit (--): initializes storage for the current tag.rawDestroy (--): destroys storage for the current tag.getTag (-- tag): returns the current active key.setTag (key --): switches the active schema and reinitializes storage when needed.getUnchecked (key -- ref): returns one typed Ref without tag validation.get (key -- ref): returns one typed Ref and asserts that key matches the current tag.assign (value key --): switches the tag if needed and stores one new value.visit (-- result): dispatches through one branch selected by the current tag.equal (other -- isEqual): compares two variants with the same type list."Variant" use
"String" 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
tag0=0
tag1=1
value1=7
equal0=TRUE
tag2=0
value2=123
equal1=FALSE
"Variant" use
"String" 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
nat=7
INIT sets typeTag to 0 and initializes the first supported schema.setTag destroys the previous active value and initializes the new active value when the key changes.assign stores a new value in the selected branch and performs the same tag switch when needed.ASSIGN copies another variant of the same schema list and keeps the copied active branch.DIE destroys only the currently active branch.get is the checked accessor and asserts that the requested key matches typeTag.getUnchecked skips that validation and is only safe when the active key is already known.equal requires the same typeList on both sides.visit consumes alternating tag and callable items and calls only the branch selected by the current tag. When the branch list ends with one unmatched final callable, that callable acts as the default branch and receives no value.get and getUnchecked point into the current active branch storage.setTag, assign, ASSIGN, and DIE may destroy or replace that active branch and invalidate earlier returned references.(variant -- size)Returns heap usage of the currently active value.
typeTag contributes to the result.