/*
The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language
governing rights and limitations under the License.
The Original Code is RAIL(Runtime Assembly Instrumentation Library) Alpha Version.
The Initial Developer of the Original Code is University of Coimbra,
Computer Science Department, Dependable Systems Group. Copyright (C) University of Coimbra.
All Rights Reserved.
*/
using System;
using Rail.Reflect;
namespace Rail.Transformation{
/// <summary>
/// <remarks>
/// There are several specification options for visitors.
/// <list type="bullet">
/// <item>Controlling descent - How deep should the visitor go? The visitor could
/// go only until modules, could descend into type or go all the way down to methods.
/// Having visitors always going deep into the tree is inneficient. Solutions:
/// locals and statements, 3; instructions, 4. The user specifies how deep to go.
/// - Barat forces the visitors to encode the logic that controls descent, so users
/// have greater control.
/// </item>
///
/// <item>Another related issue is the order of the traversals. If the framework
/// controls the descent logic, then the traversal orders will be hard-coded in it.
/// In this case the options are having only one traversal order or allowing the
/// client to specify one pre-defined order in the visitor (a property having an
/// enumerated value).
///
/// Barat uses a different mechanism. It's up to the Visitor to implement the
/// traversal logic, so the client has full control.
/// </item>
/// </list>
///
/// (Choosing: The most simple solution that does the job...)
/// The initial prototype will implement the following:
/// - Descent all the way down. If performance proves to be unnaceptable, this
/// can be easily changed using a solution similiar to JTrek.
///
/// - To control the traversal order, we use a modified version of Barat. Two
/// types:
///
/// - Visitors are visible to the clients and contain only the logic to visit
/// a certain node. Therefore, they are traversal order agnostic.
/// - Walkers contain only the traversal logic and are internal to the framework.
///
/// When a user wants to start a descent, he or she creates a Visitor, specifies
/// the traversal order using a property (TraversalOrder {PostOrder, PreOrder, ...}),
/// and calls visit in the Node where the visit should be initiated. Internally,
/// the Visitor creates a corresponding walker. The framework, when needing to
/// continue a visit, requests the Walker of the visitor and uses it to descend.
///
/// </remarks>
/// </summary>
public abstract class Visitor
{
private TraversalOrder traversalOrder;
private Walker walker;
/// <summary>
/// Summary of Visitor.
/// </summary>
///
public Visitor()
{
this.TraversalOrder = TraversalOrder.PreOrder;
}
/// <remarks>
/// The default value is pre-order.
/// </remarks>
/// <summary>
/// Gets or sets the traversal order.
/// </summary>
public TraversalOrder TraversalOrder
{
get
{
return traversalOrder;
}
set
{
if (traversalOrder != value)
{
traversalOrder = value;
switch (traversalOrder)
{
case TraversalOrder.PostOrder:
walker = new PostOrderWalker(this);
break;
case TraversalOrder.PreOrder:
walker = new PreOrderWalker(this);
break;
}
}
}
}
/// <summary>
/// Summary of VisitAssembly.
/// </summary>
/// <param name=assm></param>
public abstract void VisitAssembly(RAssemblyDef assm);
/// <summary>
/// Summary of VisitModule.
/// </summary>
/// <param name=module></param>
public abstract void VisitModule(RModuleDef module);
/// <summary>
/// Summary of VisitType.
/// </summary>
/// <param name=type></param>
public abstract void VisitType(RTypeDef type);
/// <summary>
/// Summary of VisitProperty.
/// </summary>
/// <param name=property></param>
public abstract void VisitProperty(RPropertyDef property);
/// <summary>
/// Summary of VisitField.
/// </summary>
/// <param name=field></param>
public abstract void VisitField(RFieldDef field);
/// <summary>
/// Summary of VisitMethod.
/// </summary>
/// <param name=method></param>
public abstract void VisitMethod(RMethodDef method);
/// <summary>
/// Summary of VisitConstructor.
/// </summary>
/// <param name=method></param>
public abstract void VisitConstructor(RConstructorDef method);
/// <summary>
/// Summary of VisitEvent.
/// </summary>
/// <param name=evt></param>
public abstract void VisitEvent(REventDef evt);
/// <summary>
/// Returns the walker that should be used with this Visitor.
/// <remarks> Should only be called from inside the framework by classes
/// accepting visitors.
/// </remarks>
/// </summary>
internal Walker GetWalker()
{
return walker;
}
}
/// <summary>
/// A Visitor whose methods don't do anything.
/// <remarks>
/// This class can be used as base for <code>Visitors</code> that don't
/// need to implement all <code>VisitXXX</code> methods, therefore avoiding
/// the need to create empty implementations for the methods that are
/// not needed
/// </remarks>
/// </summary>
public class EmptyVisitor : Visitor
{
/// <summary>
///
/// </summary>
/// <param name="assm"></param>
public override void VisitAssembly(RAssemblyDef assm) {}
/// <summary>
///
/// </summary>
/// <param name="module"></param>
public override void VisitModule(RModuleDef module) {}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
public override void VisitType(RTypeDef type) {}
/// <summary>
///
/// </summary>
/// <param name="property"></param>
public override void VisitProperty(RPropertyDef property) {}
/// <summary>
///
/// </summary>
/// <param name="field"></param>
public override void VisitField(RFieldDef field) {}
/// <summary>
///
/// </summary>
/// <param name="method"></param>
public override void VisitMethod(RMethodDef method) {}
/// <summary>
///
/// </summary>
/// <param name="method"></param>
public override void VisitConstructor(RConstructorDef method) {}
/// <summary>
///
/// </summary>
/// <param name="evt"></param>
public override void VisitEvent(REventDef evt) {}
}
/// <summary>
/// Implemented by nodes that can accept a visitor
/// </summary>
public interface IVisitable
{
void Accept(Visitor visitor);
}
}
|