comp.lang.ada
 help / color / mirror / Atom feed
* allocators for classwide types?
@ 1999-12-28  0:00 Ted Dennison
  1999-12-28  0:00 ` Robert A Duff
  0 siblings, 1 reply; 6+ messages in thread
From: Ted Dennison @ 1999-12-28  0:00 UTC (permalink / raw)


I have a situation where I'd like to create a convienence routine that
takes in two objects of classwide types, allocates objects of the
appropriate type with a copy of those parameter values, then puts both
objects in a record which gets returned to the user.

The thing is, it doesn't look like the language provides any way to
express initialized allocation from classwide parameters. For example, I
would like to do the following:


   subtype P1_Class is Package_1.Instance'Class;
   subtype P2_Class is Package_2.Instance.Class;
   type P1_Handle is access all P1_Class;
   type P2_Handle is access all P2_Class;
   type Descriptor is record
      Field_1 : P1_Handle;
      Field_2 : P2_Handle;
   end record;
   .
   .
   .
   function Get (F1 : in P1_Class;
                 F2 : in P2_Class := Package_2.Get
                 ) return Recognizable_Token is
   begin
      return (Field_1 => new P1_Class'(F1),
              Field_2 => new P2_Class'(F2)
              );
   end Get;

Gnat actually generates a compiler error on my variant of this. Thinking
about it logicly (often a mistake, but I like to do it anyway), the LRM
does not seem to specificly disallow this. P1_Class and P2_Class *are*
subtype indications. But it would also make absolutely no sense to do a
"new P1_Class;" (without the initilizing value) because it would have
idea how much space to allocate. However, what I'm trying to do does
make sense, as the program could figure out the actual type at runtime.

Either way, I take it the above code is somehow not legal? Is there a
trick I can use to get around this, or are my clients going to be stuck
doing their own dynamic allocations?

--
T.E.D.

mailto:dennison@telepath.com
WWW  - http://www.telepath.com/dennison/Ted/TED.html






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

* Re: allocators for classwide types?
  1999-12-28  0:00 allocators for classwide types? Ted Dennison
@ 1999-12-28  0:00 ` Robert A Duff
  1999-12-28  0:00   ` Ted Dennison
  0 siblings, 1 reply; 6+ messages in thread
From: Robert A Duff @ 1999-12-28  0:00 UTC (permalink / raw)


Ted Dennison <dennison@telepath.com> writes:

> I have a situation where I'd like to create a convienence routine that
> takes in two objects of classwide types, allocates objects of the
> appropriate type with a copy of those parameter values, then puts both
> objects in a record which gets returned to the user.
> 
> The thing is, it doesn't look like the language provides any way to
> express initialized allocation from classwide parameters. For example, I
> would like to do the following:
> 
> 
>    subtype P1_Class is Package_1.Instance'Class;
>    subtype P2_Class is Package_2.Instance.Class;
>    type P1_Handle is access all P1_Class;
>    type P2_Handle is access all P2_Class;
>    type Descriptor is record
>       Field_1 : P1_Handle;
>       Field_2 : P2_Handle;
>    end record;
>    .
>    .
>    .
>    function Get (F1 : in P1_Class;
>                  F2 : in P2_Class := Package_2.Get
>                  ) return Recognizable_Token is
                            ^^^^^^^^^^^^^^^^^^
You mean "Descriptor" here?

>    begin
>       return (Field_1 => new P1_Class'(F1),
>               Field_2 => new P2_Class'(F2)
>               );
>    end Get;

Your code looks OK to me.

> Gnat actually generates a compiler error on my variant of this. ...

You should post the text of the message.

>... Thinking
> about it logicly (often a mistake, but I like to do it anyway), the LRM
> does not seem to specificly disallow this. P1_Class and P2_Class *are*
> subtype indications. But it would also make absolutely no sense to do a
> "new P1_Class;" (without the initilizing value) because it would have
> idea how much space to allocate.

That's right -- you have to initialize it, as you did.

>... However, what I'm trying to do does
> make sense, as the program could figure out the actual type at runtime.

Right.

- Bob




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

* Re: allocators for classwide types?
  1999-12-28  0:00   ` Ted Dennison
@ 1999-12-28  0:00     ` Ted Dennison
  2000-01-06  0:00       ` Robert A Duff
  0 siblings, 1 reply; 6+ messages in thread
From: Ted Dennison @ 1999-12-28  0:00 UTC (permalink / raw)


Ted Dennison wrote:

> Robert A Duff wrote:
>
> > > Gnat actually generates a compiler error on my variant of this. ...
> >
> > You should post the text of the message.
>
> It was an internal Gnat error. That's obviously a bug, of course. But 95% of
> the time those are caused by my doing something illegal in a way that the
> compiler didn't expect. It looks like in this case I may have been doing

OK. After further playing around, it appears the problem was actually a convoluted
parameter naming problem; not really anything to do with classwide types at all.
In my actual code, the package "Get" existed in was a generic child package of
package_1, which itself was a generic. The second parameter happened to be named
the same as the parent package. It also happened to be named the same as the
record field it was getting allocated and placed into. I expanded my toy example
to match:

-----
generic
   type Fred is (<>);
package Package_1 is

   type Instance is tagged record
      Fred_Field : Fred := Fred'First;
   end record;

   subtype Class is Instance'Class;
   type Handle is access all Class;

end Package_1;
package Package_2 is

   type Instance is tagged null record;
   subtype Class is Instance'Class;
   type Handle is access all Class;

end Package_2;
with Package_1;
with Package_2;

generic
   Max_Fred : in Fred := Fred'Last;
package Package_1.Classwide_Allocator is

   type Descriptor is record
      Field_1 : Package_1.Handle;
      Field_2 : Package_2.Handle;
   end record;

   function Get (Package_1 : in Package_1.Class;
                 F2 : in Package_2.Class
                ) return Descriptor;

end Package_1.Classwide_Allocator;
package body Package_1.Classwide_Allocator is

   function Get (Package_1 : in Package_1.Class;
                 F2 : in Package_2.Class
                ) return Descriptor is
   begin
      return (Field_1 => new Package_1.Class'(Package_1),
              Field_2 => new Package_2.Class'(F2)
              );
   end Get;

end Package_1.Classwide_Allocator;
----

The above complains on the declaration of Get about an attempt to use Package_1
before the child package is complete. Obviously its confusing Package_1 the
parameter with Package_1 the package. Is this what its supposed to do? I suspect
so.

But lets add one more wrinkle that my full program has. Package_1 (and thus its
child) are actually themselves children of another package:

----
package T is
   Global : constant := 3;
end T;
generic
   type Fred is (<>);
package T.Package_1 is

   type Instance is tagged record
      Fred_Field : Fred := Fred'First;
   end record;

   subtype Class is Instance'Class;
   type Handle is access all Class;

end T.Package_1;
package Package_2 is

   type Instance is tagged null record;
   subtype Class is Instance'Class;
   type Handle is access all Class;

end Package_2;
with T.Package_1;
with Package_2;

generic
   Max_Fred : in Fred := Fred'Last;
package T.Package_1.Classwide_Allocator is

   type Descriptor is record
      Field_1 : T.Package_1.Handle;
      Field_2 : Package_2.Handle;
   end record;

   function Get (Package_1 : in T.Package_1.Class;
                 F2 : in Package_2.Class
                ) return Descriptor;

end T.Package_1.Classwide_Allocator;
package body T.Package_1.Classwide_Allocator is

   function Get (Package_1 : in T.Package_1.Class;
                 F2 : in Package_2.Class
                ) return Descriptor is
   begin
      return (Field_1 => new T.Package_1.Class'(Package_1),
              Field_2 => new Package_2.Class'(F2)
              );
   end Get;

end T.Package_1.Classwide_Allocator;

with T.Package_1;
with Package_2;
with T.Package_1.Classwide_Allocator;

procedure Test is
   package P1 is new T.Package_1 (Integer);
   package Allocator is new P1.Classwide_Allocator;

   Field_1 : P1.Instance;
   Field_2 : Package_2.Instance;
   Descriptor : Allocator.Descriptor;
begin
   Descriptor := Allocator.Get (Field_1, Field_2);
end Test;
----

Compiling this with gnat 3.12p now gets the same results I get in my actual code,
namely:

gcc -c -Ic:/Development/Classwide_Allocator/ -I./ -g -gnatq -I-
c:/Development/Classwide_Allocator/test.adb

raised TYPES.UNRECOVERABLE_ERROR : comperr.adb:88
gnatmake: "c:/Development/Classwide_Allocator/test.adb" compilation error

Compilation exited abnormally with code 4 at Tue Dec 28 11:57:59


I'll forwarding this message along to report@gnat.com


--
T.E.D.

Home - mailto:dennison@telepath.com  Work - mailto:dennison@ssd.fsi.com
WWW  - http://www.telepath.com/dennison/Ted/TED.html  ICQ  - 10545591






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

* Re: allocators for classwide types?
  1999-12-28  0:00 ` Robert A Duff
@ 1999-12-28  0:00   ` Ted Dennison
  1999-12-28  0:00     ` Ted Dennison
  0 siblings, 1 reply; 6+ messages in thread
From: Ted Dennison @ 1999-12-28  0:00 UTC (permalink / raw)


Robert A Duff wrote:

> Ted Dennison <dennison@telepath.com> writes:
>
> > I have a situation where I'd like to create a convienence routine that
> > takes in two objects of classwide types, allocates objects of the
> > appropriate type with a copy of those parameter values, then puts both
> > objects in a record which gets returned to the user.
>
> Your code looks OK to me.

Hmm. Apparently it is. I tried expanding my toy example into a compilable
system, and Gnat had no trouble with it.


> > Gnat actually generates a compiler error on my variant of this. ...
>
> You should post the text of the message.

It was an internal Gnat error. That's obviously a bug, of course. But 95% of
the time those are caused by my doing something illegal in a way that the
compiler didn't expect. It looks like in this case I may have been doing
something *legal* in a way the compiler didn't expect.

I guess the right thing to do would be to try and expand my toy example to
reproduce the bug, then submit it to ACT. That's not exactly how I wanted to
spend my coding time on my vacation, but I guess if I always got what I wanted
this would be a scary world indeed...

--
T.E.D.

Home - mailto:dennison@telepath.com
WWW  - http://www.telepath.com/dennison/Ted/TED.html






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

* Re: allocators for classwide types?
  1999-12-28  0:00     ` Ted Dennison
@ 2000-01-06  0:00       ` Robert A Duff
  2000-01-07  0:00         ` Robert Dewar
  0 siblings, 1 reply; 6+ messages in thread
From: Robert A Duff @ 2000-01-06  0:00 UTC (permalink / raw)


Ted Dennison <dennison@telepath.com> writes:

>    function Get (Package_1 : in Package_1.Class;
>                  F2 : in Package_2.Class
>                 ) return Descriptor;

This is illegal.  The parameter Package_1 hides the package Package_1,
so you can't say "Package_1.Class" in the declaration of the parameter.

If the error message was confusing, then maybe that's a bug, but
certainly the compiler should give *some* error message.

- Bob




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

* Re: allocators for classwide types?
  2000-01-06  0:00       ` Robert A Duff
@ 2000-01-07  0:00         ` Robert Dewar
  0 siblings, 0 replies; 6+ messages in thread
From: Robert Dewar @ 2000-01-07  0:00 UTC (permalink / raw)


In article <wccln63xpf5.fsf@world.std.com>,
  Robert A Duff <bobduff@world.std.com> wrote:
> Ted Dennison <dennison@telepath.com> writes:
>
> >    function Get (Package_1 : in Package_1.Class;
> >                  F2 : in Package_2.Class
> >                 ) return Descriptor;
>
> This is illegal.  The parameter Package_1 hides the package
Package_1,
> so you can't say "Package_1.Class" in the declaration of the
parameter.
>
> If the error message was confusing, then maybe that's a bug,
but
> certainly the compiler should give *some* error message.


GNAT would say here:

j.ads:8:30: formal parameter "Package_1" cannot be used before
            end of specification


which seems clear enough!

Robert Dewar
Ada Core Technologies


Sent via Deja.com http://www.deja.com/
Before you buy.




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

end of thread, other threads:[~2000-01-07  0:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-12-28  0:00 allocators for classwide types? Ted Dennison
1999-12-28  0:00 ` Robert A Duff
1999-12-28  0:00   ` Ted Dennison
1999-12-28  0:00     ` Ted Dennison
2000-01-06  0:00       ` Robert A Duff
2000-01-07  0:00         ` Robert Dewar

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