STRUCT, UNION & Conformity Clauses
Pitfall: a structure display needs at least two fields, so a one-field structure cannot be built with a display (assign the field instead).
30.1 Structures
Pitfall: a structure display needs at least two fields, so a one-field structure cannot be built with a display (assign the field instead).
BEGIN
MODE POINT = STRUCT (REAL x, y);
MODE PERSON = STRUCT (STRING name, INT age, POINT home);
POINT p := (1.5, -2.0); # structure display #
x OF p := 3.0; # field selection with OF #
PERSON bob := ("Bob", 42, (0.0, 0.0));
age OF bob +:= 1;
print((name OF bob, " is ", whole(age OF bob, 0), newline));
print(("home x = ", fixed(x OF home OF bob, 0, 1), newline))
END30.2 Rows of structures and multiple selection
BEGIN
MODE POINT = STRUCT (REAL x, y);
[] POINT pts = ((0, 0), (3, 4), (6, 8));
[] REAL xs = x OF pts; # selecting from a row gives a row: (0, 3, 6) #
print((xs, newline));
print((y OF pts[2], newline)) # y of element 2 #
END30.3 Unions
A UNION value carries both a value and the mode it currently holds:
You cannot use a union value directly in arithmetic; you must discriminate it with a conformity clause.
MODE NUMBER = UNION (INT, REAL);
NUMBER n := 42; # uniting #
n := 3.14; # now holds a REAL #30.4 Conformity clauses
Each (MODE identifier): branch is taken if the union currently holds that mode; the identifier is bound to the value.
An OUT part handles unlisted modes; the brief form is ( v | (INT i): ... | ... ).
Conformity can test without binding: (MODE): with no identifier, e.g. CASE v IN (INT): print("int") OUT print("other") ESAC.
BEGIN
MODE NUMBER = UNION (INT, REAL, STRING);
PROC describe = (NUMBER v) VOID:
CASE v IN
(INT i): print(("integer ", whole(i, 0), newline)),
(REAL r): print(("real ", fixed(r, 0, 3), newline)),
(STRING s): print(("string """, s, """", newline))
ESAC;
describe(7);
describe(2.5);
describe("seven")
END30.5 Example: shapes
CIRCLE (0, 0, 1) is a cast that makes the display a CIRCLE; the row display then unites each element into SHAPE. Note r OF c 2 means (r OF c) 2: selection binds tighter than any operator.
BEGIN
MODE CIRCLE = STRUCT (REAL cx, cy, r);
MODE RECT = STRUCT (REAL w, h);
MODE SHAPE = UNION (CIRCLE, RECT);
PROC area = (SHAPE s) REAL:
CASE s IN
(CIRCLE c): pi * r OF c ** 2,
(RECT q): w OF q * h OF q
ESAC;
[] SHAPE shapes = (CIRCLE (0, 0, 1), RECT (2, 3), CIRCLE (1, 1, 2));
REAL total := 0;
FOR i FROM LWB shapes TO UPB shapes DO total +:= area(shapes[i]) OD;
print(("total area = ", fixed(total, 0, 4), newline))
END