The syntax of equates is:
<equate> -> <idn> "=" <expr> | <idn> "=" <type_designator>For the first form, the expr must be a constant expression (7.15) or a compile-time error will occur.
An identifier equated to an expression may be used as an expression (7); the value of such an expression is the constant to which the identifier is equated. An identifier equated to a type designator is itself a type designator and denotes the same type as the type designator it is equated to. An equated identifier may not be used on the left-hand side of an assignment (5).
Some examples of legal equates:
as = array[string] % a type equate pi = 3.1416 % a constant expression equate
An equated identifier is defined in the smallest scoping unit surrounding its equate; here we mean the entire scoping unit, not just the portion after the equate. Equates that occur within the body of a statement must appear prior to any statements in that body. Equates not in such a scope (e.g., at the top level of a module) can appear anywhere within the scope.
All equates in a scope are processed by the compiler as a unit, and forward references are allowed. The compiler reports an error if a cyclic dependency is detected without any intervening user-defined type. For example, the following set of equates is illegal:
tree = maybe[tree_node] tree_node = record[left: tree, right: tree, val: int]However, within a class implementing a "tree" type we might have
tree = class ... tree_node = record[left: tree, right: tree, val: int] t: tree_node ... end treeThese equates are legal because a user-defined type, "tree", breaks the cycle.