comp.lang.ada
 help / color / mirror / Atom feed
* Dynamic redispatching
@ 2000-01-18  0:00 Ted Dennison
  2000-01-18  0:00 ` Ray Blaak
  0 siblings, 1 reply; 5+ messages in thread
From: Ted Dennison @ 2000-01-18  0:00 UTC (permalink / raw)


There's something about classwide programming I'm just not getting, and
I was hoping some of you experts here could help enlighten me.

I'm trying to write a classwide function that dynamicly redispatches
based on the tag of the function result. But it isn't dispatching on
either of the two Ada compilers I tried. Here's an example:

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

   function Dispatch return Instance;

   function Main_Dispatcher return Class;
end P1;

with Ada.Text_IO;

package body P1 is
   function Dispatch return Instance is
      Result : Instance;
   begin
      Ada.Text_IO.Put_Line ("P1 Dispatch");
      return Result;
   end Dispatch;

   function Main_Dispatcher return Class is
   begin
      return Dispatch;
   end Main_Dispatcher;
end P1;

But it appears that rather than dynamicly dispatching based on the
return type of Main_Dispatcher, it just always calls P1.Dispatch. IOW:

with P1;
package P2 is
   type Instance is new P1.Instance with null record;
   subtype Class is Instance'Class;
   type Handle is access all Class;

   function Dispatch return Instance;
end P2;

with Ada.Text_IO;
package body P2 is
   function Dispatch return Instance is
      Result : Instance;
   begin
      Ada.Text_IO.Put_Line ("P2 Dispatch");
      return Result;
   end Dispatch;
end P2;

with P1;
with P2;
procedure Test is
   Item : P1.Handle := new P2.Instance;
begin
   Item.all := P1.Main_Dispatcher;
end Test;

When I run Test, of course I want it to dispatch to P2.Dispatch and
return a value of type P2.Instance. Instead what happens is that it
dispatches to P1.Dispatch, prints "P1 Dispatch", then raises constraint
error because Item.all's tag doesn't match that of the return value.

I'd like to know exactly why it is doing this, and if there's any way to
get it to get the classwide function to properly redispatch.

--
T.E.D.

http://www.telepath.com/~dennison/Ted/TED.html


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




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

* Re: Dynamic redispatching
  2000-01-18  0:00 Dynamic redispatching Ted Dennison
@ 2000-01-18  0:00 ` Ray Blaak
  2000-01-19  0:00   ` Ted Dennison
  0 siblings, 1 reply; 5+ messages in thread
From: Ray Blaak @ 2000-01-18  0:00 UTC (permalink / raw)


Ted Dennison <dennison@telepath.com> writes:
> I'm trying to write a classwide function that dynamicly redispatches
> based on the tag of the function result. But it isn't dispatching on
> either of the two Ada compilers I tried. Here's an example:
[...]
>    function Main_Dispatcher return Class is
>    begin
>       return Dispatch;
>    end Main_Dispatcher;
[...]
> procedure Test is
>    Item : P1.Handle := new P2.Instance;
> begin
>    Item.all := P1.Main_Dispatcher;
> end Test;
> 
> When I run Test, of course I want it to dispatch to P2.Dispatch and
> return a value of type P2.Instance.

The problem is that you need an object to dispatch on. There is no information
inside Main_Dispatcher to decide which Dispatch to call, since by the time the
object is returned, it is too late (or more accurately, you are specifying only
to call P1.Dispatch).

In the statement "Item.all := P1.Main_Dispatcher", the contents of Item are
irrelevant, since only Main_Dispatcher can be called. Inside Main_Dispatcher,
no information about the result destination is known.

Perhaps this would work:

   Item.all := P1.Dispatch;

For then we have a function with a controlling result (I think), and it should
thus use the context (the tag of the destination) to dispatch.

I think the main problem was that Main_Dispatcher is not a primitive operation
of P1.Instance

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
blaak@infomatch.com                            The Rhythm has my soul.




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

* Re: Dynamic redispatching
  2000-01-18  0:00 ` Ray Blaak
@ 2000-01-19  0:00   ` Ted Dennison
  2000-01-20  0:00     ` Tucker Taft
  0 siblings, 1 reply; 5+ messages in thread
From: Ted Dennison @ 2000-01-19  0:00 UTC (permalink / raw)


In article <m3hfgazg42.fsf@baka.infomatch.bc.ca>,
  Ray Blaak <blaak@infomatch.com> wrote:
> Perhaps this would work:
>
>    Item.all := P1.Dispatch;

Yes, that would work for the example I gave. However, it won't for this
example (which is closer to what I'm trying to do):

package P1 is

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

   function Dispatch return Instance;
   function Main_Dispatcher return Class;

   type Dispatcher_Routine is access function return Class;
   Default_Dispatcher : Dispatcher_Routine := Main_Dispatcher'access;
end P1;

with P1;
with P2;

procedure Test is

   Item : P1.Handle := new P2.Instance;
begin
   Item.all := P1.Default_Dispatcher.all;
end Test;

IOW: I want to be able to supply function pointers that dispatch. Making
the type an "access function return Instance" doesn't work, because
P2.Dispatch'access isn't compatable with that type (P1.Instance and
P2.Instance are different types). So I tried making it classwide. That
works, except that the classwide function for some reason can't
redispatch to the appropriate primitive function.

Is this just a limitation of functions in Ada? Would changing everything
to procedures with "out" parameters solve the problem?

--
T.E.D.

http://www.telepath.com/~dennison/Ted/TED.html


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




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

* Re: Dynamic redispatching
  2000-01-20  0:00     ` Tucker Taft
@ 2000-01-20  0:00       ` Ted Dennison
  0 siblings, 0 replies; 5+ messages in thread
From: Ted Dennison @ 2000-01-20  0:00 UTC (permalink / raw)


In article <38875677.950A6FCA@averstar.com>,
  Tucker Taft <stt@averstar.com> wrote:

> You are trying to make this dispatching-on-result happen in a "return"
> statement, but at that point, there is no context from which to get
> the tag to control the dispatching.

I was figuring it would take the tag of the ultimate object transitively
through return calls. I guess not. :-(

> However, returning composite objects as results is generally less
> efficient than using OUT parameters (because OUT parameters can use
> pass-by-reference). So unless there is some compelling reason for
> these to be functions (such as they have discriminants whose value is
> not known to the caller, or they will often be combined with other
> function calls in the middle of a more complex expression), you might
> want to make them all procedures.

There isn't, so I am doing just that. Thanks.

--
T.E.D.

http://www.telepath.com/~dennison/Ted/TED.html


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




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

* Re: Dynamic redispatching
  2000-01-19  0:00   ` Ted Dennison
@ 2000-01-20  0:00     ` Tucker Taft
  2000-01-20  0:00       ` Ted Dennison
  0 siblings, 1 reply; 5+ messages in thread
From: Tucker Taft @ 2000-01-20  0:00 UTC (permalink / raw)


Ted Dennison wrote:
> 
> In article <m3hfgazg42.fsf@baka.infomatch.bc.ca>,
>   Ray Blaak <blaak@infomatch.com> wrote:
> > Perhaps this would work:
> >
> >    Item.all := P1.Dispatch;
> 
> Yes, that would work for the example I gave. However, it won't for this
> example (which is closer to what I'm trying to do):
> 
> package P1 is
> 
>    type Instance is tagged null record;
>    subtype Class is Instance'Class;
>    type Handle is access all Class;
> 
>    function Dispatch return Instance;
>    function Main_Dispatcher return Class;
> 
>    type Dispatcher_Routine is access function return Class;
>    Default_Dispatcher : Dispatcher_Routine := Main_Dispatcher'access;
> end P1;
> 
> with P1;
> with P2;
> 
> procedure Test is
> 
>    Item : P1.Handle := new P2.Instance;
> begin
>    Item.all := P1.Default_Dispatcher.all;
> end Test;
> 
> IOW: I want to be able to supply function pointers that dispatch. Making
> the type an "access function return Instance" doesn't work, because
> P2.Dispatch'access isn't compatable with that type (P1.Instance and
> P2.Instance are different types). So I tried making it classwide. That
> works, except that the classwide function for some reason can't
> redispatch to the appropriate primitive function.
> 
> Is this just a limitation of functions in Ada? 

Well, that's a bit of a funny way to put it.  Ada is the only OO language
that does dispatching on result, by using context.  This is analogous
to the fact that Ada is one of the few languages that does overloading
on result type.  Dispatching on result is sort of like run-time overload
resolution.  However, for it to work, there must be *some* object with
a tag around for the compiler to use to control the dispatching.
Normally this would be the object that is the target of an assignment,
or another parameter in a subprogram call with multiple controlling operands.

You are trying to make this dispatching-on-result happen in a "return"
statement, but at that point, there is no context from which to get
the tag to control the dispatching.

> ... Would changing everything
> to procedures with "out" parameters solve the problem?

You don't have to change "everything," but you will probably have
to change the Main_Dispatcher into a procedure, and change the
Dispatcher_Routine into an access-to-procedure.  You can leave the
individual Dispatcher's as functions that dispatch on result.
However, returning composite objects as results is generally less efficient
than using OUT parameters (because OUT parameters can use pass-by-reference).
So unless there is some compelling reason for these to be functions
(such as they have discriminants whose value is not known to the caller,
or they will often be combined with other function calls in the middle of
a more complex expression), you might want to make them all procedures.

> 
> --
> T.E.D.
> 
> http://www.telepath.com/~dennison/Ted/TED.html
> 
> Sent via Deja.com http://www.deja.com/
> Before you buy.

-- 
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA




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

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

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-01-18  0:00 Dynamic redispatching Ted Dennison
2000-01-18  0:00 ` Ray Blaak
2000-01-19  0:00   ` Ted Dennison
2000-01-20  0:00     ` Tucker Taft
2000-01-20  0:00       ` Ted Dennison

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