Modula-3: Typecase statements

# Typecase

A `TYPECASE` statement has the form:

        TYPECASE Expr OF
          T_1 (v_1) => S_1
        | ...
        | T_n (v_n) => S_n
        ELSE S_0
        END

where `Expr` is an expression whose type is a reference type, the `S`'s are statements, the `T`'s are reference types, and the `v`'s are identifiers. It is a static error if `Expr` has type `ADDRESS` or if any `T` is not a subtype of the type of `Expr`. The "`ELSE S_0`" and each "`(v)`" are optional.

The statement evaluates `Expr`. If the resulting reference value is a member of any listed type `T_i`, then `S_i` is executed, for the minimum such i. (Thus a `NULL` case is useful only if it comes first.) If the value is a member of no listed type and "`ELSE S_0`" is present, then it is executed. If the value is a member of no listed type and "`ELSE S_0`" is absent, a checked runtime error occurs.

Each `(v_i)` declares a variable whose type is `T_i` and whose scope is `S_i`. If `v_i` is present, it is initialized to the value of `Expr` before `S_i` is executed.

If `(v_i)` is absent, then `T_i` can be a list of type expressions separated by commas, as shorthand for a list in which the rest of the branch is repeated for each type expression. That is:

        T_1, ..., T_n => S

is shorthand for:

        T_1 => S | ... | T_n => S

For example:

        PROCEDURE ToText(r: REFANY): TEXT =
          (* Assume r = NIL or r^ is a BOOLEAN or INTEGER. *)
          BEGIN
            TYPECASE r OF
              NULL => RETURN "NIL"
            | REF BOOLEAN (rb) => RETURN Fmt.Bool(rb^)
            | REF INTEGER (ri) => RETURN Fmt.Int(ri^)
            END
          END ToText;

    Last modified on Wed Apr  3 09:38:52 PST 1996 by heydon
         modified on Mon Apr 18 14:08:25 PDT 1994 by kalsow