comp.lang.ada
 help / color / mirror / Atom feed
* Tagged type feature, or GNAT bug?
@ 1994-09-27 16:36 Michael Feldman
  1994-09-27 23:22 ` Bob Duff
  1994-09-28 11:14 ` Robert Dewar
  0 siblings, 2 replies; 3+ messages in thread
From: Michael Feldman @ 1994-09-27 16:36 UTC (permalink / raw)


-- I'm exploring tagged types as an alternative to variant records.
-- Seemingly, one should be permitted to use a classwide type as
-- one would an unconstrained variant record. But see below:

PROCEDURE TestTags IS

-- First a classical Ada 83 variant record
-- Note that the record is unconstrained

  TYPE Kinds IS (A, B, C);

  TYPE VariantRec (Discrim: Kinds := A) IS RECORD
    FixedPart: String (1..4);
    CASE Discrim IS
      WHEN A =>
        F1: Integer;
      WHEN B =>
        F2: Float;
      WHEN C =>
        F3: Boolean;
    END CASE;
  END RECORD;

-- Now a tagged type equivalent

  TYPE TaggedRec IS TAGGED RECORD
    FixedPart: String(1..4);
  END RECORD;

  TYPE A_TaggedRec IS NEW TaggedRec WITH RECORD
    F1: Integer;
  END RECORD;

  TYPE B_TaggedRec IS NEW TaggedRec WITH RECORD
    F2: Float;  
  END RECORD;

  TYPE C_TaggedRec IS NEW TaggedRec WITH RECORD
    F3: Boolean;
  END RECORD;

-- OK, some arrays now.

-- CASE 1: array of unconstrained variant records. OK in Ada 83.

  TYPE List IS ARRAY (1..4) OF VariantRec; -- unconstrained variant rec
  Stuff: List;

-- CASE 2: Now an array intended to hold any of the four types
-- (by direct analogy with Case 1)

-- GNAT rejects this - says the array elements must be constrained

  TYPE TaggedList IS ARRAY (1..4) OF TaggedRec'Class;
  TaggedStuff: TaggedList;

-- CASE 3: Array of_pointers_ to tagged records
-- This will compile OK, but seems a gratuitously required use
-- of pointers - very un-Ada-like.

  TYPE TaggedRecPtr IS ACCESS TaggedRec'Class; 
  TYPE TaggedListPtr IS ARRAY (1..4) OF TaggedRecPtr;
  TaggedStuffPtr: TaggedList;

-- So what is the solution? Perhaps I missed something in 9XRM 5.0,
-- but I found nothing to prohibit what I tried to do in Case 2.

-- The Ada 9X textbook examples make much of the fact that one
-- _can_ use pointers more flexibly in 9X, because e.g. the
-- designated objects need not be dynamic. They also show pointers
-- as a way that one _can_ do dispatching of operations on tagged-type
-- derivatives. It is not clear where (or why) this is the _only_
-- allowed way.

-- So did I bump into an Ada 9X feature, or just a GNAT bug?

BEGIN

  NULL;

END TestTags;

-- Mike Feldman



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Tagged type feature, or GNAT bug?
  1994-09-27 16:36 Tagged type feature, or GNAT bug? Michael Feldman
@ 1994-09-27 23:22 ` Bob Duff
  1994-09-28 11:14 ` Robert Dewar
  1 sibling, 0 replies; 3+ messages in thread
From: Bob Duff @ 1994-09-27 23:22 UTC (permalink / raw)


In article <369hme$e9j@felix.seas.gwu.edu>,
Michael Feldman <mfeldman@seas.gwu.edu> wrote:
>-- CASE 1: array of unconstrained variant records. OK in Ada 83.
>
>  TYPE List IS ARRAY (1..4) OF VariantRec; -- unconstrained variant rec
>  Stuff: List;
>
>-- CASE 2: Now an array intended to hold any of the four types
>-- (by direct analogy with Case 1)
>
>-- GNAT rejects this - says the array elements must be constrained

GNAT is correct here.  The rule is in RM9X-3.6(10), which says the
component subtype has to be a definite subtype.  Class-wide subtypes are
not definite (see 3.3(23) and 3.7(26)).

Class-wide subtypes are like discriminated subtypes *without* defaults.

>  TYPE TaggedList IS ARRAY (1..4) OF TaggedRec'Class;
>  TaggedStuff: TaggedList;
>
>-- CASE 3: Array of_pointers_ to tagged records
>-- This will compile OK, but seems a gratuitously required use
>-- of pointers - very un-Ada-like.
>
>  TYPE TaggedRecPtr IS ACCESS TaggedRec'Class; 
>  TYPE TaggedListPtr IS ARRAY (1..4) OF TaggedRecPtr;
>  TaggedStuffPtr: TaggedList;

That's right -- you have to use pointers (ahem, I mean access types).

Basically, "definite" means the compiler knows how much space to
allocate.  Clearly, the compiler can't know how much space to allocate
for a class-wide subtype, because you can add type extensions later,
and these can have arbitrary sizes.

Since the compiler doesn't know how much space to allocate, you have to
use a pointer.

Ada, being intended for real-time applications, doesn't like to have
implicit pointers, and the corresponding implicit heap allocation.
Instead, whenever the compiler doesn't know the size, the language
requires the programmer to use pointers, and do the necessary
allocations "by hand".

In other words, the reason you can't have an array of class-wide is the
same reason you can't have an array of unconstrained arrays:

    type T is array(1..10) of String; -- Illegal!

This example makes perfect sense from a logical point of view, but would
require implicit heap management by the compiler.  Therefore, you have
to use an access-to-String type in this example.  Same thing for
class-wide.

Thus, when converting an application that uses
discriminants-with-defaults to one that uses class-wide types, you have
to introduce pointers.  For discriminants-with-defaults, the compiler
can see the whole variant record, and can figure out the maximum size.
For class-wide subtypes, however, the maximum size is unbounded.

There are some compilers that introduce implicit heap allocation for
discriminants with defaults.  However, that is by no means universal
among compilers, and is arguably naughty behavior in a real-time
environment.  We certainly didn't want to *require* such behavior for
class-wide subtypes.

Most other OOP languages that I know of have the same restriction --
most (e.g. Smalltalk) use pointer semantics *everywhere*, and the ones
that don't (e.g. C++) require the "tag" to be nailed down (and not
change) by the time an object is created.  In either case, to change a
tag normally requires deallocating and reallocating the object -- using
pointers.
-- 
Bob Duff                                bobduff@inmet.com
Oak Tree Software, Inc.
Ada 9X Mapping/Revision Team (Intermetrics, Inc.)



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Tagged type feature, or GNAT bug?
  1994-09-27 16:36 Tagged type feature, or GNAT bug? Michael Feldman
  1994-09-27 23:22 ` Bob Duff
@ 1994-09-28 11:14 ` Robert Dewar
  1 sibling, 0 replies; 3+ messages in thread
From: Robert Dewar @ 1994-09-28 11:14 UTC (permalink / raw)


Obviously you can't have an array of type'Class, because the whole point is
that you don't know till link time what the maximum size of such an object
would be. So if you think about it Mike, you have no implementation model
for how that would work except to introduce pointers, and the solution is
simple enough: introduce the pointers in the code. Always work with pointers
to T'Class, not T'Class objects themselves.

Actually that's good advice in the variant record case too. In general the
business of allocating the maximum possible space doesn't work so well even
for variant records where you know all the possibilities statically. Some
Ada 83 compilers (RR?) introduce hidden pointers in this case, and others
(ALsys) allocate the maximum space, but place an arbitrary limit on the
maximum size permitted.

It's helpful always to think about what your implementation model is when
you run into something like this. If you can't think of a simple model, then
very likely there is a problem!

Robert




^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~1994-09-28 11:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1994-09-27 16:36 Tagged type feature, or GNAT bug? Michael Feldman
1994-09-27 23:22 ` Bob Duff
1994-09-28 11:14 ` Robert Dewar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox