obj IntOrBoolOrString = intVal:integer or boolVal:boolean or stringVal:string; var ibs:IntOrBoolOrString; var i:integer; var b:boolean; var s:string; op main() = ( (* * Use ibs as an integer; here the interpreter keeps track of the fact that * the intVal component is currently active. *) set ibs.intVal = 10; -- Treat ibs as an int; in contrast to C, the -- interpreter internally maintains the tag, -- which is set to indicate that the intVal -- component is currently active set i = ibs.intVal; -- Assign 10 to i, as expected (* * Erroneously use ibs as a string, with int as the current component. *) set s = ibs.stringVal; -- Assigns nil to s, since the interpreter -- knows that ibs is currently an integer (* * Use ibs as a boolean, again with interpreter-maintained change of tag. *) set ibs.boolVal = true; set b = ibs.boolVal; (* * Use ibs as a string, again with interpreter-maintained change of tag. *) set ibs.stringVal = "xyz"; set s = ibs.stringVal; (* * Here is the normal way to safely use a union variable. It involves * checking the current value of the tag, and accessing the component that * the tag-check says is currently active. This is the place in FMSL where * the '?.' operator gets used. It returns true for the currently used * field, false for all of the other fields. *) if ibs?.intVal then ( set i = ibs.intVal; -- Safely fetch the integer value -- do whatever with i; ); if ibs?.boolVal then ( set b = ibs.boolVal; -- Safely fetch the boolean value -- do whatever with b ); if ibs?.stringVal then ( set s = ibs.stringVal; -- Safely fetch the string value -- do whatever with s; ); (* * Assign an integer to the whole union variable. This is called * "auto-injection", and is not supported by C. DO NOT IMPLEMENT IT. *) set ibs = 10; );