comp.lang.ada
 help / color / mirror / Atom feed
* how do i implement double-dispatching?
@ 2003-12-17 18:08 cl1motorsports
  2003-12-18  2:17 ` Stephen Leake
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: cl1motorsports @ 2003-12-17 18:08 UTC (permalink / raw)


I'm trying to implement double dispatching with a visitor pattern in (of
course) Ada. I have a parse tree package that has all the node types of
the tree, and i have a visitor package with an abstract visitor type that
has a Visit operation for all the types in the parse tree. It doesn't want
to compile the way i have it written. I have provided a shortened version
of the parse tree and abstract visitor code with gnatmake errors below. If
anyone has a solution to this please point me in the correct direction. My
purpose here is to implement a framework for pretty-printers, html-izers,
language translators (e.g c2ada) all from the same parse tree without
having to recompile the parse tree. basically the framework user will
create a new type that inherits from the abstract visitor type to insure
that operations for each type of node in the parse tree are implemented.
Just thought i would give some background info on the code so you would
know why i tried to implement it like this and so you could give a
solution within the domain. well enough ranting, On to the Code!!!

-- parse_tree_pkg.ads

with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
package Parse_Tree_Pkg is

   -- abstract parse tree node
   type Parse_Tree_Node_Record is abstract tagged
      record
         Start_Line   : Integer;
         Start_Column : Integer;
         End_Line     : Integer;
         End_Column   : Integer;
      end record;
   type Parse_Tree_Node is access Parse_Tree_Node_Record'Class;

   -- actual(concrete) parse tree nodes
   type Equal_Op is new Parse_Tree_Node_Record with null record;

   type Number_Node is new Parse_Tree_Node_Record with
      record
         Value : Float;
      end record;

   type Name_Node is new Parse_Tree_Node_Record with
      record
         Value : Unbounded_String;
      end record;


   type Assignment_Node is new Parse_Tree_Node_Record with
      record
         Name       : Parse_Tree_Node;
         Equal      : Parse_Tree_Node;
         Expression : Parse_Tree_Node;
      end record;

end Parse_Tree_Pkg;





-- abstract_visitor.ads

with Parse_Tree_Pkg; use Parse_Tree_Pkg;
package Abstract_Visitor is
   -- This package provides a visitor interface
   -- so that operations can be created independant
   -- of the parse tree.
   -- If you want to implement a visitor to run
   -- operations on the parse tree you must "with" this
   -- package and create all the visit operations in
   -- it.

   type Visitor_Record is abstract tagged null record;
   type Visitor_Access is access Visitor_Record'Class;

   procedure Visit(V : in out Visitor_Record; Node : in Equal_Op) is abstract;


   procedure Visit(V : in out Visitor_Record; Node : in Number_Node) is abstract;
   procedure Visit(V : in out Visitor_Record; Node : in Name_Node) is abstract;


   procedure Visit(V : in out Visitor_Record; Node : in Assignment_Node) is abstract;

   procedure Accept_Visitor(V : in out Visitor_Record'Class; Node : in Parse_Tree_Node_Record'Class);
end Abstract_Visitor;

-- abstract_visitor.adb

package body Abstract_Visitor is

   procedure Accept_Visitor(V : in out Visitor_Record'Class; Node : in Parse_Tree_Node_Record'Class) is
   begin
      Visit(V, Node);
   end Accept_Visitor;

end Abstract_Visitor;

-- END OF CODE

and here are the errors from running gnatmake:

$ gnatmake abstract_visitor
gcc -c abstract_visitor.adb
abstract_visitor.adb:5:07: invalid parameter list in call (use -gnatf for details)
gnatmake: "abstract_visitor.adb" compilation error
$ gnatmake -gnatf abstract_visitor
gcc -c -gnatf abstract_visitor.adb
abstract_visitor.adb:5:07: no candidate interpretations match the actuals:
abstract_visitor.adb:5:16: expected type "Assignment_Node" defined at parse_tree_pkg.ads:28
abstract_visitor.adb:5:16: found type "Parse_Tree_Node_Record'Class" defined at parse_tree_pkg.ads:5
abstract_visitor.adb:5:16:   ==> in call to "Visit" at abstract_visitor.ads:24
abstract_visitor.adb:5:16:   ==> in call to "Visit" at abstract_visitor.ads:21
abstract_visitor.adb:5:16:   ==> in call to "Visit" at abstract_visitor.ads:20
abstract_visitor.adb:5:16:   ==> in call to "Visit" at abstract_visitor.ads:17
gnatmake: "abstract_visitor.adb" compilation error
$

this has been really frustrating :/

oh and this is my first post ever to a newsgroup so be gentle :)

Thanks in Advance,
Charles




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

* Re: how do i implement double-dispatching?
  2003-12-17 18:08 how do i implement double-dispatching? cl1motorsports
@ 2003-12-18  2:17 ` Stephen Leake
  2003-12-18  9:48 ` Dmitry A. Kazakov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 15+ messages in thread
From: Stephen Leake @ 2003-12-18  2:17 UTC (permalink / raw)
  To: cl1motorsports; +Cc: comp.lang.ada

cl1motorsports <cwlambert76@yahoo.com> writes:

> I'm trying to implement double dispatching with a visitor pattern in (of
> course) Ada. 

Ok, good choice :).

> I have a parse tree package that has all the node types of the tree,
> and i have a visitor package with an abstract visitor type that has
> a Visit operation for all the types in the parse tree. It doesn't
> want to compile the way i have it written. 

To be dispatching, an operation must be declared in the same package
as the tagged type.

In general, double dispatching must be done in two steps; first
dispatch on one parameter, then, within that routine, dispatch on the
other parameter. This allows both parameters to control what goes on.

There is no way in general to dispatch on two parameters at once; how
can the compiler know that all combinations have been provided?

For your particular problem, I think the best idea is to abandon the
idea of dispatching on the concrete parse_tree_node type. Instead,
define one output routine that might be needed for each concrete node
type, but have it dispatch on the Visitor type (HTML, Ada
pretty-print, etc). Then in the tree traversal subprogram, use a case
statement to call the appropriate output routine, dispatching on
Vistor.

A case statement is appropriate here, because the syntax of the input
language is known at compile time, and therefore you can have an
enumeration of node types.

Hmm. I would start this project by using OpenToken
(http://www.telepath.com/~dennison/Ted/OpenToken/OpenToken.html). That
would lead to a set of packages defining the input grammar, with
bodies that need to call output routines. The token types could take a
discriminant for Visitor, so the output calls can be dispatching. That
will have an enumeration of nodes, but not an explicit case statement.
You should look into OpenToken; it's a great system. Feel free to
email me with support questions (Ted's pretty busy these days).

In your structure, that would be something like:

type Visitor_Record is abstract tagged null record;

type Parse_Tree_Node_Record (Visitor : access visitor_Record) is
abstract tagged record ... end record;

Note that it's ok to define Vistor_Record and Parse_Tree_node_Record
in the same package; there's not much point to having a parse tree
without a way to visit it.

Hope this helps.

> oh and this is my first post ever to a newsgroup so be gentle :)

Congratulations :). Nice to have a Real Ada Question :).

-- 
-- Stephe




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

* Re: how do i implement double-dispatching?
  2003-12-17 18:08 how do i implement double-dispatching? cl1motorsports
  2003-12-18  2:17 ` Stephen Leake
@ 2003-12-18  9:48 ` Dmitry A. Kazakov
  2003-12-18 15:13 ` Martin Krischik
  2003-12-20  6:27 ` cl1motorsports
  3 siblings, 0 replies; 15+ messages in thread
From: Dmitry A. Kazakov @ 2003-12-18  9:48 UTC (permalink / raw)


cl1motorsports wrote:

> I'm trying to implement double dispatching with a visitor pattern in (of
> course) Ada. I have a parse tree package that has all the node types of
> the tree, and i have a visitor package with an abstract visitor type that
> has a Visit operation for all the types in the parse tree. It doesn't want
> to compile the way i have it written. I have provided a shortened version
> of the parse tree and abstract visitor code with gnatmake errors below. If
> anyone has a solution to this please point me in the correct direction. My
> purpose here is to implement a framework for pretty-printers, html-izers,
> language translators (e.g c2ada) all from the same parse tree without
> having to recompile the parse tree. basically the framework user will
> create a new type that inherits from the abstract visitor type to insure
> that operations for each type of node in the parse tree are implemented.
> Just thought i would give some background info on the code so you would
> know why i tried to implement it like this and so you could give a
> solution within the domain. well enough ranting, On to the Code!!!
> 
> -- parse_tree_pkg.ads
> 
> with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
> package Parse_Tree_Pkg is
> 
>    -- abstract parse tree node
>    type Parse_Tree_Node_Record is abstract tagged
>       record
>          Start_Line   : Integer;
>          Start_Column : Integer;
>          End_Line     : Integer;
>          End_Column   : Integer;
>       end record;
>    type Parse_Tree_Node is access Parse_Tree_Node_Record'Class;
> 
>    -- actual(concrete) parse tree nodes
>    type Equal_Op is new Parse_Tree_Node_Record with null record;
> 
>    type Number_Node is new Parse_Tree_Node_Record with
>       record
>          Value : Float;
>       end record;
> 
>    type Name_Node is new Parse_Tree_Node_Record with
>       record
>          Value : Unbounded_String;
>       end record;
> 
>    type Assignment_Node is new Parse_Tree_Node_Record with
>       record
>          Name       : Parse_Tree_Node;
>          Equal      : Parse_Tree_Node;
>          Expression : Parse_Tree_Node;
>       end record;
> 
> end Parse_Tree_Pkg;
> 
> -- abstract_visitor.ads
> 
> with Parse_Tree_Pkg; use Parse_Tree_Pkg;
> package Abstract_Visitor is
>    -- This package provides a visitor interface
>    -- so that operations can be created independant
>    -- of the parse tree.
>    -- If you want to implement a visitor to run
>    -- operations on the parse tree you must "with" this
>    -- package and create all the visit operations in
>    -- it.
> 
>    type Visitor_Record is abstract tagged null record;
>    type Visitor_Access is access Visitor_Record'Class;
> 
>    procedure Visit(V : in out Visitor_Record; Node : in Equal_Op) is
>    abstract;

procedure Visit
          (  V    : in out Visitor_Record;
             Node : Parse_Tree_Node_Record'Class
          )  is abstract;

Ada has a restricted form of multiple dispatch, which cannot be applied in
your case. So Visit has to be dispatching in only one parameter. An
implementation of Visit in a derived visitor type has to emulate dispatch
on the second parameter:

type My_Fashioned_Visitor is new Visitor_Record with private;
procedure Visit
          (  V    : in out My_Fashioned_Visitor;
             Node : Parse_Tree_Node_Record'Class
          )  is
begin
   if Node in Equal_Op'Class then
      -- Visiting Equal_Op or its derivate
      ...
   elsif Node in Number_Node'Class then
      ...
   elsif Node in Name_Node'Class then
      ...
   elsif Node in Assignment_Node'Class then
      ...
   else
      raise Constraint_Error; -- Who knows this Node?
   end if;
end Visit;

When the number of different nodes is known it is OK.

Note that there is a choice, you can make Visit dispatching in the Node
parameter:

with Abstract_Visitor;
...
type Parse_Tree_Node_Record is abstract ...;
procedure Visit
          (  V    : in out Visitor_Record'Class;
             Node : Parse_Tree_Node_Record
          )  is abstract;

Each node will override Visit to define what should be done with it when
visited. Which way is better depends on which type is expected to be
extended at most.

In general case there is no solution for this problem, because dispatching
operation is fundamentally different from a class-wide (generic) one. So
any solution that substitutes one for another (i.e. when one of the
arguments becomes class-wide) is inherently insufficient. Fortunaltely in
many cases one can foresee the number of types involved or break a
dispatching operation down into a set of other operations so that it could
be replaced with a class-wide one.

-- 
Regards,
Dmitry A. Kazakov
www.dmitry-kazakov.de



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

* Re: how do i implement double-dispatching?
  2003-12-17 18:08 how do i implement double-dispatching? cl1motorsports
  2003-12-18  2:17 ` Stephen Leake
  2003-12-18  9:48 ` Dmitry A. Kazakov
@ 2003-12-18 15:13 ` Martin Krischik
  2003-12-20  6:27 ` cl1motorsports
  3 siblings, 0 replies; 15+ messages in thread
From: Martin Krischik @ 2003-12-18 15:13 UTC (permalink / raw)


cl1motorsports wrote:

Havn't got much time but you might like to try:

>    procedure Accept_Visitor(V : in out Visitor_Record'Class; Node : in
>    Parse_Tree_Node_Record'Class);

procedure Accept_Visitor(V : in out Visitor_Record; Node : in
Parse_Tree_Node_Record'Class);

> end Abstract_Visitor;
> 
> -- abstract_visitor.adb
> 
> package body Abstract_Visitor is
> 
>    procedure Accept_Visitor(V : in out Visitor_Record'Class; Node : in
>    Parse_Tree_Node_Record'Class) is begin

procedure Accept_Visitor(V : in out Visitor_Record; Node : in
Parse_Tree_Node_Record'Class) is 

V_C : Visitor_Record'Class    renames Visitor_Record'Class (V);

begin

>       Visit(V, Node);

Visit(V_C, Node);

>    end Accept_Visitor;
> 
> end Abstract_Visitor;


With Regards


Martin
-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com




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

* Re: how do i implement double-dispatching?
  2003-12-17 18:08 how do i implement double-dispatching? cl1motorsports
                   ` (2 preceding siblings ...)
  2003-12-18 15:13 ` Martin Krischik
@ 2003-12-20  6:27 ` cl1motorsports
  2003-12-20  9:56   ` Martin Krischik
  2003-12-22 21:41   ` cl1motorsports
  3 siblings, 2 replies; 15+ messages in thread
From: cl1motorsports @ 2003-12-20  6:27 UTC (permalink / raw)


On Wed, 17 Dec 2003 12:08:41 -0600, cl1motorsports wrote:
<snip>
> package body Abstract_Visitor is
> 
>    procedure Accept_Visitor(V : in out Visitor_Record'Class; Node : in Parse_Tree_Node_Record'Class) is
>    begin
>       Visit(V, Node);
>    end Accept_Visitor;
> 
> end Abstract_Visitor;
> 
> -- END OF CODE
<snip>

thanks for all of your suggestions. after careful consideration i decided
to change the above Accept_Visitor procedure to:

procedure Accept_Vistor(V:in out Visitor_Record'Class; Node : in Parse_Tree_Node_Record'Class) is
begin
  if Node in Equal_Op'Class then
	Visit(V, Equal_Op(Node));
  elsif Node in Number_Node'Class then
	Visit(V, Number_Node(Node));
  ...
  end if;
end Accept_Visitor;

now it only dynamically dispatches on the Visitor_Record'Class and the
Node parameter is determined at compile time. I don't think i would have
figured that out by myself (at least not at this point in time).

and just to let y'all know. I'm trying to write a C to Ada translator. The
first task on my list is to handle #define statements. I'm sure this
should be in another thread if a topic gets started on this. But I thought
it would be nice to let y'all know what you were helping me with here.

Thanks again everyone 

[:^)



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

* Re: how do i implement double-dispatching?
  2003-12-20  6:27 ` cl1motorsports
@ 2003-12-20  9:56   ` Martin Krischik
  2003-12-20 17:00     ` cl1motorsports
  2003-12-22 21:41   ` cl1motorsports
  1 sibling, 1 reply; 15+ messages in thread
From: Martin Krischik @ 2003-12-20  9:56 UTC (permalink / raw)


cl1motorsports wrote:

> and just to let y'all know. I'm trying to write a C to Ada translator. The
> first task on my list is to handle #define statements. I'm sure this
> should be in another thread if a topic gets started on this. But I thought
> it would be nice to let y'all know what you were helping me with here.

Have you considered to send the C file thrue the C preprocessors and convert
the output? #if #define etc. pp. will be cone by then.

With Regards

Martin

-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com




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

* Re: how do i implement double-dispatching?
  2003-12-20  9:56   ` Martin Krischik
@ 2003-12-20 17:00     ` cl1motorsports
  2003-12-21 13:39       ` Stephen Leake
  0 siblings, 1 reply; 15+ messages in thread
From: cl1motorsports @ 2003-12-20 17:00 UTC (permalink / raw)


On Sat, 20 Dec 2003 10:56:07 +0100, Martin Krischik wrote:

> cl1motorsports wrote:
> 
>> and just to let y'all know. I'm trying to write a C to Ada translator. The
>> first task on my list is to handle #define statements. I'm sure this
>> should be in another thread if a topic gets started on this. But I thought
>> it would be nice to let y'all know what you were helping me with here.
> 
> Have you considered to send the C file thrue the C preprocessors and convert
> the output? #if #define etc. pp. will be cone by then.

What's the fun in that? Seriously though, the most common preprocessor is
the one that comes with gcc, and it puts alot of non standard C stuff in
its output. That is one reason I didn't want to do that. Another reason is
because some people may want to convert a whole project and want to keep
the preprocessed code. I already have some ideas on this

#define FOO
Foo : constant Boolean := True

#define FOO "i'm a string"
Foo : constant String(1..12") := "i'm a string";

#define FOO 12
Foo : constant := 12;

#define MAX(a,b) (a < b) b ? a;
generic
	type blah is <>;
function Max(a : blah; b : blah) return blah is
begin
	if (a < b) then
		return b;
	else
		return a;
	end if;
end Max;
function 

that's just a few examples. I also want to use the define statements to be
able to produce generic packages. I've got a direct conversion for most
types of #define statements (i think) except ones with the stringize and
concatination operators, and the ones that are just down right messy
(garbage in garbage out). Right now i'm just trying to work out a
framework for accomplishing this because i would also like to make some
other tools (maybe converters from other languages). I don't want ada to
die. And if there were converters from other langauges that would be a
start. Having common API's would be another great place. I think this tool
would make that easier as well (ala cbind style). i'm still in the
preliminary stages of this. However, I think with this one project i could 
take the information that i learn from it and apply it to several other
development tools, and that would put ada code directly in the programmers
hands.

> 
> With Regards
> 
> Martin




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

* Re: how do i implement double-dispatching?
  2003-12-20 17:00     ` cl1motorsports
@ 2003-12-21 13:39       ` Stephen Leake
  2003-12-21 17:40         ` cl1motorsports
  0 siblings, 1 reply; 15+ messages in thread
From: Stephen Leake @ 2003-12-21 13:39 UTC (permalink / raw)
  To: cl1motorsports; +Cc: comp.lang.ada

cl1motorsports <cwlambert76@yahoo.com> writes:

> On Sat, 20 Dec 2003 10:56:07 +0100, Martin Krischik wrote:
> 
> > Have you considered to send the C file thrue the C preprocessors
> > and convert the output? #if #define etc. pp. will be cone by then.
> 
> What's the fun in that? Seriously though, the most common preprocessor is
> the one that comes with gcc, and it puts alot of non standard C stuff in
> its output. 

Hmm. I never noticed anything that was not in the ANSI C standard. Are
you sure it is truly not in that standard? Or is it just something you
are not familiar with? In any case, you can disable any non-standard
stuff by specifying -ansi.

> That is one reason I didn't want to do that. Another reason is
> because some people may want to convert a whole project and want to
> keep the preprocessed code. 

I think you mean "translate the preprocessor statements into Ada, to
preserve structure". That is a good idea.

> I already have some ideas on this
> 
> #define FOO
> Foo : constant Boolean := True
> 
> #define FOO "i'm a string"
> Foo : constant String(1..12") := "i'm a string";
> 
> #define FOO 12
> Foo : constant := 12;
> 
> #define MAX(a,b) (a < b) b ? a;
> generic
> 	type blah is <>;
> function Max(a : blah; b : blah) return blah is
> begin
> 	if (a < b) then
> 		return b;
> 	else
> 		return a;
> 	end if;
> end Max;
> function 
> 
> that's just a few examples. 

This will work for many common uses of the preprocessor. Of course, it
will not be possible for _all_ uses of the preprocessor. But then your
translator can either run the C preprocessor and use the output, or
issue an error about untranslatable code.

> I also want to use the define statements to be able to produce
> generic packages. I've got a direct conversion for most types of
> #define statements (i think) except ones with the stringize and
> concatination operators, and the ones that are just down right messy
> (garbage in garbage out). 

Right. Those should be re-written anyway :).

-- 
-- Stephe




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

* Re: how do i implement double-dispatching?
  2003-12-21 13:39       ` Stephen Leake
@ 2003-12-21 17:40         ` cl1motorsports
  2003-12-22 22:47           ` Stephen Leake
  0 siblings, 1 reply; 15+ messages in thread
From: cl1motorsports @ 2003-12-21 17:40 UTC (permalink / raw)


On Sun, 21 Dec 2003 08:39:59 -0500, Stephen Leake wrote:

> cl1motorsports <cwlambert76@yahoo.com> writes:
> 
>> On Sat, 20 Dec 2003 10:56:07 +0100, Martin Krischik wrote:
>> 
>> > Have you considered to send the C file thrue the C preprocessors
>> > and convert the output? #if #define etc. pp. will be cone by then.
>> 
>> What's the fun in that? Seriously though, the most common preprocessor is
>> the one that comes with gcc, and it puts alot of non standard C stuff in
>> its output. 
> 
> Hmm. I never noticed anything that was not in the ANSI C standard. Are
> you sure it is truly not in that standard? Or is it just something you
> are not familiar with? In any case, you can disable any non-standard
> stuff by specifying -ansi.

extern int vsnprintf (char *   __s, size_t __maxlen,
		      __const char *   __format, __gnuc_va_list  __arg)
       __attribute__ ((__format__ (__printf__, 3, 0)));

the __attribute__ keyword gets processed even when -ansi is used. But from
what i can tell, that is only used in the system header files. I mean it
is not created by the preprocessor. I have a newer version of GCC since i
last checked this. so maybe it was only in one version or something like
that *shrugs*.
>
>> That is one reason I didn't want to do that. Another reason is because
>> some people may want to convert a whole project and want to keep the
>> preprocessed code.
> 
> I think you mean "translate the preprocessor statements into Ada, to
> preserve structure". That is a good idea.

yes that's exactly what i meant. I also want a user to be able to select
any given #define statement in the C code and specify how that statement
is translated. This will help when the default choice chosen by the
translator is ambiguous or not what the user intended.

>
>> I already have some ideas on this
>> 
>> #define FOO
>> Foo : constant Boolean := True
>> 
>> #define FOO "i'm a string"
>> Foo : constant String(1..12") := "i'm a string";
>> 
>> #define FOO 12
>> Foo : constant := 12;
>> 
>> #define MAX(a,b) (a < b) b ? a;
>> generic
>> 	type blah is <>;
>> function Max(a : blah; b : blah) return blah is begin
>> 	if (a < b) then
>> 		return b;
>> 	else
>> 		return a;
>> 	end if;
>> end Max;
>> function
>> 
>> that's just a few examples.
> 
> This will work for many common uses of the preprocessor. Of course, it
> will not be possible for _all_ uses of the preprocessor. But then your
> translator can either run the C preprocessor and use the output, or
> issue an error about untranslatable code.

Actually i plan on having it preprocess the C code as a C preprocessor
normally would when the translator doesn't have a known way to convert the
#define statement to ada code directly.

> 
>> I also want to use the define statements to be able to produce generic
>> packages. I've got a direct conversion for most types of #define
>> statements (i think) except ones with the stringize and concatination
>> operators, and the ones that are just down right messy (garbage in
>> garbage out).
> 
> Right. Those should be re-written anyway :).




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

* Re: how do i implement double-dispatching?
  2003-12-20  6:27 ` cl1motorsports
  2003-12-20  9:56   ` Martin Krischik
@ 2003-12-22 21:41   ` cl1motorsports
  2003-12-22 21:47     ` cl1motorsports
  2003-12-22 22:49     ` Stephen Leake
  1 sibling, 2 replies; 15+ messages in thread
From: cl1motorsports @ 2003-12-22 21:41 UTC (permalink / raw)


> thanks for all of your suggestions. after careful consideration i decided
> to change the above Accept_Visitor procedure to:
> 
> procedure Accept_Vistor(V:in out Visitor_Record'Class; Node : in Parse_Tree_Node_Record'Class) is
> begin
>   if Node in Equal_Op'Class then
> 	Visit(V, Equal_Op(Node));
>   elsif Node in Number_Node'Class then
> 	Visit(V, Number_Node(Node));
>   ...
>   end if;
> end Accept_Visitor;
> 
> now it only dynamically dispatches on the Visitor_Record'Class and the
> Node parameter is determined at compile time. I don't think i would have
> figured that out by myself (at least not at this point in time).

Okay. now it works when the Visitor type, Visit() procedures and the
Accept_Visitor() procedure is in a separate package from the parse tree.
but when i try to combine the 2 into one package i get
an error about multiple dispatching on all of the Visit() procedures.
what is my scope issue with being in the same package that doesn't apply
to them being in 2 packages?

Charles



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

* Re: how do i implement double-dispatching?
  2003-12-22 21:41   ` cl1motorsports
@ 2003-12-22 21:47     ` cl1motorsports
  2003-12-23 11:03       ` Dmitry A. Kazakov
  2003-12-22 22:49     ` Stephen Leake
  1 sibling, 1 reply; 15+ messages in thread
From: cl1motorsports @ 2003-12-22 21:47 UTC (permalink / raw)


On Mon, 22 Dec 2003 16:41:52 -0500, cl1motorsports wrote:

>> thanks for all of your suggestions. after careful consideration i decided
>> to change the above Accept_Visitor procedure to:
>> 
>> procedure Accept_Vistor(V:in out Visitor_Record'Class; Node : in Parse_Tree_Node_Record'Class) is
>> begin
>>   if Node in Equal_Op'Class then
>> 	Visit(V, Equal_Op(Node));
>>   elsif Node in Number_Node'Class then
>> 	Visit(V, Number_Node(Node));
>>   ...
>>   end if;
>> end Accept_Visitor;
>> 
>> now it only dynamically dispatches on the Visitor_Record'Class and the
>> Node parameter is determined at compile time. I don't think i would have
>> figured that out by myself (at least not at this point in time).
> 
> Okay. now it works when the Visitor type, Visit() procedures and the
> Accept_Visitor() procedure is in a separate package from the parse tree.
> but when i try to combine the 2 into one package i get
> an error about multiple dispatching on all of the Visit() procedures.
> what is my scope issue with being in the same package that doesn't apply
> to them being in 2 packages?

oops!, A link to the source code would be helpful:
http://www.geocities.com/cwlambert76/all.html

> 
> Charles




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

* Re: how do i implement double-dispatching?
  2003-12-21 17:40         ` cl1motorsports
@ 2003-12-22 22:47           ` Stephen Leake
  0 siblings, 0 replies; 15+ messages in thread
From: Stephen Leake @ 2003-12-22 22:47 UTC (permalink / raw)
  To: cl1motorsports; +Cc: comp.lang.ada

cl1motorsports <cwlambert76@yahoo.com> writes:

> On Sun, 21 Dec 2003 08:39:59 -0500, Stephen Leake wrote:
> 
> > cl1motorsports <cwlambert76@yahoo.com> writes:
> > 
> >> Seriously though, the most common preprocessor is
> >> the one that comes with gcc, and it puts alot of non standard C stuff in
> >> its output. 
> > 
> > Hmm. I never noticed anything that was not in the ANSI C standard. Are
> > you sure it is truly not in that standard? Or is it just something you
> > are not familiar with? In any case, you can disable any non-standard
> > stuff by specifying -ansi.
> 
> extern int vsnprintf (char *   __s, size_t __maxlen,
> 		      __const char *   __format, __gnuc_va_list  __arg)
>        __attribute__ ((__format__ (__printf__, 3, 0)));

> the __attribute__ keyword gets processed even when -ansi is used.

By the compiler, true (although maybe not with -pedantic?). But we
were talking about the preprocessor; it just passes __attribute__
thru.

> But from what i can tell, that is only used in the system header
> files. I mean it is not created by the preprocessor. I have a newer
> version of GCC since i last checked this. so maybe it was only in
> one version or something like that *shrugs*.

Ok. So as far as you know, the gcc preprocessor is ANSI compliant.
That was my point.

-- 
-- Stephe




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

* Re: how do i implement double-dispatching?
  2003-12-22 21:41   ` cl1motorsports
  2003-12-22 21:47     ` cl1motorsports
@ 2003-12-22 22:49     ` Stephen Leake
  2003-12-22 23:04       ` cl1motorsports
  1 sibling, 1 reply; 15+ messages in thread
From: Stephen Leake @ 2003-12-22 22:49 UTC (permalink / raw)
  To: cl1motorsports; +Cc: comp.lang.ada

cl1motorsports <cwlambert76@yahoo.com> writes:

> Okay. now it works when the Visitor type, Visit() procedures and the
> Accept_Visitor() procedure is in a separate package from the parse tree.
> but when i try to combine the 2 into one package i get
> an error about multiple dispatching on all of the Visit() procedures.
> what is my scope issue with being in the same package that doesn't apply
> to them being in 2 packages?

In general, you will find that the Ada rules encourage putting things
in different packages. This is a Good Thing :).

Sometimes child packages work better.

-- 
-- Stephe




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

* Re: how do i implement double-dispatching?
  2003-12-22 22:49     ` Stephen Leake
@ 2003-12-22 23:04       ` cl1motorsports
  0 siblings, 0 replies; 15+ messages in thread
From: cl1motorsports @ 2003-12-22 23:04 UTC (permalink / raw)


On Mon, 22 Dec 2003 17:49:41 -0500, Stephen Leake wrote:

> cl1motorsports <cwlambert76@yahoo.com> writes:
> 
>> Okay. now it works when the Visitor type, Visit() procedures and the
>> Accept_Visitor() procedure is in a separate package from the parse tree.
>> but when i try to combine the 2 into one package i get
>> an error about multiple dispatching on all of the Visit() procedures.
>> what is my scope issue with being in the same package that doesn't apply
>> to them being in 2 packages?
> 
> In general, you will find that the Ada rules encourage putting things
> in different packages. This is a Good Thing :).
But in this case there is no point of having a visitor with out a tree to
visit or a parse tree with no visitor to run operations on it. Currently
to use this in a program i have to do this:

with Parse_Tree_Pkg; use Parse_Tree_Pkg;
with Abstract_Visitor_Pkg; use Abstract_Visitor_Pkg;
with Interpret_Tree; use Interpret_Tree;

a person using the interpret_Tree package having to know that it's
created from an abstract visitor package exposes implementation and that's
what I am trying to avoid. The user should only have to do:

with parse_tree_pkg; use parse_tree_pkg;
with Interpret_Tree; use interpret_Tree;

am i correct on this or am i missing something?


> 
> Sometimes child packages work better.




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

* Re: how do i implement double-dispatching?
  2003-12-22 21:47     ` cl1motorsports
@ 2003-12-23 11:03       ` Dmitry A. Kazakov
  0 siblings, 0 replies; 15+ messages in thread
From: Dmitry A. Kazakov @ 2003-12-23 11:03 UTC (permalink / raw)


cl1motorsports wrote:

> On Mon, 22 Dec 2003 16:41:52 -0500, cl1motorsports wrote:
> 
>>> thanks for all of your suggestions. after careful consideration i
>>> decided to change the above Accept_Visitor procedure to:
>>> 
>>> procedure Accept_Vistor(V:in out Visitor_Record'Class; Node : in
>>> Parse_Tree_Node_Record'Class) is begin
>>>   if Node in Equal_Op'Class then
>>> Visit(V, Equal_Op(Node));
>>>   elsif Node in Number_Node'Class then
>>> Visit(V, Number_Node(Node));
>>>   ...
>>>   end if;
>>> end Accept_Visitor;
>>> 
>>> now it only dynamically dispatches on the Visitor_Record'Class and the
>>> Node parameter is determined at compile time. I don't think i would have
>>> figured that out by myself (at least not at this point in time).
>> 
>> Okay. now it works when the Visitor type, Visit() procedures and the
>> Accept_Visitor() procedure is in a separate package from the parse tree.
>> but when i try to combine the 2 into one package i get
>> an error about multiple dispatching on all of the Visit() procedures.
>> what is my scope issue with being in the same package that doesn't apply
>> to them being in 2 packages?

This is a strength of Ada. The compiler indicates a problem in your design.
Visit appears to be multiple dispatching but it is not according to your
design. You should declare it as follows:

procedure Visit
          (  V    : in out Visitor_Record;
             Node : Equal_Op'Class
          )  is abstract;
procedure Visit
          (  V    : in out Visitor_Record;
             Node : Number_Node'Class
          )  is abstract;

Now Visit dispatches in V, but does not in Node, for you do the latter
manually in Accept_Visitor.

-- 
Regards,
Dmitry A. Kazakov
www.dmitry-kazakov.de



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

end of thread, other threads:[~2003-12-23 11:03 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-12-17 18:08 how do i implement double-dispatching? cl1motorsports
2003-12-18  2:17 ` Stephen Leake
2003-12-18  9:48 ` Dmitry A. Kazakov
2003-12-18 15:13 ` Martin Krischik
2003-12-20  6:27 ` cl1motorsports
2003-12-20  9:56   ` Martin Krischik
2003-12-20 17:00     ` cl1motorsports
2003-12-21 13:39       ` Stephen Leake
2003-12-21 17:40         ` cl1motorsports
2003-12-22 22:47           ` Stephen Leake
2003-12-22 21:41   ` cl1motorsports
2003-12-22 21:47     ` cl1motorsports
2003-12-23 11:03       ` Dmitry A. Kazakov
2003-12-22 22:49     ` Stephen Leake
2003-12-22 23:04       ` cl1motorsports

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