Difference between revisions of "Visitor"
m (11 revisions: initial import from SamrtEiffel Wiki - The Grand SmartEiffel Book) |
|
(2 intermediate revisions by the same user not shown) | |
(No difference)
|
Revision as of 22:50, 3 March 2013
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 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.
Framework
Every visitable class inherits from VISITABLE. With it are associated:
Visitable classes
The visitable classes are all the classes of the syntactic and semantic tree. There we find in particular
- EXPRESSION, INSTRUCTION (syntactic classes)
- TYPE, FEATURE_STAMP, LIVE_TYPE... (semantic classes)
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.