comp.lang.ada
 help / color / mirror / Atom feed
* Access to aliased string declaration question.
@ 1999-06-09  0:00 Rex Reges
  1999-06-10  0:00 ` Robert Dewar
  1999-06-10  0:00 ` Matthew Heaney
  0 siblings, 2 replies; 4+ messages in thread
From: Rex Reges @ 1999-06-09  0:00 UTC (permalink / raw)


Example program below doesn't compile...

with Text_IO ;
use  Text_IO ;

procedure Borg is

   -- Example of ragged arrays using heap and declared values.

   -- Create access to unconstrained type string.
   type String_Access_Type is access all String ;

   -- Define an array of strings:
   type String_Array_Type is array ( Positive range <> ) of
String_Access_Type ;

   -- Declare "ragged" arrays of strings...
   Borg_Strings  : String_Array_Type ( 1..3 ) ;
   Dalek_Strings : String_Array_Type ( 1..3 ) ;

   -- Create constants for alias access example.
   --                                                 
123456789112345678921
   Static_Dalek_String_1 : aliased String( 1..21 ) := "Resistance is
futile."  ;
   Static_Dalek_String_2 : aliased String( 1..12 ) :=
"Exterminate!"           ;
   Static_Dalek_String_3 : aliased String( 1..12 ) :=
"Exterminate!"           ;


begin
 
   -- Create the heap strings.
 
   Borg_Strings(1) := new String'( "We are the Borg."         );
   Borg_Strings(2) := new String'( "Resistance is futile."    );
   Borg_Strings(3) := new String'( "You will be assimilated." );
 
 
   -- Assign the declared strings.
 
   Dalek_Strings := ( 1 => Static_Dalek_String_1'access ,
                      2 => Static_Dalek_String_2'access ,
                      3 => Static_Dalek_String_3'access ) ;
 
 
   -- The Borg versus the Daleks...
   for I in 1..3 
   loop
       Put_Line( "Borg:  " & Borg_Strings ( I ).all ) ;
       Put_Line( "Dalek: " & Dalek_Strings( I ).all ) ;
   end loop ;
   
 
end Borg;

End of example program.
The compilation results for this program are:

   $ gnatmake borg.adb
   gcc -c borg.adb
   borg.adb:36:28: object subtype must statically match designated
subtype
   borg.adb:37:28: object subtype must statically match designated
subtype
   borg.adb:38:28: object subtype must statically match designated
subtype
   gnatmake: "borg.adb" compilation error


If I remove the Dalek's string range indices, the program compiles 
without error:

   Static_Dalek_String_1 : aliased String := "Resistance is futile."  ;
   Static_Dalek_String_2 : aliased String := "Exterminate!"           ;
   Static_Dalek_String_3 : aliased String := "Exterminate!"           ;


Why is this so? Shouldn't String_Access_Type be able to point to any
string?


Rex Reges




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

* Re: Access to aliased string declaration question.
  1999-06-09  0:00 Access to aliased string declaration question Rex Reges
@ 1999-06-10  0:00 ` Robert Dewar
  1999-06-10  0:00 ` Matthew Heaney
  1 sibling, 0 replies; 4+ messages in thread
From: Robert Dewar @ 1999-06-10  0:00 UTC (permalink / raw)


In article <375ED457.A85A462B@Boeing.com>,
  Rex Reges <Rex.R.Reges@Boeing.com> wrote:
> Example program below doesn't compile...
>
> with Text_IO ;
> use  Text_IO ;
>
> procedure Borg is
>
>    -- Example of ragged arrays using heap and declared values.

<<code snipped>>

a very common error, common enough that we added some extra
warnings to GNAT to help understand the error. Your program
now generates warnings like:

    23.   Static_Dalek_String_3 : aliased String( 1..12 ) :=
                                                 "Exterminate!";
          |
        >>> warning: aliased object has explicit bounds
        >>> warning: declare with explicit initialization
        >>> warning: for use with unconstrained access

If you give explicit bounds, then you cannot use an
unconstrained access. This confusing rule results from the
fact that the explicit bounds make the nominal subtype of
the object constrained. Just remove the bounds and all will
be well.

The reason for this (in my opinion highly dubious) bit of
language design is to allow the compiler to save space and
not generate a template for the bounds in this case. I
personally think this was a case of the design being over-
influenced by a very minor space optimization issue.



Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Re: Access to aliased string declaration question.
  1999-06-09  0:00 Access to aliased string declaration question Rex Reges
  1999-06-10  0:00 ` Robert Dewar
@ 1999-06-10  0:00 ` Matthew Heaney
  1999-06-10  0:00   ` Matthew Heaney
  1 sibling, 1 reply; 4+ messages in thread
From: Matthew Heaney @ 1999-06-10  0:00 UTC (permalink / raw)


On 9 Jun 1999 20:53, Rex Reges <Rex.R.Reges@Boeing.com> wrote:

> Why is this so? Shouldn't String_Access_Type be able to point to any
> string?

Not exactly.  An access object of type String_Access_Type can only point
to /unconstrained/ strings.

You have to understand how arrays and array pointers are implemented.

Associated with an unconstrained array object is a little data structure
called a "string descriptor" or "dope vector," that stores the indices
of the array and the length of the array.

When you deference an access object that designates a unconstrained
string object, the compiler (er, run-time system) uses the dope vector
to determine how long the array is, or to determine which physical
characters are being accessed.

For example, if S is an access object, then the dereference:

  Put_Line (S.all);

would look up the length of the string designated by S in the dope
vector associated with that string object.

Pointers to unconstrained arrays always do this: consult the dope
vector.

However, for constrained array objects, no dope vector is necessary,
because you know everything about the string object at the point of its
declaration.  For example:

  S : String (1 .. 10);

You know the length and bounds of S, so there is no need for any
additional data structure (ie a dope vector) to store the info.

Likewise for a constrained array access type:

  type String_Access is access all String (1 .. 10);

  S : String_Access;

When you deference S, you know up front what the length and indices of
the designed string object are, so you don't need to consult a dope
vector.

So we see that an access object that designates an unconstrained array
object is fundamentally different from an access object that designates
a constrained array object.  The former must consult a dope vector, the
latter does not.

Now you might argue that you might as well generate a dope vector for
this declaration, even though it's constrained:

   Static_Dalek_String_1 : aliased String (1 .. 21) := 
     "Resistance is futile.";

If you did so, then you'd be able to designate this string object using
either kind of access type.  

However, this would generate an extra 8 bytes (for the dope vector) for
each string object, all in the hope that maybe the object will be
designated by an unconstrained access object.

But Ada is a systems programming language, and systems programmers don't
take kindly to this kind of code bloat.  They want to pay only for what
they need, and having to carry around extra dope vector baggage when it
isn't needed for the problem at hand would not be acceptable.

Ada puts you, the programmer, in the driver's seat: if /you/ want a dope
vector, then /you/ declare the object like this, without bounds:

   Static_Dalek_String_1 : aliased String := 
     "Resistance is futile.";

If you want no dope vector, then declare it as you did earlier, with
explicit bounds.

Yes, this must seem like a pain in the ass.  I'm not unsympathetic.  But
it's just a consequence of the fact that Ada is for programming systems,
and you have to let the /programmer/ decide where and when he wants to
pay storage cost.

It's not all that bad, either.  Sometimes you can have it both ways by
declaring a dynamic (or maybe static) access subtype:

  type String_Access is access all String;

  S : aliased String (1 .. 10);

...

  declare
    subtype S_Access is String_Access (S'Range);
    SA : S_Access := S'Access;
  begin

Here we declare a subtype that points only to strings having the bounds
of object S.  This is a constrained string object, designed by an access
object whose (base) type is unconstrained.

This works even if the bounds are determined at run-time:

  procedure Op (F, L : Positive) is

    S : aliased String (F .. L);

    subtype S_Access is String_Access (F .. L);  -- or S'Range

    SA : S_Access := S'Access;

  begin


Post another message if any of this is unclear.  This is one of the more
esoteric features of Ada.

Matt
<mailto:matthew_heaney@acm.org>








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

* Re: Access to aliased string declaration question.
  1999-06-10  0:00 ` Matthew Heaney
@ 1999-06-10  0:00   ` Matthew Heaney
  0 siblings, 0 replies; 4+ messages in thread
From: Matthew Heaney @ 1999-06-10  0:00 UTC (permalink / raw)


On 10 Jun 1999 04:39, Matthew Heaney <matthew_heaney@acm.org> wrote:

> It's not all that bad, either.  Sometimes you can have it both ways by
> declaring a dynamic (or maybe static) access subtype:
> 
>   type String_Access is access all String;
> 
>   S : aliased String (1 .. 10);
> 
> ...
> 
>   declare
>     subtype S_Access is String_Access (S'Range);
>     SA : S_Access := S'Access;
>   begin
> 
> Here we declare a subtype that points only to strings having the bounds
> of object S.  This is a constrained string object, designed by an access
> object whose (base) type is unconstrained.

Actually, you don't even need the subtype mark:

  declare
    SA : String_Access (S'Range) := S'Access;
  begin


> This works even if the bounds are determined at run-time:
> 
>   procedure Op (F, L : Positive) is
> 
>     S : aliased String (F .. L);
> 
>     subtype S_Access is String_Access (F .. L);  -- or S'Range
> 
>     SA : S_Access := S'Access;
> 
>   begin


No subtype mark is needed here either:

  procedure Op (F, L : Positive) is

     S : aliased String (F .. L);

     SA : String_Access (S'Range) := S'Access;

  begin







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

end of thread, other threads:[~1999-06-10  0:00 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-06-09  0:00 Access to aliased string declaration question Rex Reges
1999-06-10  0:00 ` Robert Dewar
1999-06-10  0:00 ` Matthew Heaney
1999-06-10  0:00   ` Matthew Heaney

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