[comp.lang.ada] Passing around unconstrained variant records

seaberg@flapjack.cs.washington.edu (Erik Seaberg) (11/12/90)

A Data Structures class project is to write one of those
parenthesized-expression evaluators, using a binary threaded tree to
represent a general tree.  (There are n-ary operators, like min and
max, as well as an assign operator.)  I use a tokenizer to convert the
input string into tokens, and wrote a generic tree package to make a
tree out of the expression's tokens.  To be elegant, I tried to use a
variant record

        subtype VARIABLE_NAME is CHARACTER range 'A'..'Z';      
        type TOKEN_CLASS is (NONE, NUMBER, VARIABLE, PLUS, ASSIGN, -- etc. )

        type TOKEN (CLASS : TOKEN_CLASS := NONE) is record
            case CLASS is
                when NUMBER   : VALUE => INTEGER;
                when VARIABLE : NAME  => VARIABLE_NAME;
                when others   : null;
            end case;
        end record;

so that only number tokens would have an integer value, and only
variable tokens would specify a variable.  I used class none as a
default so that I could declare objects of type token without having
to know the subtype in advance (since the tokenizer could return
tokens of any type).

Anyway, I instantiate the generic tree package for a tree of tokens,
try to make a new tree out of the variable token 'A', and wind up with
a constraint_error when trying to evaluate "A := 1".  I go into gory
detail with the debugger, see the variable token 'A' passed into
Make_Root (of a new tree), look at the resulting tree, and the
debugger says the value of its root is

        class variable
        name NIL
        ...             -- links to rest of tree

which explains the constraint_error -- the class of the token made it
into the tree, but the name is never stored and can't be dereferenced
from my array of variables.  Likewise, all number tokens wind up with
a value field of 0 stored in the tree.

What gives?  Is the tree package assuming that every token has the
default class (which has no other fields)?  A token is passed to
Make_Root as an in parameter of the private (not limited) type used to
instantiate the package.  If a variant record has a default subtype,
and any objects of the type (declared unconstrained) have enough space
allocated to store the largest subtype of the variant record type, why
isn't the entire object (largest possible subtype) passed as a
parameter of that unconstrained type?

I broke down and gave each token all of those fields (class is just
another field, the record is no longer variant -- after all, this has
to *work*), but I'd like to know why the more sophisticated way didn't
fly.
------------------------------------------------------------------------
"In a high dimension of which we know nothing, the great Khan bellowed
 with rage, but Mr. Prosser only stood there and wimpered....
 indecipherable strangers handing out inexplicable humiliation and an
 army of horsemen laughing at him in his head -- what a day."