#region license
// Copyright (c) 2003, 2004, 2005 Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

//
// DO NOT EDIT THIS FILE!
//
// This file was generated automatically by astgen.boo.
//

namespace Boo.Lang.Compiler.Ast
{
	using System;
	
	public class DepthFirstTransformer : IAstVisitor
	{
		protected Node _resultingNode = null;	

		public virtual void OnCompileUnit(Boo.Lang.Compiler.Ast.CompileUnit node)
		{	
			if (EnterCompileUnit(node))
			{
				Visit(node.Modules);

				LeaveCompileUnit(node);
			}
		}

		public virtual bool EnterCompileUnit(Boo.Lang.Compiler.Ast.CompileUnit node)
		{
			return true;
		}
		
		public virtual void LeaveCompileUnit(Boo.Lang.Compiler.Ast.CompileUnit node)
		{
		}

		public virtual void OnExplicitMemberInfo(Boo.Lang.Compiler.Ast.ExplicitMemberInfo node)
		{	
			if (EnterExplicitMemberInfo(node))
			{
				SimpleTypeReference currentInterfaceTypeValue = node.InterfaceType;
				if (null != currentInterfaceTypeValue)
				{			
					SimpleTypeReference newValue = (SimpleTypeReference)VisitNode(currentInterfaceTypeValue);
					if (!object.ReferenceEquals(newValue, currentInterfaceTypeValue))
					{
						node.InterfaceType = newValue;
					}
				}

				LeaveExplicitMemberInfo(node);
			}
		}

		public virtual bool EnterExplicitMemberInfo(Boo.Lang.Compiler.Ast.ExplicitMemberInfo node)
		{
			return true;
		}
		
		public virtual void LeaveExplicitMemberInfo(Boo.Lang.Compiler.Ast.ExplicitMemberInfo node)
		{
		}

		public virtual void OnSimpleTypeReference(Boo.Lang.Compiler.Ast.SimpleTypeReference node)
		{	
		}

		public virtual void OnArrayTypeReference(Boo.Lang.Compiler.Ast.ArrayTypeReference node)
		{	
			if (EnterArrayTypeReference(node))
			{
				TypeReference currentElementTypeValue = node.ElementType;
				if (null != currentElementTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentElementTypeValue);
					if (!object.ReferenceEquals(newValue, currentElementTypeValue))
					{
						node.ElementType = newValue;
					}
				}
				IntegerLiteralExpression currentRankValue = node.Rank;
				if (null != currentRankValue)
				{			
					IntegerLiteralExpression newValue = (IntegerLiteralExpression)VisitNode(currentRankValue);
					if (!object.ReferenceEquals(newValue, currentRankValue))
					{
						node.Rank = newValue;
					}
				}

				LeaveArrayTypeReference(node);
			}
		}

		public virtual bool EnterArrayTypeReference(Boo.Lang.Compiler.Ast.ArrayTypeReference node)
		{
			return true;
		}
		
		public virtual void LeaveArrayTypeReference(Boo.Lang.Compiler.Ast.ArrayTypeReference node)
		{
		}

		public virtual void OnCallableTypeReference(Boo.Lang.Compiler.Ast.CallableTypeReference node)
		{	
			if (EnterCallableTypeReference(node))
			{
				Visit(node.Parameters);
				TypeReference currentReturnTypeValue = node.ReturnType;
				if (null != currentReturnTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentReturnTypeValue);
					if (!object.ReferenceEquals(newValue, currentReturnTypeValue))
					{
						node.ReturnType = newValue;
					}
				}

				LeaveCallableTypeReference(node);
			}
		}

		public virtual bool EnterCallableTypeReference(Boo.Lang.Compiler.Ast.CallableTypeReference node)
		{
			return true;
		}
		
		public virtual void LeaveCallableTypeReference(Boo.Lang.Compiler.Ast.CallableTypeReference node)
		{
		}

		public virtual void OnGenericTypeReference(Boo.Lang.Compiler.Ast.GenericTypeReference node)
		{	
			if (EnterGenericTypeReference(node))
			{
				Visit(node.GenericArguments);

				LeaveGenericTypeReference(node);
			}
		}

		public virtual bool EnterGenericTypeReference(Boo.Lang.Compiler.Ast.GenericTypeReference node)
		{
			return true;
		}
		
		public virtual void LeaveGenericTypeReference(Boo.Lang.Compiler.Ast.GenericTypeReference node)
		{
		}

		public virtual void OnGenericTypeDefinitionReference(Boo.Lang.Compiler.Ast.GenericTypeDefinitionReference node)
		{	
		}

		public virtual void OnCallableDefinition(Boo.Lang.Compiler.Ast.CallableDefinition node)
		{	
			if (EnterCallableDefinition(node))
			{
				Visit(node.Attributes);
				Visit(node.Parameters);
				TypeReference currentReturnTypeValue = node.ReturnType;
				if (null != currentReturnTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentReturnTypeValue);
					if (!object.ReferenceEquals(newValue, currentReturnTypeValue))
					{
						node.ReturnType = newValue;
					}
				}
				Visit(node.ReturnTypeAttributes);

				LeaveCallableDefinition(node);
			}
		}

		public virtual bool EnterCallableDefinition(Boo.Lang.Compiler.Ast.CallableDefinition node)
		{
			return true;
		}
		
		public virtual void LeaveCallableDefinition(Boo.Lang.Compiler.Ast.CallableDefinition node)
		{
		}

		public virtual void OnNamespaceDeclaration(Boo.Lang.Compiler.Ast.NamespaceDeclaration node)
		{	
		}

		public virtual void OnImport(Boo.Lang.Compiler.Ast.Import node)
		{	
			if (EnterImport(node))
			{
				ReferenceExpression currentAssemblyReferenceValue = node.AssemblyReference;
				if (null != currentAssemblyReferenceValue)
				{			
					ReferenceExpression newValue = (ReferenceExpression)VisitNode(currentAssemblyReferenceValue);
					if (!object.ReferenceEquals(newValue, currentAssemblyReferenceValue))
					{
						node.AssemblyReference = newValue;
					}
				}
				ReferenceExpression currentAliasValue = node.Alias;
				if (null != currentAliasValue)
				{			
					ReferenceExpression newValue = (ReferenceExpression)VisitNode(currentAliasValue);
					if (!object.ReferenceEquals(newValue, currentAliasValue))
					{
						node.Alias = newValue;
					}
				}

				LeaveImport(node);
			}
		}

		public virtual bool EnterImport(Boo.Lang.Compiler.Ast.Import node)
		{
			return true;
		}
		
		public virtual void LeaveImport(Boo.Lang.Compiler.Ast.Import node)
		{
		}

		public virtual void OnModule(Boo.Lang.Compiler.Ast.Module node)
		{	
			if (EnterModule(node))
			{
				Visit(node.Attributes);
				Visit(node.Members);
				Visit(node.BaseTypes);
				NamespaceDeclaration currentNamespaceValue = node.Namespace;
				if (null != currentNamespaceValue)
				{			
					NamespaceDeclaration newValue = (NamespaceDeclaration)VisitNode(currentNamespaceValue);
					if (!object.ReferenceEquals(newValue, currentNamespaceValue))
					{
						node.Namespace = newValue;
					}
				}
				Visit(node.Imports);
				Block currentGlobalsValue = node.Globals;
				if (null != currentGlobalsValue)
				{			
					Block newValue = (Block)VisitNode(currentGlobalsValue);
					if (!object.ReferenceEquals(newValue, currentGlobalsValue))
					{
						node.Globals = newValue;
					}
				}
				Visit(node.AssemblyAttributes);

				LeaveModule(node);
			}
		}

		public virtual bool EnterModule(Boo.Lang.Compiler.Ast.Module node)
		{
			return true;
		}
		
		public virtual void LeaveModule(Boo.Lang.Compiler.Ast.Module node)
		{
		}

		public virtual void OnClassDefinition(Boo.Lang.Compiler.Ast.ClassDefinition node)
		{	
			if (EnterClassDefinition(node))
			{
				Visit(node.Attributes);
				Visit(node.Members);
				Visit(node.BaseTypes);

				LeaveClassDefinition(node);
			}
		}

		public virtual bool EnterClassDefinition(Boo.Lang.Compiler.Ast.ClassDefinition node)
		{
			return true;
		}
		
		public virtual void LeaveClassDefinition(Boo.Lang.Compiler.Ast.ClassDefinition node)
		{
		}

		public virtual void OnStructDefinition(Boo.Lang.Compiler.Ast.StructDefinition node)
		{	
			if (EnterStructDefinition(node))
			{
				Visit(node.Attributes);
				Visit(node.Members);
				Visit(node.BaseTypes);

				LeaveStructDefinition(node);
			}
		}

		public virtual bool EnterStructDefinition(Boo.Lang.Compiler.Ast.StructDefinition node)
		{
			return true;
		}
		
		public virtual void LeaveStructDefinition(Boo.Lang.Compiler.Ast.StructDefinition node)
		{
		}

		public virtual void OnInterfaceDefinition(Boo.Lang.Compiler.Ast.InterfaceDefinition node)
		{	
			if (EnterInterfaceDefinition(node))
			{
				Visit(node.Attributes);
				Visit(node.Members);
				Visit(node.BaseTypes);

				LeaveInterfaceDefinition(node);
			}
		}

		public virtual bool EnterInterfaceDefinition(Boo.Lang.Compiler.Ast.InterfaceDefinition node)
		{
			return true;
		}
		
		public virtual void LeaveInterfaceDefinition(Boo.Lang.Compiler.Ast.InterfaceDefinition node)
		{
		}

		public virtual void OnEnumDefinition(Boo.Lang.Compiler.Ast.EnumDefinition node)
		{	
			if (EnterEnumDefinition(node))
			{
				Visit(node.Attributes);
				Visit(node.Members);
				Visit(node.BaseTypes);

				LeaveEnumDefinition(node);
			}
		}

		public virtual bool EnterEnumDefinition(Boo.Lang.Compiler.Ast.EnumDefinition node)
		{
			return true;
		}
		
		public virtual void LeaveEnumDefinition(Boo.Lang.Compiler.Ast.EnumDefinition node)
		{
		}

		public virtual void OnEnumMember(Boo.Lang.Compiler.Ast.EnumMember node)
		{	
			if (EnterEnumMember(node))
			{
				Visit(node.Attributes);
				IntegerLiteralExpression currentInitializerValue = node.Initializer;
				if (null != currentInitializerValue)
				{			
					IntegerLiteralExpression newValue = (IntegerLiteralExpression)VisitNode(currentInitializerValue);
					if (!object.ReferenceEquals(newValue, currentInitializerValue))
					{
						node.Initializer = newValue;
					}
				}

				LeaveEnumMember(node);
			}
		}

		public virtual bool EnterEnumMember(Boo.Lang.Compiler.Ast.EnumMember node)
		{
			return true;
		}
		
		public virtual void LeaveEnumMember(Boo.Lang.Compiler.Ast.EnumMember node)
		{
		}

		public virtual void OnField(Boo.Lang.Compiler.Ast.Field node)
		{	
			if (EnterField(node))
			{
				Visit(node.Attributes);
				TypeReference currentTypeValue = node.Type;
				if (null != currentTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentTypeValue);
					if (!object.ReferenceEquals(newValue, currentTypeValue))
					{
						node.Type = newValue;
					}
				}
				Expression currentInitializerValue = node.Initializer;
				if (null != currentInitializerValue)
				{			
					Expression newValue = (Expression)VisitNode(currentInitializerValue);
					if (!object.ReferenceEquals(newValue, currentInitializerValue))
					{
						node.Initializer = newValue;
					}
				}

				LeaveField(node);
			}
		}

		public virtual bool EnterField(Boo.Lang.Compiler.Ast.Field node)
		{
			return true;
		}
		
		public virtual void LeaveField(Boo.Lang.Compiler.Ast.Field node)
		{
		}

		public virtual void OnProperty(Boo.Lang.Compiler.Ast.Property node)
		{	
			if (EnterProperty(node))
			{
				Visit(node.Attributes);
				Visit(node.Parameters);
				Method currentGetterValue = node.Getter;
				if (null != currentGetterValue)
				{			
					Method newValue = (Method)VisitNode(currentGetterValue);
					if (!object.ReferenceEquals(newValue, currentGetterValue))
					{
						node.Getter = newValue;
					}
				}
				Method currentSetterValue = node.Setter;
				if (null != currentSetterValue)
				{			
					Method newValue = (Method)VisitNode(currentSetterValue);
					if (!object.ReferenceEquals(newValue, currentSetterValue))
					{
						node.Setter = newValue;
					}
				}
				TypeReference currentTypeValue = node.Type;
				if (null != currentTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentTypeValue);
					if (!object.ReferenceEquals(newValue, currentTypeValue))
					{
						node.Type = newValue;
					}
				}
				ExplicitMemberInfo currentExplicitInfoValue = node.ExplicitInfo;
				if (null != currentExplicitInfoValue)
				{			
					ExplicitMemberInfo newValue = (ExplicitMemberInfo)VisitNode(currentExplicitInfoValue);
					if (!object.ReferenceEquals(newValue, currentExplicitInfoValue))
					{
						node.ExplicitInfo = newValue;
					}
				}

				LeaveProperty(node);
			}
		}

		public virtual bool EnterProperty(Boo.Lang.Compiler.Ast.Property node)
		{
			return true;
		}
		
		public virtual void LeaveProperty(Boo.Lang.Compiler.Ast.Property node)
		{
		}

		public virtual void OnEvent(Boo.Lang.Compiler.Ast.Event node)
		{	
			if (EnterEvent(node))
			{
				Visit(node.Attributes);
				Method currentAddValue = node.Add;
				if (null != currentAddValue)
				{			
					Method newValue = (Method)VisitNode(currentAddValue);
					if (!object.ReferenceEquals(newValue, currentAddValue))
					{
						node.Add = newValue;
					}
				}
				Method currentRemoveValue = node.Remove;
				if (null != currentRemoveValue)
				{			
					Method newValue = (Method)VisitNode(currentRemoveValue);
					if (!object.ReferenceEquals(newValue, currentRemoveValue))
					{
						node.Remove = newValue;
					}
				}
				Method currentRaiseValue = node.Raise;
				if (null != currentRaiseValue)
				{			
					Method newValue = (Method)VisitNode(currentRaiseValue);
					if (!object.ReferenceEquals(newValue, currentRaiseValue))
					{
						node.Raise = newValue;
					}
				}
				TypeReference currentTypeValue = node.Type;
				if (null != currentTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentTypeValue);
					if (!object.ReferenceEquals(newValue, currentTypeValue))
					{
						node.Type = newValue;
					}
				}

				LeaveEvent(node);
			}
		}

		public virtual bool EnterEvent(Boo.Lang.Compiler.Ast.Event node)
		{
			return true;
		}
		
		public virtual void LeaveEvent(Boo.Lang.Compiler.Ast.Event node)
		{
		}

		public virtual void OnLocal(Boo.Lang.Compiler.Ast.Local node)
		{	
		}

		public virtual void OnCallableBlockExpression(Boo.Lang.Compiler.Ast.CallableBlockExpression node)
		{	
			if (EnterCallableBlockExpression(node))
			{
				Visit(node.Parameters);
				TypeReference currentReturnTypeValue = node.ReturnType;
				if (null != currentReturnTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentReturnTypeValue);
					if (!object.ReferenceEquals(newValue, currentReturnTypeValue))
					{
						node.ReturnType = newValue;
					}
				}
				Block currentBodyValue = node.Body;
				if (null != currentBodyValue)
				{			
					Block newValue = (Block)VisitNode(currentBodyValue);
					if (!object.ReferenceEquals(newValue, currentBodyValue))
					{
						node.Body = newValue;
					}
				}

				LeaveCallableBlockExpression(node);
			}
		}

		public virtual bool EnterCallableBlockExpression(Boo.Lang.Compiler.Ast.CallableBlockExpression node)
		{
			return true;
		}
		
		public virtual void LeaveCallableBlockExpression(Boo.Lang.Compiler.Ast.CallableBlockExpression node)
		{
		}

		public virtual void OnMethod(Boo.Lang.Compiler.Ast.Method node)
		{	
			if (EnterMethod(node))
			{
				Visit(node.Attributes);
				Visit(node.Parameters);
				TypeReference currentReturnTypeValue = node.ReturnType;
				if (null != currentReturnTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentReturnTypeValue);
					if (!object.ReferenceEquals(newValue, currentReturnTypeValue))
					{
						node.ReturnType = newValue;
					}
				}
				Visit(node.ReturnTypeAttributes);
				Block currentBodyValue = node.Body;
				if (null != currentBodyValue)
				{			
					Block newValue = (Block)VisitNode(currentBodyValue);
					if (!object.ReferenceEquals(newValue, currentBodyValue))
					{
						node.Body = newValue;
					}
				}
				Visit(node.Locals);
				ExplicitMemberInfo currentExplicitInfoValue = node.ExplicitInfo;
				if (null != currentExplicitInfoValue)
				{			
					ExplicitMemberInfo newValue = (ExplicitMemberInfo)VisitNode(currentExplicitInfoValue);
					if (!object.ReferenceEquals(newValue, currentExplicitInfoValue))
					{
						node.ExplicitInfo = newValue;
					}
				}

				LeaveMethod(node);
			}
		}

		public virtual bool EnterMethod(Boo.Lang.Compiler.Ast.Method node)
		{
			return true;
		}
		
		public virtual void LeaveMethod(Boo.Lang.Compiler.Ast.Method node)
		{
		}

		public virtual void OnConstructor(Boo.Lang.Compiler.Ast.Constructor node)
		{	
			if (EnterConstructor(node))
			{
				Visit(node.Attributes);
				Visit(node.Parameters);
				TypeReference currentReturnTypeValue = node.ReturnType;
				if (null != currentReturnTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentReturnTypeValue);
					if (!object.ReferenceEquals(newValue, currentReturnTypeValue))
					{
						node.ReturnType = newValue;
					}
				}
				Visit(node.ReturnTypeAttributes);
				Block currentBodyValue = node.Body;
				if (null != currentBodyValue)
				{			
					Block newValue = (Block)VisitNode(currentBodyValue);
					if (!object.ReferenceEquals(newValue, currentBodyValue))
					{
						node.Body = newValue;
					}
				}
				Visit(node.Locals);
				ExplicitMemberInfo currentExplicitInfoValue = node.ExplicitInfo;
				if (null != currentExplicitInfoValue)
				{			
					ExplicitMemberInfo newValue = (ExplicitMemberInfo)VisitNode(currentExplicitInfoValue);
					if (!object.ReferenceEquals(newValue, currentExplicitInfoValue))
					{
						node.ExplicitInfo = newValue;
					}
				}

				LeaveConstructor(node);
			}
		}

		public virtual bool EnterConstructor(Boo.Lang.Compiler.Ast.Constructor node)
		{
			return true;
		}
		
		public virtual void LeaveConstructor(Boo.Lang.Compiler.Ast.Constructor node)
		{
		}

		public virtual void OnDestructor(Boo.Lang.Compiler.Ast.Destructor node)
		{	
			if (EnterDestructor(node))
			{
				Visit(node.Attributes);
				Visit(node.Parameters);
				TypeReference currentReturnTypeValue = node.ReturnType;
				if (null != currentReturnTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentReturnTypeValue);
					if (!object.ReferenceEquals(newValue, currentReturnTypeValue))
					{
						node.ReturnType = newValue;
					}
				}
				Visit(node.ReturnTypeAttributes);
				Block currentBodyValue = node.Body;
				if (null != currentBodyValue)
				{			
					Block newValue = (Block)VisitNode(currentBodyValue);
					if (!object.ReferenceEquals(newValue, currentBodyValue))
					{
						node.Body = newValue;
					}
				}
				Visit(node.Locals);
				ExplicitMemberInfo currentExplicitInfoValue = node.ExplicitInfo;
				if (null != currentExplicitInfoValue)
				{			
					ExplicitMemberInfo newValue = (ExplicitMemberInfo)VisitNode(currentExplicitInfoValue);
					if (!object.ReferenceEquals(newValue, currentExplicitInfoValue))
					{
						node.ExplicitInfo = newValue;
					}
				}

				LeaveDestructor(node);
			}
		}

		public virtual bool EnterDestructor(Boo.Lang.Compiler.Ast.Destructor node)
		{
			return true;
		}
		
		public virtual void LeaveDestructor(Boo.Lang.Compiler.Ast.Destructor node)
		{
		}

		public virtual void OnParameterDeclaration(Boo.Lang.Compiler.Ast.ParameterDeclaration node)
		{	
			if (EnterParameterDeclaration(node))
			{
				TypeReference currentTypeValue = node.Type;
				if (null != currentTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentTypeValue);
					if (!object.ReferenceEquals(newValue, currentTypeValue))
					{
						node.Type = newValue;
					}
				}
				Visit(node.Attributes);

				LeaveParameterDeclaration(node);
			}
		}

		public virtual bool EnterParameterDeclaration(Boo.Lang.Compiler.Ast.ParameterDeclaration node)
		{
			return true;
		}
		
		public virtual void LeaveParameterDeclaration(Boo.Lang.Compiler.Ast.ParameterDeclaration node)
		{
		}

		public virtual void OnDeclaration(Boo.Lang.Compiler.Ast.Declaration node)
		{	
			if (EnterDeclaration(node))
			{
				TypeReference currentTypeValue = node.Type;
				if (null != currentTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentTypeValue);
					if (!object.ReferenceEquals(newValue, currentTypeValue))
					{
						node.Type = newValue;
					}
				}

				LeaveDeclaration(node);
			}
		}

		public virtual bool EnterDeclaration(Boo.Lang.Compiler.Ast.Declaration node)
		{
			return true;
		}
		
		public virtual void LeaveDeclaration(Boo.Lang.Compiler.Ast.Declaration node)
		{
		}

		public virtual void OnAttribute(Boo.Lang.Compiler.Ast.Attribute node)
		{	
			if (EnterAttribute(node))
			{
				Visit(node.Arguments);
				Visit(node.NamedArguments);

				LeaveAttribute(node);
			}
		}

		public virtual bool EnterAttribute(Boo.Lang.Compiler.Ast.Attribute node)
		{
			return true;
		}
		
		public virtual void LeaveAttribute(Boo.Lang.Compiler.Ast.Attribute node)
		{
		}

		public virtual void OnStatementModifier(Boo.Lang.Compiler.Ast.StatementModifier node)
		{	
			if (EnterStatementModifier(node))
			{
				Expression currentConditionValue = node.Condition;
				if (null != currentConditionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentConditionValue);
					if (!object.ReferenceEquals(newValue, currentConditionValue))
					{
						node.Condition = newValue;
					}
				}

				LeaveStatementModifier(node);
			}
		}

		public virtual bool EnterStatementModifier(Boo.Lang.Compiler.Ast.StatementModifier node)
		{
			return true;
		}
		
		public virtual void LeaveStatementModifier(Boo.Lang.Compiler.Ast.StatementModifier node)
		{
		}

		public virtual void OnGotoStatement(Boo.Lang.Compiler.Ast.GotoStatement node)
		{	
			if (EnterGotoStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				ReferenceExpression currentLabelValue = node.Label;
				if (null != currentLabelValue)
				{			
					ReferenceExpression newValue = (ReferenceExpression)VisitNode(currentLabelValue);
					if (!object.ReferenceEquals(newValue, currentLabelValue))
					{
						node.Label = newValue;
					}
				}

				LeaveGotoStatement(node);
			}
		}

		public virtual bool EnterGotoStatement(Boo.Lang.Compiler.Ast.GotoStatement node)
		{
			return true;
		}
		
		public virtual void LeaveGotoStatement(Boo.Lang.Compiler.Ast.GotoStatement node)
		{
		}

		public virtual void OnLabelStatement(Boo.Lang.Compiler.Ast.LabelStatement node)
		{	
			if (EnterLabelStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}

				LeaveLabelStatement(node);
			}
		}

		public virtual bool EnterLabelStatement(Boo.Lang.Compiler.Ast.LabelStatement node)
		{
			return true;
		}
		
		public virtual void LeaveLabelStatement(Boo.Lang.Compiler.Ast.LabelStatement node)
		{
		}

		public virtual void OnBlock(Boo.Lang.Compiler.Ast.Block node)
		{	
			if (EnterBlock(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Visit(node.Statements);

				LeaveBlock(node);
			}
		}

		public virtual bool EnterBlock(Boo.Lang.Compiler.Ast.Block node)
		{
			return true;
		}
		
		public virtual void LeaveBlock(Boo.Lang.Compiler.Ast.Block node)
		{
		}

		public virtual void OnDeclarationStatement(Boo.Lang.Compiler.Ast.DeclarationStatement node)
		{	
			if (EnterDeclarationStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Declaration currentDeclarationValue = node.Declaration;
				if (null != currentDeclarationValue)
				{			
					Declaration newValue = (Declaration)VisitNode(currentDeclarationValue);
					if (!object.ReferenceEquals(newValue, currentDeclarationValue))
					{
						node.Declaration = newValue;
					}
				}
				Expression currentInitializerValue = node.Initializer;
				if (null != currentInitializerValue)
				{			
					Expression newValue = (Expression)VisitNode(currentInitializerValue);
					if (!object.ReferenceEquals(newValue, currentInitializerValue))
					{
						node.Initializer = newValue;
					}
				}

				LeaveDeclarationStatement(node);
			}
		}

		public virtual bool EnterDeclarationStatement(Boo.Lang.Compiler.Ast.DeclarationStatement node)
		{
			return true;
		}
		
		public virtual void LeaveDeclarationStatement(Boo.Lang.Compiler.Ast.DeclarationStatement node)
		{
		}

		public virtual void OnMacroStatement(Boo.Lang.Compiler.Ast.MacroStatement node)
		{	
			if (EnterMacroStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Visit(node.Arguments);
				Block currentBlockValue = node.Block;
				if (null != currentBlockValue)
				{			
					Block newValue = (Block)VisitNode(currentBlockValue);
					if (!object.ReferenceEquals(newValue, currentBlockValue))
					{
						node.Block = newValue;
					}
				}

				LeaveMacroStatement(node);
			}
		}

		public virtual bool EnterMacroStatement(Boo.Lang.Compiler.Ast.MacroStatement node)
		{
			return true;
		}
		
		public virtual void LeaveMacroStatement(Boo.Lang.Compiler.Ast.MacroStatement node)
		{
		}

		public virtual void OnTryStatement(Boo.Lang.Compiler.Ast.TryStatement node)
		{	
			if (EnterTryStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Block currentProtectedBlockValue = node.ProtectedBlock;
				if (null != currentProtectedBlockValue)
				{			
					Block newValue = (Block)VisitNode(currentProtectedBlockValue);
					if (!object.ReferenceEquals(newValue, currentProtectedBlockValue))
					{
						node.ProtectedBlock = newValue;
					}
				}
				Visit(node.ExceptionHandlers);
				Block currentEnsureBlockValue = node.EnsureBlock;
				if (null != currentEnsureBlockValue)
				{			
					Block newValue = (Block)VisitNode(currentEnsureBlockValue);
					if (!object.ReferenceEquals(newValue, currentEnsureBlockValue))
					{
						node.EnsureBlock = newValue;
					}
				}

				LeaveTryStatement(node);
			}
		}

		public virtual bool EnterTryStatement(Boo.Lang.Compiler.Ast.TryStatement node)
		{
			return true;
		}
		
		public virtual void LeaveTryStatement(Boo.Lang.Compiler.Ast.TryStatement node)
		{
		}

		public virtual void OnExceptionHandler(Boo.Lang.Compiler.Ast.ExceptionHandler node)
		{	
			if (EnterExceptionHandler(node))
			{
				Declaration currentDeclarationValue = node.Declaration;
				if (null != currentDeclarationValue)
				{			
					Declaration newValue = (Declaration)VisitNode(currentDeclarationValue);
					if (!object.ReferenceEquals(newValue, currentDeclarationValue))
					{
						node.Declaration = newValue;
					}
				}
				Block currentBlockValue = node.Block;
				if (null != currentBlockValue)
				{			
					Block newValue = (Block)VisitNode(currentBlockValue);
					if (!object.ReferenceEquals(newValue, currentBlockValue))
					{
						node.Block = newValue;
					}
				}

				LeaveExceptionHandler(node);
			}
		}

		public virtual bool EnterExceptionHandler(Boo.Lang.Compiler.Ast.ExceptionHandler node)
		{
			return true;
		}
		
		public virtual void LeaveExceptionHandler(Boo.Lang.Compiler.Ast.ExceptionHandler node)
		{
		}

		public virtual void OnIfStatement(Boo.Lang.Compiler.Ast.IfStatement node)
		{	
			if (EnterIfStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Expression currentConditionValue = node.Condition;
				if (null != currentConditionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentConditionValue);
					if (!object.ReferenceEquals(newValue, currentConditionValue))
					{
						node.Condition = newValue;
					}
				}
				Block currentTrueBlockValue = node.TrueBlock;
				if (null != currentTrueBlockValue)
				{			
					Block newValue = (Block)VisitNode(currentTrueBlockValue);
					if (!object.ReferenceEquals(newValue, currentTrueBlockValue))
					{
						node.TrueBlock = newValue;
					}
				}
				Block currentFalseBlockValue = node.FalseBlock;
				if (null != currentFalseBlockValue)
				{			
					Block newValue = (Block)VisitNode(currentFalseBlockValue);
					if (!object.ReferenceEquals(newValue, currentFalseBlockValue))
					{
						node.FalseBlock = newValue;
					}
				}

				LeaveIfStatement(node);
			}
		}

		public virtual bool EnterIfStatement(Boo.Lang.Compiler.Ast.IfStatement node)
		{
			return true;
		}
		
		public virtual void LeaveIfStatement(Boo.Lang.Compiler.Ast.IfStatement node)
		{
		}

		public virtual void OnUnlessStatement(Boo.Lang.Compiler.Ast.UnlessStatement node)
		{	
			if (EnterUnlessStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Expression currentConditionValue = node.Condition;
				if (null != currentConditionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentConditionValue);
					if (!object.ReferenceEquals(newValue, currentConditionValue))
					{
						node.Condition = newValue;
					}
				}
				Block currentBlockValue = node.Block;
				if (null != currentBlockValue)
				{			
					Block newValue = (Block)VisitNode(currentBlockValue);
					if (!object.ReferenceEquals(newValue, currentBlockValue))
					{
						node.Block = newValue;
					}
				}

				LeaveUnlessStatement(node);
			}
		}

		public virtual bool EnterUnlessStatement(Boo.Lang.Compiler.Ast.UnlessStatement node)
		{
			return true;
		}
		
		public virtual void LeaveUnlessStatement(Boo.Lang.Compiler.Ast.UnlessStatement node)
		{
		}

		public virtual void OnForStatement(Boo.Lang.Compiler.Ast.ForStatement node)
		{	
			if (EnterForStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Visit(node.Declarations);
				Expression currentIteratorValue = node.Iterator;
				if (null != currentIteratorValue)
				{			
					Expression newValue = (Expression)VisitNode(currentIteratorValue);
					if (!object.ReferenceEquals(newValue, currentIteratorValue))
					{
						node.Iterator = newValue;
					}
				}
				Block currentBlockValue = node.Block;
				if (null != currentBlockValue)
				{			
					Block newValue = (Block)VisitNode(currentBlockValue);
					if (!object.ReferenceEquals(newValue, currentBlockValue))
					{
						node.Block = newValue;
					}
				}

				LeaveForStatement(node);
			}
		}

		public virtual bool EnterForStatement(Boo.Lang.Compiler.Ast.ForStatement node)
		{
			return true;
		}
		
		public virtual void LeaveForStatement(Boo.Lang.Compiler.Ast.ForStatement node)
		{
		}

		public virtual void OnWhileStatement(Boo.Lang.Compiler.Ast.WhileStatement node)
		{	
			if (EnterWhileStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Expression currentConditionValue = node.Condition;
				if (null != currentConditionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentConditionValue);
					if (!object.ReferenceEquals(newValue, currentConditionValue))
					{
						node.Condition = newValue;
					}
				}
				Block currentBlockValue = node.Block;
				if (null != currentBlockValue)
				{			
					Block newValue = (Block)VisitNode(currentBlockValue);
					if (!object.ReferenceEquals(newValue, currentBlockValue))
					{
						node.Block = newValue;
					}
				}

				LeaveWhileStatement(node);
			}
		}

		public virtual bool EnterWhileStatement(Boo.Lang.Compiler.Ast.WhileStatement node)
		{
			return true;
		}
		
		public virtual void LeaveWhileStatement(Boo.Lang.Compiler.Ast.WhileStatement node)
		{
		}

		public virtual void OnGivenStatement(Boo.Lang.Compiler.Ast.GivenStatement node)
		{	
			if (EnterGivenStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Expression currentExpressionValue = node.Expression;
				if (null != currentExpressionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentExpressionValue);
					if (!object.ReferenceEquals(newValue, currentExpressionValue))
					{
						node.Expression = newValue;
					}
				}
				Visit(node.WhenClauses);
				Block currentOtherwiseBlockValue = node.OtherwiseBlock;
				if (null != currentOtherwiseBlockValue)
				{			
					Block newValue = (Block)VisitNode(currentOtherwiseBlockValue);
					if (!object.ReferenceEquals(newValue, currentOtherwiseBlockValue))
					{
						node.OtherwiseBlock = newValue;
					}
				}

				LeaveGivenStatement(node);
			}
		}

		public virtual bool EnterGivenStatement(Boo.Lang.Compiler.Ast.GivenStatement node)
		{
			return true;
		}
		
		public virtual void LeaveGivenStatement(Boo.Lang.Compiler.Ast.GivenStatement node)
		{
		}

		public virtual void OnWhenClause(Boo.Lang.Compiler.Ast.WhenClause node)
		{	
			if (EnterWhenClause(node))
			{
				Expression currentConditionValue = node.Condition;
				if (null != currentConditionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentConditionValue);
					if (!object.ReferenceEquals(newValue, currentConditionValue))
					{
						node.Condition = newValue;
					}
				}
				Block currentBlockValue = node.Block;
				if (null != currentBlockValue)
				{			
					Block newValue = (Block)VisitNode(currentBlockValue);
					if (!object.ReferenceEquals(newValue, currentBlockValue))
					{
						node.Block = newValue;
					}
				}

				LeaveWhenClause(node);
			}
		}

		public virtual bool EnterWhenClause(Boo.Lang.Compiler.Ast.WhenClause node)
		{
			return true;
		}
		
		public virtual void LeaveWhenClause(Boo.Lang.Compiler.Ast.WhenClause node)
		{
		}

		public virtual void OnBreakStatement(Boo.Lang.Compiler.Ast.BreakStatement node)
		{	
			if (EnterBreakStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}

				LeaveBreakStatement(node);
			}
		}

		public virtual bool EnterBreakStatement(Boo.Lang.Compiler.Ast.BreakStatement node)
		{
			return true;
		}
		
		public virtual void LeaveBreakStatement(Boo.Lang.Compiler.Ast.BreakStatement node)
		{
		}

		public virtual void OnContinueStatement(Boo.Lang.Compiler.Ast.ContinueStatement node)
		{	
			if (EnterContinueStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}

				LeaveContinueStatement(node);
			}
		}

		public virtual bool EnterContinueStatement(Boo.Lang.Compiler.Ast.ContinueStatement node)
		{
			return true;
		}
		
		public virtual void LeaveContinueStatement(Boo.Lang.Compiler.Ast.ContinueStatement node)
		{
		}

		public virtual void OnReturnStatement(Boo.Lang.Compiler.Ast.ReturnStatement node)
		{	
			if (EnterReturnStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Expression currentExpressionValue = node.Expression;
				if (null != currentExpressionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentExpressionValue);
					if (!object.ReferenceEquals(newValue, currentExpressionValue))
					{
						node.Expression = newValue;
					}
				}

				LeaveReturnStatement(node);
			}
		}

		public virtual bool EnterReturnStatement(Boo.Lang.Compiler.Ast.ReturnStatement node)
		{
			return true;
		}
		
		public virtual void LeaveReturnStatement(Boo.Lang.Compiler.Ast.ReturnStatement node)
		{
		}

		public virtual void OnYieldStatement(Boo.Lang.Compiler.Ast.YieldStatement node)
		{	
			if (EnterYieldStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Expression currentExpressionValue = node.Expression;
				if (null != currentExpressionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentExpressionValue);
					if (!object.ReferenceEquals(newValue, currentExpressionValue))
					{
						node.Expression = newValue;
					}
				}

				LeaveYieldStatement(node);
			}
		}

		public virtual bool EnterYieldStatement(Boo.Lang.Compiler.Ast.YieldStatement node)
		{
			return true;
		}
		
		public virtual void LeaveYieldStatement(Boo.Lang.Compiler.Ast.YieldStatement node)
		{
		}

		public virtual void OnRaiseStatement(Boo.Lang.Compiler.Ast.RaiseStatement node)
		{	
			if (EnterRaiseStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Expression currentExceptionValue = node.Exception;
				if (null != currentExceptionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentExceptionValue);
					if (!object.ReferenceEquals(newValue, currentExceptionValue))
					{
						node.Exception = newValue;
					}
				}

				LeaveRaiseStatement(node);
			}
		}

		public virtual bool EnterRaiseStatement(Boo.Lang.Compiler.Ast.RaiseStatement node)
		{
			return true;
		}
		
		public virtual void LeaveRaiseStatement(Boo.Lang.Compiler.Ast.RaiseStatement node)
		{
		}

		public virtual void OnUnpackStatement(Boo.Lang.Compiler.Ast.UnpackStatement node)
		{	
			if (EnterUnpackStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Visit(node.Declarations);
				Expression currentExpressionValue = node.Expression;
				if (null != currentExpressionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentExpressionValue);
					if (!object.ReferenceEquals(newValue, currentExpressionValue))
					{
						node.Expression = newValue;
					}
				}

				LeaveUnpackStatement(node);
			}
		}

		public virtual bool EnterUnpackStatement(Boo.Lang.Compiler.Ast.UnpackStatement node)
		{
			return true;
		}
		
		public virtual void LeaveUnpackStatement(Boo.Lang.Compiler.Ast.UnpackStatement node)
		{
		}

		public virtual void OnExpressionStatement(Boo.Lang.Compiler.Ast.ExpressionStatement node)
		{	
			if (EnterExpressionStatement(node))
			{
				StatementModifier currentModifierValue = node.Modifier;
				if (null != currentModifierValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentModifierValue);
					if (!object.ReferenceEquals(newValue, currentModifierValue))
					{
						node.Modifier = newValue;
					}
				}
				Expression currentExpressionValue = node.Expression;
				if (null != currentExpressionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentExpressionValue);
					if (!object.ReferenceEquals(newValue, currentExpressionValue))
					{
						node.Expression = newValue;
					}
				}

				LeaveExpressionStatement(node);
			}
		}

		public virtual bool EnterExpressionStatement(Boo.Lang.Compiler.Ast.ExpressionStatement node)
		{
			return true;
		}
		
		public virtual void LeaveExpressionStatement(Boo.Lang.Compiler.Ast.ExpressionStatement node)
		{
		}

		public virtual void OnOmittedExpression(Boo.Lang.Compiler.Ast.OmittedExpression node)
		{	
		}

		public virtual void OnExpressionPair(Boo.Lang.Compiler.Ast.ExpressionPair node)
		{	
			if (EnterExpressionPair(node))
			{
				Expression currentFirstValue = node.First;
				if (null != currentFirstValue)
				{			
					Expression newValue = (Expression)VisitNode(currentFirstValue);
					if (!object.ReferenceEquals(newValue, currentFirstValue))
					{
						node.First = newValue;
					}
				}
				Expression currentSecondValue = node.Second;
				if (null != currentSecondValue)
				{			
					Expression newValue = (Expression)VisitNode(currentSecondValue);
					if (!object.ReferenceEquals(newValue, currentSecondValue))
					{
						node.Second = newValue;
					}
				}

				LeaveExpressionPair(node);
			}
		}

		public virtual bool EnterExpressionPair(Boo.Lang.Compiler.Ast.ExpressionPair node)
		{
			return true;
		}
		
		public virtual void LeaveExpressionPair(Boo.Lang.Compiler.Ast.ExpressionPair node)
		{
		}

		public virtual void OnMethodInvocationExpression(Boo.Lang.Compiler.Ast.MethodInvocationExpression node)
		{	
			if (EnterMethodInvocationExpression(node))
			{
				Expression currentTargetValue = node.Target;
				if (null != currentTargetValue)
				{			
					Expression newValue = (Expression)VisitNode(currentTargetValue);
					if (!object.ReferenceEquals(newValue, currentTargetValue))
					{
						node.Target = newValue;
					}
				}
				Visit(node.Arguments);
				Visit(node.NamedArguments);

				LeaveMethodInvocationExpression(node);
			}
		}

		public virtual bool EnterMethodInvocationExpression(Boo.Lang.Compiler.Ast.MethodInvocationExpression node)
		{
			return true;
		}
		
		public virtual void LeaveMethodInvocationExpression(Boo.Lang.Compiler.Ast.MethodInvocationExpression node)
		{
		}

		public virtual void OnUnaryExpression(Boo.Lang.Compiler.Ast.UnaryExpression node)
		{	
			if (EnterUnaryExpression(node))
			{
				Expression currentOperandValue = node.Operand;
				if (null != currentOperandValue)
				{			
					Expression newValue = (Expression)VisitNode(currentOperandValue);
					if (!object.ReferenceEquals(newValue, currentOperandValue))
					{
						node.Operand = newValue;
					}
				}

				LeaveUnaryExpression(node);
			}
		}

		public virtual bool EnterUnaryExpression(Boo.Lang.Compiler.Ast.UnaryExpression node)
		{
			return true;
		}
		
		public virtual void LeaveUnaryExpression(Boo.Lang.Compiler.Ast.UnaryExpression node)
		{
		}

		public virtual void OnBinaryExpression(Boo.Lang.Compiler.Ast.BinaryExpression node)
		{	
			if (EnterBinaryExpression(node))
			{
				Expression currentLeftValue = node.Left;
				if (null != currentLeftValue)
				{			
					Expression newValue = (Expression)VisitNode(currentLeftValue);
					if (!object.ReferenceEquals(newValue, currentLeftValue))
					{
						node.Left = newValue;
					}
				}
				Expression currentRightValue = node.Right;
				if (null != currentRightValue)
				{			
					Expression newValue = (Expression)VisitNode(currentRightValue);
					if (!object.ReferenceEquals(newValue, currentRightValue))
					{
						node.Right = newValue;
					}
				}

				LeaveBinaryExpression(node);
			}
		}

		public virtual bool EnterBinaryExpression(Boo.Lang.Compiler.Ast.BinaryExpression node)
		{
			return true;
		}
		
		public virtual void LeaveBinaryExpression(Boo.Lang.Compiler.Ast.BinaryExpression node)
		{
		}

		public virtual void OnConditionalExpression(Boo.Lang.Compiler.Ast.ConditionalExpression node)
		{	
			if (EnterConditionalExpression(node))
			{
				Expression currentConditionValue = node.Condition;
				if (null != currentConditionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentConditionValue);
					if (!object.ReferenceEquals(newValue, currentConditionValue))
					{
						node.Condition = newValue;
					}
				}
				Expression currentTrueValueValue = node.TrueValue;
				if (null != currentTrueValueValue)
				{			
					Expression newValue = (Expression)VisitNode(currentTrueValueValue);
					if (!object.ReferenceEquals(newValue, currentTrueValueValue))
					{
						node.TrueValue = newValue;
					}
				}
				Expression currentFalseValueValue = node.FalseValue;
				if (null != currentFalseValueValue)
				{			
					Expression newValue = (Expression)VisitNode(currentFalseValueValue);
					if (!object.ReferenceEquals(newValue, currentFalseValueValue))
					{
						node.FalseValue = newValue;
					}
				}

				LeaveConditionalExpression(node);
			}
		}

		public virtual bool EnterConditionalExpression(Boo.Lang.Compiler.Ast.ConditionalExpression node)
		{
			return true;
		}
		
		public virtual void LeaveConditionalExpression(Boo.Lang.Compiler.Ast.ConditionalExpression node)
		{
		}

		public virtual void OnReferenceExpression(Boo.Lang.Compiler.Ast.ReferenceExpression node)
		{	
		}

		public virtual void OnMemberReferenceExpression(Boo.Lang.Compiler.Ast.MemberReferenceExpression node)
		{	
			if (EnterMemberReferenceExpression(node))
			{
				Expression currentTargetValue = node.Target;
				if (null != currentTargetValue)
				{			
					Expression newValue = (Expression)VisitNode(currentTargetValue);
					if (!object.ReferenceEquals(newValue, currentTargetValue))
					{
						node.Target = newValue;
					}
				}

				LeaveMemberReferenceExpression(node);
			}
		}

		public virtual bool EnterMemberReferenceExpression(Boo.Lang.Compiler.Ast.MemberReferenceExpression node)
		{
			return true;
		}
		
		public virtual void LeaveMemberReferenceExpression(Boo.Lang.Compiler.Ast.MemberReferenceExpression node)
		{
		}

		public virtual void OnGenericReferenceExpression(Boo.Lang.Compiler.Ast.GenericReferenceExpression node)
		{	
			if (EnterGenericReferenceExpression(node))
			{
				Expression currentTargetValue = node.Target;
				if (null != currentTargetValue)
				{			
					Expression newValue = (Expression)VisitNode(currentTargetValue);
					if (!object.ReferenceEquals(newValue, currentTargetValue))
					{
						node.Target = newValue;
					}
				}
				Visit(node.GenericArguments);

				LeaveGenericReferenceExpression(node);
			}
		}

		public virtual bool EnterGenericReferenceExpression(Boo.Lang.Compiler.Ast.GenericReferenceExpression node)
		{
			return true;
		}
		
		public virtual void LeaveGenericReferenceExpression(Boo.Lang.Compiler.Ast.GenericReferenceExpression node)
		{
		}

		public virtual void OnAstLiteralExpression(Boo.Lang.Compiler.Ast.AstLiteralExpression node)
		{	
		}

		public virtual void OnStringLiteralExpression(Boo.Lang.Compiler.Ast.StringLiteralExpression node)
		{	
		}

		public virtual void OnCharLiteralExpression(Boo.Lang.Compiler.Ast.CharLiteralExpression node)
		{	
		}

		public virtual void OnTimeSpanLiteralExpression(Boo.Lang.Compiler.Ast.TimeSpanLiteralExpression node)
		{	
		}

		public virtual void OnIntegerLiteralExpression(Boo.Lang.Compiler.Ast.IntegerLiteralExpression node)
		{	
		}

		public virtual void OnDoubleLiteralExpression(Boo.Lang.Compiler.Ast.DoubleLiteralExpression node)
		{	
		}

		public virtual void OnNullLiteralExpression(Boo.Lang.Compiler.Ast.NullLiteralExpression node)
		{	
		}

		public virtual void OnSelfLiteralExpression(Boo.Lang.Compiler.Ast.SelfLiteralExpression node)
		{	
		}

		public virtual void OnSuperLiteralExpression(Boo.Lang.Compiler.Ast.SuperLiteralExpression node)
		{	
		}

		public virtual void OnBoolLiteralExpression(Boo.Lang.Compiler.Ast.BoolLiteralExpression node)
		{	
		}

		public virtual void OnRELiteralExpression(Boo.Lang.Compiler.Ast.RELiteralExpression node)
		{	
		}

		public virtual void OnExpressionInterpolationExpression(Boo.Lang.Compiler.Ast.ExpressionInterpolationExpression node)
		{	
			if (EnterExpressionInterpolationExpression(node))
			{
				Visit(node.Expressions);

				LeaveExpressionInterpolationExpression(node);
			}
		}

		public virtual bool EnterExpressionInterpolationExpression(Boo.Lang.Compiler.Ast.ExpressionInterpolationExpression node)
		{
			return true;
		}
		
		public virtual void LeaveExpressionInterpolationExpression(Boo.Lang.Compiler.Ast.ExpressionInterpolationExpression node)
		{
		}

		public virtual void OnHashLiteralExpression(Boo.Lang.Compiler.Ast.HashLiteralExpression node)
		{	
			if (EnterHashLiteralExpression(node))
			{
				Visit(node.Items);

				LeaveHashLiteralExpression(node);
			}
		}

		public virtual bool EnterHashLiteralExpression(Boo.Lang.Compiler.Ast.HashLiteralExpression node)
		{
			return true;
		}
		
		public virtual void LeaveHashLiteralExpression(Boo.Lang.Compiler.Ast.HashLiteralExpression node)
		{
		}

		public virtual void OnListLiteralExpression(Boo.Lang.Compiler.Ast.ListLiteralExpression node)
		{	
			if (EnterListLiteralExpression(node))
			{
				Visit(node.Items);

				LeaveListLiteralExpression(node);
			}
		}

		public virtual bool EnterListLiteralExpression(Boo.Lang.Compiler.Ast.ListLiteralExpression node)
		{
			return true;
		}
		
		public virtual void LeaveListLiteralExpression(Boo.Lang.Compiler.Ast.ListLiteralExpression node)
		{
		}

		public virtual void OnArrayLiteralExpression(Boo.Lang.Compiler.Ast.ArrayLiteralExpression node)
		{	
			if (EnterArrayLiteralExpression(node))
			{
				Visit(node.Items);
				ArrayTypeReference currentTypeValue = node.Type;
				if (null != currentTypeValue)
				{			
					ArrayTypeReference newValue = (ArrayTypeReference)VisitNode(currentTypeValue);
					if (!object.ReferenceEquals(newValue, currentTypeValue))
					{
						node.Type = newValue;
					}
				}

				LeaveArrayLiteralExpression(node);
			}
		}

		public virtual bool EnterArrayLiteralExpression(Boo.Lang.Compiler.Ast.ArrayLiteralExpression node)
		{
			return true;
		}
		
		public virtual void LeaveArrayLiteralExpression(Boo.Lang.Compiler.Ast.ArrayLiteralExpression node)
		{
		}

		public virtual void OnGeneratorExpression(Boo.Lang.Compiler.Ast.GeneratorExpression node)
		{	
			if (EnterGeneratorExpression(node))
			{
				Expression currentExpressionValue = node.Expression;
				if (null != currentExpressionValue)
				{			
					Expression newValue = (Expression)VisitNode(currentExpressionValue);
					if (!object.ReferenceEquals(newValue, currentExpressionValue))
					{
						node.Expression = newValue;
					}
				}
				Visit(node.Declarations);
				Expression currentIteratorValue = node.Iterator;
				if (null != currentIteratorValue)
				{			
					Expression newValue = (Expression)VisitNode(currentIteratorValue);
					if (!object.ReferenceEquals(newValue, currentIteratorValue))
					{
						node.Iterator = newValue;
					}
				}
				StatementModifier currentFilterValue = node.Filter;
				if (null != currentFilterValue)
				{			
					StatementModifier newValue = (StatementModifier)VisitNode(currentFilterValue);
					if (!object.ReferenceEquals(newValue, currentFilterValue))
					{
						node.Filter = newValue;
					}
				}

				LeaveGeneratorExpression(node);
			}
		}

		public virtual bool EnterGeneratorExpression(Boo.Lang.Compiler.Ast.GeneratorExpression node)
		{
			return true;
		}
		
		public virtual void LeaveGeneratorExpression(Boo.Lang.Compiler.Ast.GeneratorExpression node)
		{
		}

		public virtual void OnExtendedGeneratorExpression(Boo.Lang.Compiler.Ast.ExtendedGeneratorExpression node)
		{	
			if (EnterExtendedGeneratorExpression(node))
			{
				Visit(node.Items);

				LeaveExtendedGeneratorExpression(node);
			}
		}

		public virtual bool EnterExtendedGeneratorExpression(Boo.Lang.Compiler.Ast.ExtendedGeneratorExpression node)
		{
			return true;
		}
		
		public virtual void LeaveExtendedGeneratorExpression(Boo.Lang.Compiler.Ast.ExtendedGeneratorExpression node)
		{
		}

		public virtual void OnSlice(Boo.Lang.Compiler.Ast.Slice node)
		{	
			if (EnterSlice(node))
			{
				Expression currentBeginValue = node.Begin;
				if (null != currentBeginValue)
				{			
					Expression newValue = (Expression)VisitNode(currentBeginValue);
					if (!object.ReferenceEquals(newValue, currentBeginValue))
					{
						node.Begin = newValue;
					}
				}
				Expression currentEndValue = node.End;
				if (null != currentEndValue)
				{			
					Expression newValue = (Expression)VisitNode(currentEndValue);
					if (!object.ReferenceEquals(newValue, currentEndValue))
					{
						node.End = newValue;
					}
				}
				Expression currentStepValue = node.Step;
				if (null != currentStepValue)
				{			
					Expression newValue = (Expression)VisitNode(currentStepValue);
					if (!object.ReferenceEquals(newValue, currentStepValue))
					{
						node.Step = newValue;
					}
				}

				LeaveSlice(node);
			}
		}

		public virtual bool EnterSlice(Boo.Lang.Compiler.Ast.Slice node)
		{
			return true;
		}
		
		public virtual void LeaveSlice(Boo.Lang.Compiler.Ast.Slice node)
		{
		}

		public virtual void OnSlicingExpression(Boo.Lang.Compiler.Ast.SlicingExpression node)
		{	
			if (EnterSlicingExpression(node))
			{
				Expression currentTargetValue = node.Target;
				if (null != currentTargetValue)
				{			
					Expression newValue = (Expression)VisitNode(currentTargetValue);
					if (!object.ReferenceEquals(newValue, currentTargetValue))
					{
						node.Target = newValue;
					}
				}
				Visit(node.Indices);

				LeaveSlicingExpression(node);
			}
		}

		public virtual bool EnterSlicingExpression(Boo.Lang.Compiler.Ast.SlicingExpression node)
		{
			return true;
		}
		
		public virtual void LeaveSlicingExpression(Boo.Lang.Compiler.Ast.SlicingExpression node)
		{
		}

		public virtual void OnTryCastExpression(Boo.Lang.Compiler.Ast.TryCastExpression node)
		{	
			if (EnterTryCastExpression(node))
			{
				Expression currentTargetValue = node.Target;
				if (null != currentTargetValue)
				{			
					Expression newValue = (Expression)VisitNode(currentTargetValue);
					if (!object.ReferenceEquals(newValue, currentTargetValue))
					{
						node.Target = newValue;
					}
				}
				TypeReference currentTypeValue = node.Type;
				if (null != currentTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentTypeValue);
					if (!object.ReferenceEquals(newValue, currentTypeValue))
					{
						node.Type = newValue;
					}
				}

				LeaveTryCastExpression(node);
			}
		}

		public virtual bool EnterTryCastExpression(Boo.Lang.Compiler.Ast.TryCastExpression node)
		{
			return true;
		}
		
		public virtual void LeaveTryCastExpression(Boo.Lang.Compiler.Ast.TryCastExpression node)
		{
		}

		public virtual void OnCastExpression(Boo.Lang.Compiler.Ast.CastExpression node)
		{	
			if (EnterCastExpression(node))
			{
				Expression currentTargetValue = node.Target;
				if (null != currentTargetValue)
				{			
					Expression newValue = (Expression)VisitNode(currentTargetValue);
					if (!object.ReferenceEquals(newValue, currentTargetValue))
					{
						node.Target = newValue;
					}
				}
				TypeReference currentTypeValue = node.Type;
				if (null != currentTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentTypeValue);
					if (!object.ReferenceEquals(newValue, currentTypeValue))
					{
						node.Type = newValue;
					}
				}

				LeaveCastExpression(node);
			}
		}

		public virtual bool EnterCastExpression(Boo.Lang.Compiler.Ast.CastExpression node)
		{
			return true;
		}
		
		public virtual void LeaveCastExpression(Boo.Lang.Compiler.Ast.CastExpression node)
		{
		}

		public virtual void OnTypeofExpression(Boo.Lang.Compiler.Ast.TypeofExpression node)
		{	
			if (EnterTypeofExpression(node))
			{
				TypeReference currentTypeValue = node.Type;
				if (null != currentTypeValue)
				{			
					TypeReference newValue = (TypeReference)VisitNode(currentTypeValue);
					if (!object.ReferenceEquals(newValue, currentTypeValue))
					{
						node.Type = newValue;
					}
				}

				LeaveTypeofExpression(node);
			}
		}

		public virtual bool EnterTypeofExpression(Boo.Lang.Compiler.Ast.TypeofExpression node)
		{
			return true;
		}
		
		public virtual void LeaveTypeofExpression(Boo.Lang.Compiler.Ast.TypeofExpression node)
		{
		}
		
		protected virtual void RemoveCurrentNode()
		{
			_resultingNode = null;
		}
		
		protected virtual void ReplaceCurrentNode(Node replacement)
		{
			_resultingNode = replacement;
		}
		
		protected virtual void OnNode(Node node)
		{
			node.Accept(this);
		}
		
		public virtual Node VisitNode(Node node)
		{
			if (null != node)
			{
				try
				{
					Node saved = _resultingNode;
					_resultingNode = node;
					OnNode(node);
					Node result = _resultingNode;
					_resultingNode = saved;
					return result;
				}
				catch (Boo.Lang.Compiler.CompilerError)
				{
					throw;
				}
				catch (Exception error)
				{
					OnError(node, error);
				}
			}
			return null;
		}
		
		protected virtual void OnError(Node node, Exception error)
		{
			throw Boo.Lang.Compiler.CompilerErrorFactory.InternalError(node, error);
		}
		
		public Node Visit(Node node)
		{
			return VisitNode(node);
		}
		
		public Expression Visit(Expression node)
		{
			return (Expression)VisitNode(node);
		}
		
		public Statement Visit(Statement node)
		{
			return (Statement)VisitNode(node);
		}
		
		public virtual bool Visit(NodeCollection collection)
		{
			if (null != collection)
			{
				int removed = 0;
				
				Node[] nodes = collection.ToArray();
				for (int i=0; i<nodes.Length; ++i)
				{					
					Node currentNode = nodes[i];
					Node resultingNode = VisitNode(currentNode);
					if (currentNode != resultingNode)
					{
						int actualIndex = i-removed;
						if (null == resultingNode)
						{
							++removed;
							collection.RemoveAt(actualIndex);
						}
						else
						{
							collection.ReplaceAt(actualIndex, resultingNode);
						}
					}
				}
				return true;
			}
			return false;
		}
	}
}
