comp.lang.ada
 help / color / mirror / Atom feed
From: "Robert I. Eachus" <rieachus@comcast.net>
Subject: Re: issue with implementing a visitor design pattern
Date: Fri, 16 Jan 2004 22:41:49 -0500
Date: 2004-01-16T22:41:49-05:00	[thread overview]
Message-ID: <OdKdnWfUk9xjM5XdRVn-gg@comcast.com> (raw)
In-Reply-To: <100dqeul3pqiua0@corp.supernews.com>

cl1 wrote:
> i'm trying to implement a visitor pattern for a parse tree(its a simple
> calculator at this point). i have an abstract type:

I'll try to help...
> 
> type Visitor_Record is abstract tagged null record;
> 
> with primative operations Visit() for each node type like so:
> 
> Visit(V : in out Visitor_Record; Node : in Add_Op'Class) is abstract;
> ...
> Visit(V : in out Visitor_Record; Node : in Assignment_Node'Class) is
> abstract;

Do not make Visit classwide.  In other words get rid of the 'Class in 
the definition.  For dynamic dispatching where you may need 'Class is as 
the type of the formal parameter in the call.

> what i'm trying to do is implement a Preorder_Visitor_Record type that uses
> the Visit() operation to
> traverse the tree and calls an operation Visit_Operation() that is also a
> primative operation on Preorder_Visitor_Record
> like so:
> with parse_tree_pkg; use parse_tree_pkg; -- has the parse tree nodes a
> primative operation Accept_Visitor() for each node
>                                                                  -- and the
> abstract Visitor_Record with primative operations Visit() for each node
> package Preorder_Visitor_Pkg is
>     type Preorder_Visitor_Record is new Visitor_Record with null record;
> 
>     -- this is overidiing the abstract version in parse_tree_pkg;

But it doesn't in Ada and that is your problem.  It overloads not 
overrides in some scopes.  Ada 200Y will probably have an overrides 
keyword which will get you an error message at compile time here.

>     procedure Visit ( V : in out Preorder_Visitor_Record; Node : in
> Add_Op'Class);
>     .....
> 
>     procedure Visit_Operation (V : in preorder_Visitor_Record; node : in
> add_op'class);
> end preorder_visitor_Pkg;

Same problem here...
> 
> package body Preorder_Visitor_Pkg is
> 
> procedure Visit_Operation ( V : in out Preorder_Visitor_Record; Node : in
> Add_Op'Class)
> is begin
>     raise Not_Implemented; -- better handling in actual code with an error
> message using ada.exceptions
> end Visit_Operation
> procedure Visit( V : in out Preorder_Visitor_Record; Node : in Add_Op'Class)
> is begin
>     Visit_Operation(V, Node);
> end Visit;
> 
> 
> the actual code errors saying ambiguos call of Visit_Operation() from within
> the Visit() procedure. with possible interpretations at the definition of
> Preorder_Visitor_Record and at the specification for Visit_Operation.
> 
> the code works when you take Visit_Operation out of the mix. the package
> compiles and works with a test driver. but when i try to add in this
> Visit_Operation it doesn't work. I don't know if there are some scoping
> issues or if there is something else i need to know about primative
> operations to make this work. any guidance would be appreciated.
> 
> Thanks,
> Charles Lambert

The much deeper problem you have is that the Visitor pattern is a waste 
of effort in Ada.  Not wrong, or unimplementable, but the pattern as 
such is much heavier weight than it needs to be.  The normal approach to 
this problem in Ada is, in the package that declares the abstract data 
type, (the parse tree in this case) to have a generic procedure to do 
the work:

package Parse_Tree_Pkg is -- I'd call it Parse_Trees, but that is a 

                           -- style issue...

     type Node is ...;
     type Parse_Tree is ...;

     generic
       with procedure Visitor (N: in out Node);
     procedure In_Order (PT: in out Parse_Tree); -- visit all the nodes
                                                 -- of a parse tree in
                                                 -- order and Visitor
                                                 -- Visitor;

Now you can instantiate In_Order with whatever visitor you want.  Much 
easier to work with, and easier to change the In_Order instantiation to 
Pre_Order or Post_Order if the design changes.  Note that the generic 
formal procedure doesn't mention the ADT in its profile.  So you can 
pass the same concrete visitor implementation just as easily to a queue 
or stack, as long as the node type is the same.

-- 
                                           Robert I. Eachus

"The war on terror is a different kind of war, waged capture by capture, 
cell by cell, and victory by victory. Our security is assured by our 
perseverance and by our sure belief in the success of liberty." -- 
George W. Bush




  reply	other threads:[~2004-01-17  3:41 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-01-15 19:22 issue with implementing a visitor design pattern cl1
2004-01-17  3:41 ` Robert I. Eachus [this message]
2004-01-17 21:24   ` Robert A Duff
2004-01-24 20:38     ` Dale Stanbrough
2004-01-24 21:44       ` Robert A Duff
2004-01-26  8:34         ` Dmitry A. Kazakov
2004-01-26 20:18           ` Robert A Duff
2004-01-27  8:36             ` Dmitry A. Kazakov
2004-02-01  0:32               ` Georg Bauhaus
2004-01-17 23:05   ` cl1
replies disabled

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