comp.lang.ada
 help / color / mirror / Atom feed
* Dynamically tagged expression not allowed. Why?
@ 2010-05-29 17:36 Marc A. Criley
  2010-05-29 18:23 ` Dmitry A. Kazakov
  2010-06-01 23:36 ` Randy Brukardt
  0 siblings, 2 replies; 10+ messages in thread
From: Marc A. Criley @ 2010-05-29 17:36 UTC (permalink / raw)


I'm creating a GNAT 4.4.3 on Ubuntu Ada binding for some C++ classes, 
using the binding generated by g++ -fdump-ada-spec as a starting point. 
While the binding will compile cleanly, the client code gets a 
compilation error, "dynamically tagged expression not allowed", when 
trying to set up the declarations to utilize it.

Stripping out a test case, I see that it has nothing to with the C++ 
binding per se, but it's an Ada issue that's flummoxing me.  Here's the 
test code:

procedure Dyty_Test is

    type Class_Type is tagged limited record
       null;
    end record;

    function New_Class_Instance return Class_Type'Class;

    Conn : Class_Type := New_Class_Instance;

    function New_Class_Instance return Class_Type'Class is
    begin
       -- Just a stub
       return New_Class_Instance;
    end New_Class_Instance;

begin
    null;
end Dyty_Test;

The Class_Type definition MUST be a tagged limited record to correspond 
to the C++ class, and the New_Class_Instance function (the constructor) 
MUST return a class-wide instance of that type.  (There are 
corresponding C++ pragmas as well for these, but the error is the same 
whether they're present or not.)

The error is on the declaration of "Conn", with the error occurring on 
the invocation of the initializing New_Class_Instance function. I'm just 
not understanding something here.

I've tried a number of variations, but these have more or less become 
guesswork, and so it's time to ask for help :-)


Thanks.

Marc A. Criley
McKae Technologies
www.mckae.com



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

* Re: Dynamically tagged expression not allowed. Why?
  2010-05-29 17:36 Dynamically tagged expression not allowed. Why? Marc A. Criley
@ 2010-05-29 18:23 ` Dmitry A. Kazakov
  2010-06-03  2:37   ` Yannick Duchêne (Hibou57)
  2010-06-01 23:36 ` Randy Brukardt
  1 sibling, 1 reply; 10+ messages in thread
From: Dmitry A. Kazakov @ 2010-05-29 18:23 UTC (permalink / raw)


On Sat, 29 May 2010 12:36:33 -0500, Marc A. Criley wrote:

> Stripping out a test case, I see that it has nothing to with the C++ 
> binding per se, but it's an Ada issue that's flummoxing me.  Here's the 
> test code:
> 
> procedure Dyty_Test is
> 
>     type Class_Type is tagged limited record
>        null;
>     end record;
> 
>     function New_Class_Instance return Class_Type'Class;
> 
>     Conn : Class_Type := New_Class_Instance;

Should Conn be mutable? Otherwise you could use a function instead.

>     function New_Class_Instance return Class_Type'Class is
>     begin
>        -- Just a stub
>        return New_Class_Instance;

Infinite recursion. I suppose it is

return X : Class_Type;

>     end New_Class_Instance;
> 
> The error is on the declaration of "Conn", with the error occurring on 
> the invocation of the initializing New_Class_Instance function. I'm just 
> not understanding something here.

You are "returning" a class-wide limited object, which is to "initialize" a
specific object.

A more difficult problem is that to initialize Conn, GNAT wants to know the
body of the initializer.
--------------------------------------------------------------
Variant 1. Two packages (to have the body):

   package P is
      type Class_Type is tagged limited record
         null;
      end record;
      function New_Class_Instance return Class_Type'Class;
      function New_Class_Object return Class_Type;
   end P;

   package P.Instances is
      Conn : Class_Type := New_Class_Object;
   end P.Instances;

   package body P is
      function New_Class_Object return Class_Type is
      begin
         return X : Class_Type;
      end New_Class_Object;
      function New_Class_Instance return Class_Type'Class is
      begin
         return New_Class_Object;
      end New_Class_Instance;
   end P;
----------------------------------------------------------------------------------------------------
Variant 2. Old good Ada initialization (in 80's we knew how to do it right)

   package P is
      type Class_Type is tagged limited record
         null;
      end record;
      function New_Class_Instance return Class_Type'Class;
      Conn : Class_Type; -- It will be OK upon the body elaboration!
   end P;

   package body P is
      procedure Construct (Object : in out Class_Type) is
      begin
         null;
      end Construct;
      function New_Class_Instance return Class_Type'Class is
      begin
         return X : Class_Type do
            Construct (X);
         end return;
      end New_Class_Instance;
   begin
      Construct (Conn); -- Fix it now
   end P;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Dynamically tagged expression not allowed. Why?
  2010-05-29 17:36 Dynamically tagged expression not allowed. Why? Marc A. Criley
  2010-05-29 18:23 ` Dmitry A. Kazakov
@ 2010-06-01 23:36 ` Randy Brukardt
  2010-06-03  2:36   ` Yannick Duchêne (Hibou57)
  2010-06-05 18:47   ` Marc A. Criley
  1 sibling, 2 replies; 10+ messages in thread
From: Randy Brukardt @ 2010-06-01 23:36 UTC (permalink / raw)


"Marc A. Criley" <mcNOSPAM@mckae.com> wrote in message 
news:c2ead$4c0150a0$4ca4a823$11809@API-DIGITAL.COM...
...
> Stripping out a test case, I see that it has nothing to with the C++ 
> binding per se, but it's an Ada issue that's flummoxing me.  Here's the 
> test code:
>
> procedure Dyty_Test is
>
>    type Class_Type is tagged limited record
>       null;
>    end record;
>
>    function New_Class_Instance return Class_Type'Class;
>
>    Conn : Class_Type := New_Class_Instance;

This is illegal because the function returns a class-wide object and you are 
assigning it into an object of a specific type. You have to explicitly use a 
type conversion here:

    Conn : Class_Type := Class_Type (New_Class_Instance);

to specify that you want to truncate the returned object, or make the object 
classwide:

   Conn : Class_Type'Class := New_Class_Instance;

But notice that while both of these are legal, they'll both raise 
Program_Error because an access-before-elaboration error (the body of 
New_Class_Instance hasn't been elaborated at the point of this call).

                               Randy.






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

* Re: Dynamically tagged expression not allowed. Why?
  2010-06-01 23:36 ` Randy Brukardt
@ 2010-06-03  2:36   ` Yannick Duchêne (Hibou57)
  2010-06-03  7:57     ` Dmitry A. Kazakov
  2010-06-03 16:03     ` Adam Beneschan
  2010-06-05 18:47   ` Marc A. Criley
  1 sibling, 2 replies; 10+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2010-06-03  2:36 UTC (permalink / raw)


Le Wed, 02 Jun 2010 01:36:17 +0200, Randy Brukardt <randy@rrsoftware.com>  
a écrit:
> You have to explicitly use a
> type conversion here:
>
>     Conn : Class_Type := Class_Type (New_Class_Instance);
>
This one is not legal, as Class_Type is limited and conversion are not  
allowed on limited type due to their copy based semantic.
[ARM 2005 4.6] says about type conversions
“Neither the target type nor the operand type shall be limited”

> to specify that you want to truncate the returned object, or make the  
> object
> classwide:
>
>    Conn : Class_Type'Class := New_Class_Instance;
That is a beautiful one (to my eyes)


> But notice that while both of these are legal, they'll both raise
> Program_Error because an access-before-elaboration error (the body of
> New_Class_Instance hasn't been elaborated at the point of this call).
Not necessarily, as he can move the body of the function returning  
Class_Type before the declaration of the variable initialized from this  
function.

Instead of


    function New_Class_Instance return Class_Type'Class;

    Conn : Class_Type := New_Class_Instance;

    function New_Class_Instance return Class_Type'Class is
    begin
       -- Just a stub
       return New_Class_Instance;
    end New_Class_Instance;


Simply do


    function New_Class_Instance return Class_Type'Class;

    function New_Class_Instance return Class_Type'Class is
    begin
       -- Just a stub
       return New_Class_Instance;
    end New_Class_Instance;

    Conn : Class_Type := New_Class_Instance;

and everything will go fine.

-- 
There is even better than a pragma Assert: a SPARK --# check.
--# check C and WhoKnowWhat and YouKnowWho;
--# assert Ada;
--  i.e. forget about previous premises which leads to conclusion
--  and start with new conclusion as premise.



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

* Re: Dynamically tagged expression not allowed. Why?
  2010-05-29 18:23 ` Dmitry A. Kazakov
@ 2010-06-03  2:37   ` Yannick Duchêne (Hibou57)
  2010-06-03  7:48     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 10+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2010-06-03  2:37 UTC (permalink / raw)


Le Sat, 29 May 2010 20:23:36 +0200, Dmitry A. Kazakov  
<mailbox@dmitry-kazakov.de> a écrit:
>>     Conn : Class_Type := New_Class_Instance;
>
> Should Conn be mutable? Otherwise you could use a function instead.
>
Good note (formally talking).

May be the reason was a matter of efficiency ?

-- 
There is even better than a pragma Assert: a SPARK --# check.
--# check C and WhoKnowWhat and YouKnowWho;
--# assert Ada;
--  i.e. forget about previous premises which leads to conclusion
--  and start with new conclusion as premise.



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

* Re: Dynamically tagged expression not allowed. Why?
  2010-06-03  2:37   ` Yannick Duchêne (Hibou57)
@ 2010-06-03  7:48     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 10+ messages in thread
From: Dmitry A. Kazakov @ 2010-06-03  7:48 UTC (permalink / raw)


On Thu, 03 Jun 2010 04:37:42 +0200, Yannick Duch�ne (Hibou57) wrote:

> Le Sat, 29 May 2010 20:23:36 +0200, Dmitry A. Kazakov  
> <mailbox@dmitry-kazakov.de> a �crit:
>>>     Conn : Class_Type := New_Class_Instance;
>>
>> Should Conn be mutable? Otherwise you could use a function instead.
>>
> Good note (formally talking).
> 
> May be the reason was a matter of efficiency ?

A renaming could also go, but it would not because of the "unseen body"
problem.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Dynamically tagged expression not allowed. Why?
  2010-06-03  2:36   ` Yannick Duchêne (Hibou57)
@ 2010-06-03  7:57     ` Dmitry A. Kazakov
  2010-06-03  8:21       ` Yannick Duchêne (Hibou57)
  2010-06-03 16:03     ` Adam Beneschan
  1 sibling, 1 reply; 10+ messages in thread
From: Dmitry A. Kazakov @ 2010-06-03  7:57 UTC (permalink / raw)


On Thu, 03 Jun 2010 04:36:12 +0200, Yannick Duch�ne (Hibou57) wrote:

> Not necessarily, as he can move the body of the function returning  
> Class_Type before the declaration of the variable initialized from this  
> function.

You cannot have bodies in the package specifications. This is a difficult
problem, since present construction model does not support deferred
initialization. In short, you cannot have this in a single package.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Dynamically tagged expression not allowed. Why?
  2010-06-03  7:57     ` Dmitry A. Kazakov
@ 2010-06-03  8:21       ` Yannick Duchêne (Hibou57)
  0 siblings, 0 replies; 10+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2010-06-03  8:21 UTC (permalink / raw)


Le Thu, 03 Jun 2010 09:57:33 +0200, Dmitry A. Kazakov  
<mailbox@dmitry-kazakov.de> a écrit:
> You cannot have bodies in the package specifications. This is a difficult
> problem, since present construction model does not support deferred
> initialization. In short, you cannot have this in a single package.
OK. I had though the example was an exact extract from the real thing.

So indeed, if the variable is to be in a spec, it needs two packages, one  
containing the function, and one containing the variable, so that one  
package -- the one containing the function -- can be elaborated before the  
other -- containing the variable. A child package would be a good choice  
to hold that variable.


-- 
There is even better than a pragma Assert: a SPARK --# check.
--# check C and WhoKnowWhat and YouKnowWho;
--# assert Ada;
--  i.e. forget about previous premises which leads to conclusion
--  and start with new conclusion as premise.



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

* Re: Dynamically tagged expression not allowed. Why?
  2010-06-03  2:36   ` Yannick Duchêne (Hibou57)
  2010-06-03  7:57     ` Dmitry A. Kazakov
@ 2010-06-03 16:03     ` Adam Beneschan
  1 sibling, 0 replies; 10+ messages in thread
From: Adam Beneschan @ 2010-06-03 16:03 UTC (permalink / raw)


On Jun 2, 7:36 pm, Yannick Duchêne (Hibou57)
<yannick_duch...@yahoo.fr> wrote:
> Le Wed, 02 Jun 2010 01:36:17 +0200, Randy Brukardt <ra...@rrsoftware.com>  
> a écrit:> You have to explicitly use a
> > type conversion here:
>
> >     Conn : Class_Type := Class_Type (New_Class_Instance);
>
> This one is not legal, as Class_Type is limited and conversion are not  
> allowed on limited type due to their copy based semantic.
> [ARM 2005 4.6] says about type conversions
> “Neither the target type nor the operand type shall be limited”

Umm, no, that sentence (4.6(24.7)) applies only to array types.  (And,
I think, only in cases where there is no common ancestor of the
operand and target type.)  However, 7.5(2.1-2.2) makes it illegal.
Type conversions on limited types are allowed in some cases; e.g. if
T1 is a limited tagged type, and T2 is a type extension, and X2 is an
object of type T2, you can use T1(X2) as an actual parameter to a
procedure that takes an IN OUT parameter of type T1.  This is a view
conversion and doesn't involve a copy.

                               -- Adam



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

* Re: Dynamically tagged expression not allowed. Why?
  2010-06-01 23:36 ` Randy Brukardt
  2010-06-03  2:36   ` Yannick Duchêne (Hibou57)
@ 2010-06-05 18:47   ` Marc A. Criley
  1 sibling, 0 replies; 10+ messages in thread
From: Marc A. Criley @ 2010-06-05 18:47 UTC (permalink / raw)


On 06/01/2010 06:36 PM, Randy Brukardt wrote:
> "Marc A. Criley"<mcNOSPAM@mckae.com>  wrote in message
> news:c2ead$4c0150a0$4ca4a823$11809@API-DIGITAL.COM...
> ...
>> Stripping out a test case, I see that it has nothing to with the C++
>> binding per se, but it's an Ada issue that's flummoxing me.  Here's the
>> test code:
>>
>> procedure Dyty_Test is
>>
>>     type Class_Type is tagged limited record
>>        null;
>>     end record;
>>
>>     function New_Class_Instance return Class_Type'Class;
>>
>>     Conn : Class_Type := New_Class_Instance;
>
> This is illegal because the function returns a class-wide object and you are
> assigning it into an object of a specific type. You have to explicitly use a
> type conversion here:
>
>      Conn : Class_Type := Class_Type (New_Class_Instance);
>
> to specify that you want to truncate the returned object, or make the object
> classwide:
>
>     Conn : Class_Type'Class := New_Class_Instance;
>
> But notice that while both of these are legal, they'll both raise
> Program_Error because an access-before-elaboration error (the body of
> New_Class_Instance hasn't been elaborated at the point of this call).

Actually, stripping out the C++ interface pragmas was probably a bad 
idea on my part. (Though the thread *was* educational :-)

I thought that to create an instance of the C++ class I had to invoke 
the New_Class_Instance function myself, from which arose this issue. 
Turns out I don't. GNAT's handling of the C++ pragmas does it all for me 
automagically.

The documentation on creation an Ada binding to C++ is somewhat...terse 
when it comes to describing the mechanics of what is going on "under the 
hood", from whence came my misunderstanding.

So this part is all better now, I can step in and verify that my 
constructors are being executed. I'm having other problems, but that's 
just the usual banging the head against the wall stuff.

Marc A. Criley
www.mckae.com



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

end of thread, other threads:[~2010-06-05 18:47 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-29 17:36 Dynamically tagged expression not allowed. Why? Marc A. Criley
2010-05-29 18:23 ` Dmitry A. Kazakov
2010-06-03  2:37   ` Yannick Duchêne (Hibou57)
2010-06-03  7:48     ` Dmitry A. Kazakov
2010-06-01 23:36 ` Randy Brukardt
2010-06-03  2:36   ` Yannick Duchêne (Hibou57)
2010-06-03  7:57     ` Dmitry A. Kazakov
2010-06-03  8:21       ` Yannick Duchêne (Hibou57)
2010-06-03 16:03     ` Adam Beneschan
2010-06-05 18:47   ` Marc A. Criley

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