Visitor

From SmartEiffelWiki


SmartEiffel vistors are a mechanism that let you reuse the SmartEiffel kernel in order to build new applicationss.

This is how eiffeldoc, for example, can have been built without touching the system kernel.

The origin of visitors is a design pattern, in fact the acyclic visitor (http://www.objectmentor.com/resources/articles/acv.pdf) developed by Robert C. Martin.

This design pattern has been adopted and adapted by SmartEiffel. All the framework classes are in the SmartEiffel/tools/visitor directory.

Table of contents

Framework

Every visitable class inherits from VISITABLE. With it are associated:

  • a class derived from VISITOR,
  • a feature accept which has for its parameter an object of that class.

Visitable classes

The visitable classes are all the classes of the syntactic and semantic tree. There we find in particular

Using visitors

Simple cases

Each visitor can be used separately, but you can also use several in the same class; this is the most common case.

To use visitors, you have to create a visitor class. This class will have the following properties:

  • inherits all the visitor classes of the framework (conforming inheritance)
  • also inherits from the VISITOR class itself (conforming inheritance)
  • defines all the visit_* features of the visitor classes.

Usually, such a class also provides a feature which lets you start a search. If that does not exist, it is enough to run the accept feature on a visitable object. Of course, that object must be visitable by that visitor, in other words, that visitor must inherit from the framework visitor class which is able to visit the object.

For some examples, see AGENT_CREATION_HELPER or again HIDDEN_EXPRESSION_DETECTOR.

Using IN_OUT_VISITOR

IN_OUT_VISITOR is a class that lets you do a complete search of a class's syntactic tree, depth-first.

Each node is visited by the following algorithm (the NODE class is imaginary):

feature {NODE}
   visit_node (a_node: NODE) is
      do
         if enter_node(a_node) then
            node.child.accept(Current);
            exit_node(a_node);
         end
      end

feature {}
   enter_node (a_node: NODE): BOOLEAN is
      do
         Result := True
      end

   exit_node (a_node: NODE) is
      do
      end

The interesting point is that a class inheriting from IN_OUT_VISITOR has to redefine only what is strictly necessary.

See, for example, EIFFELDOC_SHORTER_CLASSDOC and EIFFELDOC_SHORTER_FIND_CLIENTS.

Other languages