IndexedNames (e.g. `a(0)` or `a(2, 3)`) are necessary to access elements
of nested or multidimensional arrays (which have too many dimensions for
vhpiLogicVecVal) or to set individual elements of single-dimensional
arrays. Add basic support for these objects.
Although objDecls are names too, they also include the decl properties
which we don't want. Therefore, we use a separate hierarchy for
exprs/names. For future work, it might be nice to use the object
framework (tree_t, type_t, etc) for VHPI as well.
IndexedNames are created lazily. This is useful for nested arrays. For
example, a signal like
type a is array(0 to 9) of std_logic_vector(31 downto 0);
signal b: a;
might only be accessed like `b(0)` and never like `b(2)(3)`.
The encoding of prefixedName varies slightly from the UML. To reuse the
above example, while the UML says that the prefix of `b(0)` is `b`,
we set prefix as NULL in this situation, using simpleName instead. This
makes it easier to walk nested prefixes, since we don't have to compare
prefix to simpleName.
To populate IndexedNames, we must iterate over all constraints on the
array, and create `c_indexedName`s for each. One option here would be to
pass BaseIndex to init_indexedName. However, this would require decoding
the BaseIndex into indices for each constraint. Indead, I chose to pass
the indices directly, and create BaseIndex from them. I think this is
easier, because it doesn't involve any division.