diff --git a/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs b/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
index d41814054..77ff1c8c6 100644
--- a/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
+++ b/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
@@ -25,10 +25,8 @@ using System.Windows.Media;
 using ICSharpCode.AvalonEdit.Editing;
 using ICSharpCode.AvalonEdit.Rendering;
 using ICSharpCode.AvalonEdit.Utils;
-using ICSharpCode.Decompiler.Disassembler;
 using ILSpy.Debugger.Bookmarks;
 using ILSpy.Debugger.Services;
-using ILSpy.Debugger.ToolTips;
 using Mono.Cecil;
 
 namespace ILSpy.Debugger.AvalonEdit
@@ -74,7 +72,7 @@ namespace ILSpy.Debugger.AvalonEdit
 				// create a dictionary line number => first bookmark
 				Dictionary<int, BookmarkBase> bookmarkDict = new Dictionary<int, BookmarkBase>();
 				foreach (var bm in BookmarkManager.Bookmarks) {
-					if (IconBarMargin.CurrentType == null || bm.TypeName != IconBarMargin.CurrentType.FullName)
+					if (CurrentType == null || bm.TypeName != CurrentType.FullName)
 						continue;
 					
 					int line = bm.LineNumber;
@@ -88,10 +86,44 @@ namespace ILSpy.Debugger.AvalonEdit
 					BookmarkBase bm;
 					if (bookmarkDict.TryGetValue(lineNumber, out bm)) {
 						Rect rect = new Rect(0, PixelSnapHelpers.Round(line.VisualTop - textView.VerticalOffset, pixelSize.Height), 16, 16);
-						drawingContext.DrawImage(bm.Image, rect);						
+						if (dragDropBookmark == bm && dragStarted)
+							drawingContext.PushOpacity(0.5);
+						drawingContext.DrawImage(bm.Image, rect);
+						if (dragDropBookmark == bm && dragStarted)
+							drawingContext.Pop();
 					}
-				}				
+				}
+				if (dragDropBookmark != null && dragStarted) {
+					Rect rect = new Rect(0, PixelSnapHelpers.Round(dragDropCurrentPoint - 8, pixelSize.Height), 16, 16);
+					drawingContext.DrawImage(dragDropBookmark.Image, rect);
+				}
+			}
+		}
+		
+		IBookmark dragDropBookmark; // bookmark being dragged (!=null if drag'n'drop is active)
+		double dragDropStartPoint;
+		double dragDropCurrentPoint;
+		bool dragStarted; // whether drag'n'drop operation has started (mouse was moved minimum distance)
+		
+		protected override void OnMouseDown(MouseButtonEventArgs e)
+		{
+			base.OnMouseDown(e);
+			int line = GetLineFromMousePosition(e);
+			if (!e.Handled && line > 0) {
+				IBookmark bm = GetBookmarkFromLine(line);
+				if (bm != null) {
+					bm.MouseDown(e);
+					if (!e.Handled) {
+						if (e.ChangedButton == MouseButton.Left && bm.CanDragDrop && CaptureMouse()) {
+							StartDragDrop(bm, e);
+							e.Handled = true;
+						}
+					}
+				}
 			}
+			// don't allow selecting text through the IconBarMargin
+			if (e.ChangedButton == MouseButton.Left)
+				e.Handled = true;
 		}
 		
 		BookmarkBase GetBookmarkFromLine(int line)
@@ -99,8 +131,8 @@ namespace ILSpy.Debugger.AvalonEdit
 			BookmarkBase result = null;
 			foreach (BookmarkBase bm in BookmarkManager.Bookmarks) {
 				if (bm.LineNumber == line &&
-				    IconBarMargin.CurrentType != null &&
-				    bm.TypeName == IconBarMargin.CurrentType.FullName) {
+				    CurrentType != null &&
+				    bm.TypeName == CurrentType.FullName) {
 					if (result == null || bm.ZOrder > result.ZOrder)
 						result = bm;
 				}
@@ -108,6 +140,46 @@ namespace ILSpy.Debugger.AvalonEdit
 			return result;
 		}
 		
+		protected override void OnLostMouseCapture(MouseEventArgs e)
+		{
+			CancelDragDrop();
+			base.OnLostMouseCapture(e);
+		}
+		
+		void StartDragDrop(IBookmark bm, MouseEventArgs e)
+		{
+			dragDropBookmark = bm;
+			dragDropStartPoint = dragDropCurrentPoint = e.GetPosition(this).Y;
+			if (TextView != null) {
+				TextArea area = TextView.Services.GetService(typeof(TextArea)) as TextArea;
+				if (area != null)
+					area.PreviewKeyDown += TextArea_PreviewKeyDown;
+			}
+		}
+		
+		void CancelDragDrop()
+		{
+			if (dragDropBookmark != null) {
+				dragDropBookmark = null;
+				dragStarted = false;
+				if (TextView != null) {
+					TextArea area = TextView.Services.GetService(typeof(TextArea)) as TextArea;
+					if (area != null)
+						area.PreviewKeyDown -= TextArea_PreviewKeyDown;
+				}
+				ReleaseMouseCapture();
+				InvalidateVisual();
+			}
+		}
+		
+		void TextArea_PreviewKeyDown(object sender, KeyEventArgs e)
+		{
+			// any key press cancels drag'n'drop
+			CancelDragDrop();
+			if (e.Key == Key.Escape)
+				e.Handled = true;
+		}
+		
 		int GetLineFromMousePosition(MouseEventArgs e)
 		{
 			TextView textView = this.TextView;
@@ -119,10 +191,29 @@ namespace ILSpy.Debugger.AvalonEdit
 			return vl.FirstDocumentLine.LineNumber;
 		}
 		
+		protected override void OnMouseMove(MouseEventArgs e)
+		{
+			base.OnMouseMove(e);
+			if (dragDropBookmark != null) {
+				dragDropCurrentPoint = e.GetPosition(this).Y;
+				if (Math.Abs(dragDropCurrentPoint - dragDropStartPoint) > SystemParameters.MinimumVerticalDragDistance)
+					dragStarted = true;
+				InvalidateVisual();
+			}
+		}
+		
 		protected override void OnMouseUp(MouseButtonEventArgs e)
 		{
 			base.OnMouseUp(e);
 			int line = GetLineFromMousePosition(e);
+			if (!e.Handled && dragDropBookmark != null) {
+				if (dragStarted) {
+					if (line != 0)
+						dragDropBookmark.Drop(line);
+					e.Handled = true;
+				}
+				CancelDragDrop();
+			}
 			if (!e.Handled && line != 0) {
 				IBookmark bm = GetBookmarkFromLine(line);
 				if (bm != null) {
@@ -144,4 +235,4 @@ namespace ILSpy.Debugger.AvalonEdit
 			}
 		}
 	}
-}
+}
\ No newline at end of file
diff --git a/Decompiler/.gitignore b/Decompiler/.gitignore
deleted file mode 100644
index c75695746..000000000
--- a/Decompiler/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-bin/
-obj/
\ No newline at end of file
diff --git a/Decompiler/tests/QuickSort/AssemblyInfo.cs b/Decompiler/tests/QuickSort/AssemblyInfo.cs
deleted file mode 100644
index 0386c7e48..000000000
--- a/Decompiler/tests/QuickSort/AssemblyInfo.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-#region Using directives
-
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-#endregion
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("QuickSort")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("QuickSort")]
-[assembly: AssemblyCopyright("")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// This sets the default COM visibility of types in the assembly to invisible.
-// If you need to expose a type to COM, use [ComVisible(true)] on that type.
-[assembly: ComVisible(false)]
-
-// The assembly version has following format :
-//
-// Major.Minor.Build.Revision
-//
-// You can specify all the values or you can use the default the Revision and 
-// Build Numbers by using the '*' as shown below:
-[assembly: AssemblyVersion("1.0.*")]
diff --git a/Decompiler/tests/QuickSort/Program.cs b/Decompiler/tests/QuickSort/Program.cs
deleted file mode 100644
index 4cb22fe3b..000000000
--- a/Decompiler/tests/QuickSort/Program.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-static class QuickSortProgram
-{
-	public static void Main(string[] args)
-	{
-		int[] intArray = new int[args.Length];
-		for (int i = 0; i < intArray.Length; i++) {
-			intArray[i] = int.Parse(args[i]);
-		}
-		QuickSort(intArray, 0, intArray.Length - 1);
-		for (int i = 0; i < intArray.Length; i++) {
-			System.Console.Write(intArray[i].ToString() + " ");
-		}
-	}
-	
-	/// For description of this algorithm see:
-	/// http://en.wikipedia.org/wiki/Quick_sort
-	public static void QuickSort(int[] array, int left, int right)
-	{
-		if (right > left) {
-			int pivotIndex = (left + right) / 2;
-			int pivotNew = Partition(array, left, right, pivotIndex);
-			QuickSort(array, left, pivotNew - 1);
-			QuickSort(array, pivotNew + 1, right);
-		}
-	}
-	
-	static int Partition(int[] array, int left, int right,
-	                     int pivotIndex)
-	{
-		int pivotValue = array[pivotIndex];
-		Swap(array, pivotIndex, right);
-		int storeIndex = left;
-		for(int i = left; i < right; i++) {
-			if (array[i] <= pivotValue) {
-				Swap(array, storeIndex, i);
-				storeIndex = storeIndex + 1;
-			}
-		}
-		Swap(array, right, storeIndex);
-		return storeIndex;
-	}
-	
-	static void Swap(int[] array, int index1, int index2)
-	{
-		int tmp = array[index1];
-		array[index1] = array[index2];
-		array[index2] = tmp;
-	}
-}
\ No newline at end of file
diff --git a/Decompiler/tests/QuickSort/QuickSort.csproj b/Decompiler/tests/QuickSort/QuickSort.csproj
deleted file mode 100644
index 191c2a69c..000000000
--- a/Decompiler/tests/QuickSort/QuickSort.csproj
+++ /dev/null
@@ -1,36 +0,0 @@
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <ProjectGuid>{9C2A1C63-38EA-42CA-BDDD-7D80D9592893}</ProjectGuid>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <OutputType>Exe</OutputType>
-    <RootNamespace>QuickSort</RootNamespace>
-    <AssemblyName>QuickSort</AssemblyName>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <OutputPath>bin\Debug\</OutputPath>
-    <DebugSymbols>True</DebugSymbols>
-    <DebugType>Full</DebugType>
-    <Optimize>False</Optimize>
-    <CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <OutputPath>bin\Release\</OutputPath>
-    <DebugSymbols>False</DebugSymbols>
-    <DebugType>None</DebugType>
-    <Optimize>True</Optimize>
-    <CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
-    <DefineConstants>TRACE</DefineConstants>
-  </PropertyGroup>
-  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="AssemblyInfo.cs" />
-    <Compile Include="Program.cs" />
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/Decompiler/tests/QuickSort/QuickSort.sln b/Decompiler/tests/QuickSort/QuickSort.sln
deleted file mode 100644
index 8ee47e87f..000000000
--- a/Decompiler/tests/QuickSort/QuickSort.sln
+++ /dev/null
@@ -1,18 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
-# SharpDevelop 3.0.0.2707
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuickSort", "QuickSort.csproj", "{9C2A1C63-38EA-42CA-BDDD-7D80D9592893}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Any CPU = Debug|Any CPU
-		Release|Any CPU = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{9C2A1C63-38EA-42CA-BDDD-7D80D9592893}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{9C2A1C63-38EA-42CA-BDDD-7D80D9592893}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{9C2A1C63-38EA-42CA-BDDD-7D80D9592893}.Release|Any CPU.Build.0 = Release|Any CPU
-		{9C2A1C63-38EA-42CA-BDDD-7D80D9592893}.Release|Any CPU.ActiveCfg = Release|Any CPU
-	EndGlobalSection
-EndGlobal
diff --git a/Decompiler/tests/QuickSort/bin/Debug/QuickSort.exe b/Decompiler/tests/QuickSort/bin/Debug/QuickSort.exe
deleted file mode 100644
index 7e3f98ac5..000000000
Binary files a/Decompiler/tests/QuickSort/bin/Debug/QuickSort.exe and /dev/null differ
diff --git a/Decompiler/tests/QuickSort/bin/Debug/QuickSort.pdb b/Decompiler/tests/QuickSort/bin/Debug/QuickSort.pdb
deleted file mode 100644
index 0ef5b30bf..000000000
Binary files a/Decompiler/tests/QuickSort/bin/Debug/QuickSort.pdb and /dev/null differ
diff --git a/Decompiler/tests/Stack/StackTests.exe b/Decompiler/tests/Stack/StackTests.exe
deleted file mode 100644
index db6194ad6..000000000
Binary files a/Decompiler/tests/Stack/StackTests.exe and /dev/null differ
diff --git a/Decompiler/tests/Stack/StackTests.il b/Decompiler/tests/Stack/StackTests.il
deleted file mode 100644
index 78d50bc19..000000000
--- a/Decompiler/tests/Stack/StackTests.il
+++ /dev/null
@@ -1,135 +0,0 @@
-.assembly extern mscorlib
-{
-  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
-  .ver 4:0:0:0
-}
-.assembly StackTests
-{
-  .hash algorithm 0x00008004
-  .ver 1:0:4059:39717
-}
-.module StackTests.exe
-.imagebase 0x00400000
-.file alignment 0x00000200
-.stackreserve 0x00100000
-.subsystem 0x0003       // WINDOWS_CUI
-.corflags 0x00000003    //  ILONLY 32BITREQUIRED
-
-.class private auto ansi beforefieldinit StackTests.Program extends [mscorlib]System.Object
-{
-  .method public hidebysig static void  Main(string[] args) cil managed
-  {
-    .entrypoint
-    .maxstack  8
-	
-	ldc.i4.0
-	call string StackTests.Program::Test1(bool cond)
-	call void [mscorlib]System.Console::WriteLine(string) // false
-	
-	ldc.i4.1
-	call string StackTests.Program::Test1(bool cond)
-	call void [mscorlib]System.Console::WriteLine(string) // true
-	
-	ldc.i4.0
-	ldc.i4.0
-	ldc.i4.0
-	call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
-	call void [mscorlib]System.Console::WriteLine(int32)  // 11
-	
-	ldc.i4.0
-	ldc.i4.1
-	ldc.i4.0
-	call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
-	call void [mscorlib]System.Console::WriteLine(int32)  // 21
-	
-	ldc.i4.1
-	ldc.i4.1
-	ldc.i4.1
-	call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
-	call void [mscorlib]System.Console::WriteLine(int32)  // 32
-	
-	ldc.i4.2
-	ldc.i4.1
-	ldc.i4.0
-	call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
-	call void [mscorlib]System.Console::WriteLine(int32)  // 23
-	
-	ret
-  }
-
-  .method public hidebysig static string Test1(bool cond) cil managed
-  {
-	ldarg.0
-	brtrue TRUE
-	
-	FALSE:
-	ldstr "false"
-	br EXIT
-		
-	TRUE:
-	ldstr "true"
-		
-	EXIT:
-	ret
-  }
-
-  .method public hidebysig static int32 Test2(int32 switch1, int32 br1, int32 br2) cil managed
-  {
-    ldarg.0
-    switch (ENTRY1, ENTRY2, ENTRY3)
-	ldc.i4.0
-    ret
-
-    ENTRY1:
-	ldc.i4.1
-    br BRANCH1
-
-    ENTRY2:
-	ldc.i4.2
-    br BRANCH1
-
-    ENTRY3:
-	ldc.i4.3
-    br BRANCH2
-	
-	BRANCH1:
-	ldarg.1
-	brtrue BRANCH2
-	
-	EXIT1:
-	ldc.i4 10
-	add
-	ret
-	
-	BRANCH2:
-	ldarg.2
-	brtrue.s EXIT3
-	
-	EXIT2:
-	ldc.i4 20
-	add
-	ret
-	
-	EXIT3:
-	ldc.i4 30
-	add
-	ret
-  }
-
-  .method public hidebysig specialname rtspecialname 
-          instance void  .ctor() cil managed
-  {
-    // Code size       7 (0x7)
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
-    IL_0006:  ret
-  } // end of method Program::.ctor
-
-} // end of class StackTests.Program
-
-
-// =============================================================
-
-// *********** DISASSEMBLY COMPLETE ***********************
-// WARNING: Created Win32 resource file D:\git\ILSpy\Decompiler\tests\Stack\StackTests.res
diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs
index 2e488f385..5116658a5 100644
--- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs
+++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs
@@ -17,28 +17,12 @@ namespace Decompiler
 		
 		public void GenerateCode(ITextOutput output)
 		{
-			for (int i = 0; i < 4; i++) {
-				if (Options.ReduceAstJumps) {
-					//astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveGotos(), null);
-					//astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null);
-				}
-				if (Options.ReduceAstLoops) {
-					//astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null);
-				}
-				if (Options.ReduceAstOther) {
-					astCompileUnit.AcceptVisitor(new Transforms.Ast.Idioms(), null);
-					astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveEmptyElseBody(), null);
-					astCompileUnit.AcceptVisitor(new Transforms.Ast.PushNegation(), null);
-				}
-			}
-			if (Options.ReduceAstOther) {
-				astCompileUnit.AcceptVisitor(new Transforms.Ast.SimplifyTypeReferences(), null);
-				astCompileUnit.AcceptVisitor(new Transforms.Ast.Idioms(), null);
-			}
-			if (Options.ReduceAstLoops) {
-				//astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null);
-			}
-			
+			GenerateCode(output, null);
+		}
+		
+		public void GenerateCode(ITextOutput output, Predicate<IAstVisitor<object, object>> transformAbortCondition)
+		{
+			Transforms.TransformationPipeline.RunTransformationsUntil(astCompileUnit, transformAbortCondition);
 			astCompileUnit.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }, null);
 			
 			var outputFormatter = new TextOutputFormatter(output);
@@ -263,14 +247,18 @@ namespace Decompiler
 					}
 					
 					name = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(name);
-					if (ns.Length == 0)
-						return new SimpleType(name);
-					string[] parts = ns.Split('.');
-					AstType nsType = new SimpleType(parts[0]);
-					for (int i = 1; i < parts.Length; i++) {
-						nsType = new MemberType { Target = nsType, MemberName = parts[i] };
-					}
-					return new MemberType { Target = nsType, MemberName = name }.WithAnnotation(type);
+					
+					// TODO: Until we can simplify type with 'using', use just the name without namesapce
+					return new SimpleType(name).WithAnnotation(type);
+					
+//					if (ns.Length == 0)
+//						return new SimpleType(name).WithAnnotation(type);
+//					string[] parts = ns.Split('.');
+//					AstType nsType = new SimpleType(parts[0]);
+//					for (int i = 1; i < parts.Length; i++) {
+//						nsType = new MemberType { Target = nsType, MemberName = parts[i] };
+//					}
+//					return new MemberType { Target = nsType, MemberName = name }.WithAnnotation(type);
 				}
 			}
 		}
@@ -487,7 +475,7 @@ namespace Decompiler
 			return astField;
 		}
 		
-		IEnumerable<ParameterDeclaration> MakeParameters(IEnumerable<ParameterDefinition> paramCol)
+		public static IEnumerable<ParameterDeclaration> MakeParameters(IEnumerable<ParameterDefinition> paramCol)
 		{
 			foreach(ParameterDefinition paramDef in paramCol) {
 				ParameterDeclaration astParam = new ParameterDeclaration();
@@ -502,4 +490,4 @@ namespace Decompiler
 			}
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/ICSharpCode.Decompiler/Ast/AstMetodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
similarity index 74%
rename from ICSharpCode.Decompiler/Ast/AstMetodBodyBuilder.cs
rename to ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
index 4e266680d..1f131d3b5 100644
--- a/ICSharpCode.Decompiler/Ast/AstMetodBodyBuilder.cs
+++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
@@ -15,8 +15,7 @@ namespace Decompiler
 	public class AstMethodBodyBuilder
 	{
 		MethodDefinition methodDef;
-		static Dictionary<string, Cecil.TypeReference> localVarTypes = new Dictionary<string, Cecil.TypeReference>();
-		static Dictionary<string, bool> localVarDefined = new Dictionary<string, bool>();
+		HashSet<ILVariable> definedLocalVars = new HashSet<ILVariable>();
 		
 		public static BlockStatement CreateMethodBody(MethodDefinition methodDef)
 		{
@@ -47,48 +46,45 @@ namespace Decompiler
 			if (methodDef.Body == null) return null;
 			
 			ILBlock ilMethod = new ILBlock();
-			ilMethod.Body = new ILAstBuilder().Build(methodDef, true);
+			ILAstBuilder astBuilder = new ILAstBuilder();
+			ilMethod.Body = astBuilder.Build(methodDef, true);
 			
 			ILAstOptimizer bodyGraph = new ILAstOptimizer();
 			bodyGraph.Optimize(ilMethod);
 			
 			List<string> intNames = new List<string>(new string[] {"i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t"});
 			Dictionary<string, int> typeNames = new Dictionary<string, int>();
-			foreach(VariableDefinition varDef in methodDef.Body.Variables) {
-				if (string.IsNullOrEmpty(varDef.Name)) {
-					if (varDef.VariableType.FullName == Constants.Int32 && intNames.Count > 0) {
-						varDef.Name = intNames[0];
-						intNames.RemoveAt(0);
-					} else {
-						string name;
-						if (varDef.VariableType.IsArray) {
-							name = "array";
-						} else if (!typeNameToVariableNameDict.TryGetValue(varDef.VariableType.FullName, out name)) {
-							name = varDef.VariableType.Name;
-							// remove the 'I' for interfaces
-							if (name.Length >= 3 && name[0] == 'I' && char.IsUpper(name[1]) && char.IsLower(name[2]))
-								name = name.Substring(1);
-							// remove the backtick (generics)
-							int pos = name.IndexOf('`');
-							if (pos >= 0)
-								name = name.Substring(0, pos);
-							if (name.Length == 0)
-								name = "obj";
-							else
-								name = char.ToLower(name[0]) + name.Substring(1);
-						}
-						if (!typeNames.ContainsKey(name)) {
-							typeNames.Add(name, 0);
-						}
-						int count = typeNames[name];
-						if (count > 0) {
-							name += count.ToString();
-						}
-						varDef.Name = name;
+			foreach(ILVariable varDef in astBuilder.Variables) {
+				if (varDef.Type.FullName == Constants.Int32 && intNames.Count > 0) {
+					varDef.Name = intNames[0];
+					intNames.RemoveAt(0);
+				} else {
+					string name;
+					if (varDef.Type.IsArray) {
+						name = "array";
+					} else if (!typeNameToVariableNameDict.TryGetValue(varDef.Type.FullName, out name)) {
+						name = varDef.Type.Name;
+						// remove the 'I' for interfaces
+						if (name.Length >= 3 && name[0] == 'I' && char.IsUpper(name[1]) && char.IsLower(name[2]))
+							name = name.Substring(1);
+						// remove the backtick (generics)
+						int pos = name.IndexOf('`');
+						if (pos >= 0)
+							name = name.Substring(0, pos);
+						if (name.Length == 0)
+							name = "obj";
+						else
+							name = char.ToLower(name[0]) + name.Substring(1);
 					}
+					if (!typeNames.ContainsKey(name)) {
+						typeNames.Add(name, 0);
+					}
+					int count = ++(typeNames[name]);
+					if (count > 1) {
+						name += count.ToString();
+					}
+					varDef.Name = name;
 				}
-				localVarTypes[varDef.Name] = varDef.VariableType;
-				localVarDefined[varDef.Name] = false;
 				
 //				Ast.VariableDeclaration astVar = new Ast.VariableDeclaration(varDef.Name);
 //				Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(astVar);
@@ -117,8 +113,10 @@ namespace Decompiler
 			if (node is ILLabel) {
 				yield return new Ast.LabelStatement { Label = ((ILLabel)node).Name };
 			} else if (node is ILExpression) {
-				object codeExpr = TransformExpression((ILExpression)node);
+				List<ILRange> ilRanges = ((ILExpression)node).GetILRanges();
+				AstNode codeExpr = TransformExpression((ILExpression)node);
 				if (codeExpr != null) {
+					codeExpr = codeExpr.WithAnnotation(ilRanges);
 					if (codeExpr is Ast.Expression) {
 						yield return new Ast.ExpressionStatement { Expression = (Ast.Expression)codeExpr };
 					} else if (codeExpr is Ast.Statement) {
@@ -151,12 +149,30 @@ namespace Decompiler
 			*/
 			} else if (node is ILCondition) {
 				ILCondition conditionalNode = (ILCondition)node;
-				// Swap bodies
-				yield return new Ast.IfElseStatement {
-					Condition = new UnaryOperatorExpression(UnaryOperatorType.Not, MakeBranchCondition(conditionalNode.Condition)),
-					TrueStatement = TransformBlock(conditionalNode.FalseBlock),
-					FalseStatement = TransformBlock(conditionalNode.TrueBlock)
-				};
+				if (conditionalNode.FalseBlock.Body.Any()) {
+					// Swap bodies
+					yield return new Ast.IfElseStatement {
+						Condition = new UnaryOperatorExpression(UnaryOperatorType.Not, MakeBranchCondition(conditionalNode.Condition)),
+						TrueStatement = TransformBlock(conditionalNode.FalseBlock),
+						FalseStatement = TransformBlock(conditionalNode.TrueBlock)
+					};
+				} else {
+					yield return new Ast.IfElseStatement {
+						Condition = MakeBranchCondition(conditionalNode.Condition),
+						TrueStatement = TransformBlock(conditionalNode.TrueBlock),
+						FalseStatement = TransformBlock(conditionalNode.FalseBlock)
+					};
+				}
+			} else if (node is ILSwitch) {
+				ILSwitch ilSwitch = (ILSwitch)node;
+				SwitchStatement switchStmt = new SwitchStatement() { Expression = (Expression)TransformExpression(ilSwitch.Condition.Arguments[0]) };
+				for (int i = 0; i < ilSwitch.CaseBlocks.Count; i++) {
+					switchStmt.AddChild(new SwitchSection() {
+					    	CaseLabels = new[] { new CaseLabel() { Expression = new PrimitiveExpression(i) } },
+					    	Statements = new[] { TransformBlock(ilSwitch.CaseBlocks[i]) }
+					}, SwitchStatement.SwitchSectionRole);
+				}
+				yield return switchStmt;
 			} else if (node is ILTryCatchBlock) {
 				ILTryCatchBlock tryCatchNode = ((ILTryCatchBlock)node);
 				List<Ast.CatchClause> catchClauses = new List<CatchClause>();
@@ -189,7 +205,7 @@ namespace Decompiler
 			return args;
 		}
 		
-		object TransformExpression(ILExpression expr)
+		AstNode TransformExpression(ILExpression expr)
 		{
 			List<Ast.Expression> args = TransformExpressionArguments(expr);
 			return TransformByteCode(methodDef, expr, args);
@@ -252,7 +268,7 @@ namespace Decompiler
 			*/
 		}
 		
-		static object TransformByteCode(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args)
+		AstNode TransformByteCode(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args)
 		{
 			try {
 				AstNode ret = TransformByteCode_Internal(methodDef, byteCode, args);
@@ -267,7 +283,7 @@ namespace Decompiler
 			}
 		}
 		
-		static string FormatByteCodeOperand(object operand)
+		string FormatByteCodeOperand(object operand)
 		{
 			if (operand == null) {
 				return string.Empty;
@@ -292,7 +308,7 @@ namespace Decompiler
 			}
 		}
 		
-		static AstNode TransformByteCode_Internal(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args)
+		AstNode TransformByteCode_Internal(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args)
 		{
 			// throw new NotImplementedException();
 			
@@ -326,6 +342,7 @@ namespace Decompiler
 					case Code.Sub_Ovf:    return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
 					case Code.Sub_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
 					case Code.And:        return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2);
+					case Code.Or:         return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseOr, arg2);
 					case Code.Xor:        return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2);
 					case Code.Shl:        return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2);
 					case Code.Shr:        return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
@@ -360,7 +377,7 @@ namespace Decompiler
 				case Code.Ldelem_Any:
 					throw new NotImplementedException();
 				case Code.Ldelema:
-					return arg1.Indexer(arg2);
+					return MakeRef(arg1.Indexer(arg2));
 					
 				case Code.Stelem_I:
 				case Code.Stelem_I1:
@@ -459,49 +476,28 @@ namespace Decompiler
 					case Code.Box: throw new NotImplementedException();
 					case Code.Break: throw new NotImplementedException();
 				case Code.Call:
+					return TransformCall(false, operand, methodDef, args);
 				case Code.Callvirt:
-					// TODO: Diferentiate vitual and non-vitual dispach
-					Cecil.MethodReference cecilMethod = ((MethodReference)operand);
-					Ast.Expression target;
-					List<Ast.Expression> methodArgs = new List<Ast.Expression>(args);
-					if (cecilMethod.HasThis) {
-						target = methodArgs[0];
-						methodArgs.RemoveAt(0);
-					} else {
-						target = new TypeReferenceExpression { Type = AstBuilder.ConvertType(cecilMethod.DeclaringType)};
+					return TransformCall(true, operand, methodDef, args);
+				case Code.Ldftn:
+					{
+						Cecil.MethodReference cecilMethod = ((MethodReference)operand);
+						var expr = new Ast.IdentifierExpression(cecilMethod.Name);
+						expr.TypeArguments = ConvertTypeArguments(cecilMethod);
+						expr.AddAnnotation(cecilMethod);
+						return new IdentifierExpression("ldftn").Invoke(expr)
+							.WithAnnotation(new Transforms.DelegateConstruction.Annotation(false, methodDef.DeclaringType));
 					}
-					
-					// TODO: Constructors are ignored
-					if (cecilMethod.Name == ".ctor") {
-						return new CommentStatement("Constructor");
+				case Code.Ldvirtftn:
+					{
+						Cecil.MethodReference cecilMethod = ((MethodReference)operand);
+						var expr = new Ast.IdentifierExpression(cecilMethod.Name);
+						expr.TypeArguments = ConvertTypeArguments(cecilMethod);
+						expr.AddAnnotation(cecilMethod);
+						return new IdentifierExpression("ldvirtftn").Invoke(expr)
+							.WithAnnotation(new Transforms.DelegateConstruction.Annotation(true, methodDef.DeclaringType));
 					}
 					
-					// TODO: Hack, detect properties properly
-					if (cecilMethod.Name.StartsWith("get_")) {
-						return target.Member(cecilMethod.Name.Remove(0, 4)).WithAnnotation(cecilMethod);
-					} else if (cecilMethod.Name.StartsWith("set_")) {
-						return new Ast.AssignmentExpression(
-							target.Member(cecilMethod.Name.Remove(0, 4)).WithAnnotation(cecilMethod),
-							methodArgs[0]
-						);
-					}
-					
-					// Multi-dimensional array acces // TODO: do properly
-					/*
-					if (cecilMethod.Name == "Get") {
-						return new Ast.IndexerExpression(target, methodArgs);
-					} else if (cecilMethod.Name == "Set") {
-						Expression val = methodArgs[methodArgs.Count - 1];
-						methodArgs.RemoveAt(methodArgs.Count - 1);
-						return new Ast.AssignmentExpression(
-							new Ast.IndexerExpression(target, methodArgs),
-							AssignmentOperatorType.Assign,
-							Convert(val, ((Cecil.ArrayType)((target.UserData as Dictionary<string, object>)["Type"])).ElementType)
-						);
-					}*/
-					
-					// Default invocation
-					return target.Invoke(cecilMethod.Name, methodArgs).WithAnnotation(cecilMethod);
 					case Code.Calli: throw new NotImplementedException();
 					case Code.Castclass: return arg1.CastTo(operandAsTypeRef);
 					case Code.Ckfinite: throw new NotImplementedException();
@@ -521,7 +517,12 @@ namespace Decompiler
 					} else {
 						return new Ast.IdentifierExpression(((ParameterDefinition)operand).Name);
 					}
-					case Code.Ldarga: throw new NotImplementedException();
+				case Code.Ldarga:
+					if (methodDef.HasThis && ((ParameterDefinition)operand).Index < 0) {
+						return MakeRef(new Ast.ThisReferenceExpression());
+					} else {
+						return MakeRef(new Ast.IdentifierExpression(((ParameterDefinition)operand).Name));
+					}
 				case Code.Ldc_I4:
 				case Code.Ldc_I8:
 				case Code.Ldc_R4:
@@ -540,16 +541,24 @@ namespace Decompiler
 						.Member(((FieldReference)operand).Name).WithAnnotation(operand),
 						arg1);
 				case Code.Ldflda:
-					case Code.Ldsflda: throw new NotImplementedException();
-					case Code.Ldftn: throw new NotImplementedException();
+					return MakeRef(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand));
+				case Code.Ldsflda:
+					return MakeRef(
+						AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
+						.Member(((FieldReference)operand).Name).WithAnnotation(operand));
 				case Code.Ldloc:
 					if (operand is ILVariable) {
 						return new Ast.IdentifierExpression(((ILVariable)operand).Name);
 					} else {
 						return new Ast.IdentifierExpression(((VariableDefinition)operand).Name);
 					}
-					case Code.Ldloca: throw new NotImplementedException();
-					case Code.Ldnull: return new Ast.PrimitiveExpression(null);
+				case Code.Ldloca:
+					if (operand is ILVariable) {
+						return MakeRef(new Ast.IdentifierExpression(((ILVariable)operand).Name));
+					} else {
+						return MakeRef(new Ast.IdentifierExpression(((VariableDefinition)operand).Name));
+					}
+					case Code.Ldnull: return new Ast.NullReferenceExpression();
 					case Code.Ldobj: throw new NotImplementedException();
 					case Code.Ldstr: return new Ast.PrimitiveExpression(operand);
 				case Code.Ldtoken:
@@ -558,7 +567,6 @@ namespace Decompiler
 					} else {
 						throw new NotImplementedException();
 					}
-					case Code.Ldvirtftn: throw new NotImplementedException();
 					case Code.Leave: return null;
 					case Code.Localloc: throw new NotImplementedException();
 					case Code.Mkrefany: throw new NotImplementedException();
@@ -577,7 +585,6 @@ namespace Decompiler
 					};
 					case Code.No: throw new NotImplementedException();
 					case Code.Nop: return null;
-					case Code.Or: throw new NotImplementedException();
 					case Code.Pop: return arg1;
 					case Code.Readonly: throw new NotImplementedException();
 					case Code.Refanytype: throw new NotImplementedException();
@@ -591,32 +598,18 @@ namespace Decompiler
 						}
 					}
 					case Code.Rethrow: return new Ast.ThrowStatement();
-					case Code.Sizeof: throw new NotImplementedException();
+					case Code.Sizeof: return new Ast.SizeOfExpression { Type = AstBuilder.ConvertType(operand as TypeReference) };
 					case Code.Starg: throw new NotImplementedException();
 					case Code.Stloc: {
-						if (operand is ILVariable) {
-							var astLocalVar = new Ast.VariableDeclarationStatement();
-							astLocalVar.Type = new Ast.PrimitiveType("var");
-							astLocalVar.Variables = new [] {
-								new Ast.VariableInitializer(((ILVariable)operand).Name, arg1)
+						ILVariable locVar = (ILVariable)operand;
+						if (!definedLocalVars.Contains(locVar)) {
+							definedLocalVars.Add(locVar);
+							return new Ast.VariableDeclarationStatement() {
+								Type = locVar.Type != null ? AstBuilder.ConvertType(locVar.Type) : new Ast.PrimitiveType("var"),
+								Variables = new[] { new Ast.VariableInitializer(locVar.Name, arg1) }
 							};
-							return astLocalVar;
-						}
-						VariableDefinition locVar = (VariableDefinition)operand;
-						string name = locVar.Name;
-						arg1 = Convert(arg1, locVar.VariableType);
-						if (localVarDefined.ContainsKey(name)) {
-							if (localVarDefined[name]) {
-								return new Ast.AssignmentExpression(new Ast.IdentifierExpression(name), arg1);
-							} else {
-								var astLocalVar = new Ast.VariableDeclarationStatement();
-								astLocalVar.Type = AstBuilder.ConvertType(localVarTypes[name]);
-								astLocalVar.Variables = new[] { new Ast.VariableInitializer(name, arg1) };
-								localVarDefined[name] = true;
-								return astLocalVar;
-							}
 						} else {
-							return new Ast.AssignmentExpression(new Ast.IdentifierExpression(name), arg1);
+							return new Ast.AssignmentExpression(new Ast.IdentifierExpression(locVar.Name), arg1);
 						}
 					}
 					case Code.Stobj: throw new NotImplementedException();
@@ -631,6 +624,84 @@ namespace Decompiler
 			}
 		}
 		
+		static AstNode TransformCall(bool isVirtual, object operand, MethodDefinition methodDef, List<Ast.Expression> args)
+		{
+			Cecil.MethodReference cecilMethod = ((MethodReference)operand);
+			Ast.Expression target;
+			List<Ast.Expression> methodArgs = new List<Ast.Expression>(args);
+			if (cecilMethod.HasThis) {
+				target = methodArgs[0];
+				methodArgs.RemoveAt(0);
+				
+				// Unpack any DirectionExpression that is used as target for the call
+				// (calling methods on value types implicitly passes the first argument by reference)
+				if (target is DirectionExpression) {
+					target = ((DirectionExpression)target).Expression;
+					target.Remove(); // detach from DirectionExpression
+				}
+			} else {
+				target = new TypeReferenceExpression { Type = AstBuilder.ConvertType(cecilMethod.DeclaringType) };
+			}
+			if (target is ThisReferenceExpression && !isVirtual) {
+				// a non-virtual call on "this" might be a "base"-call.
+				if (cecilMethod.DeclaringType != methodDef.DeclaringType) {
+					// If we're not calling a method in the current class; we must be calling one in the base class.
+					target = new BaseReferenceExpression();
+				}
+			}
+			
+			// Resolve the method to figure out whether it is an accessor:
+			Cecil.MethodDefinition cecilMethodDef = cecilMethod.Resolve();
+			if (cecilMethodDef != null) {
+				if (cecilMethodDef.IsGetter && methodArgs.Count == 0) {
+					foreach (var prop in cecilMethodDef.DeclaringType.Properties) {
+						if (prop.GetMethod == cecilMethodDef)
+							return target.Member(prop.Name).WithAnnotation(prop);
+					}
+				} else if (cecilMethodDef.IsSetter && methodArgs.Count == 1) {
+					foreach (var prop in cecilMethodDef.DeclaringType.Properties) {
+						if (prop.SetMethod == cecilMethodDef)
+							return new Ast.AssignmentExpression(target.Member(prop.Name).WithAnnotation(prop), methodArgs[0]);
+					}
+				} else if (cecilMethodDef.IsAddOn && methodArgs.Count == 1) {
+					foreach (var ev in cecilMethodDef.DeclaringType.Events) {
+						if (ev.AddMethod == cecilMethodDef) {
+							return new Ast.AssignmentExpression {
+								Left = target.Member(ev.Name).WithAnnotation(ev),
+								Operator = AssignmentOperatorType.Add,
+								Right = methodArgs[0]
+							};
+						}
+					}
+				} else if (cecilMethodDef.IsRemoveOn && methodArgs.Count == 1) {
+					foreach (var ev in cecilMethodDef.DeclaringType.Events) {
+						if (ev.RemoveMethod == cecilMethodDef) {
+							return new Ast.AssignmentExpression {
+								Left = target.Member(ev.Name).WithAnnotation(ev),
+								Operator = AssignmentOperatorType.Subtract,
+								Right = methodArgs[0]
+							};
+						}
+					}
+				}
+			}
+			// Default invocation
+			return target.Invoke(cecilMethod.Name, ConvertTypeArguments(cecilMethod), methodArgs).WithAnnotation(cecilMethod);
+		}
+		
+		static IEnumerable<AstType> ConvertTypeArguments(MethodReference cecilMethod)
+		{
+			GenericInstanceMethod g = cecilMethod as GenericInstanceMethod;
+			if (g == null)
+				return null;
+			return g.GenericArguments.Select(t => AstBuilder.ConvertType(t));
+		}
+		
+		static Ast.DirectionExpression MakeRef(Ast.Expression expr)
+		{
+			return new DirectionExpression { Expression = expr, FieldDirection = FieldDirection.Ref };
+		}
+		
 		static Ast.Expression Convert(Ast.Expression expr, Cecil.TypeReference reqType)
 		{
 			if (reqType == null) {
diff --git a/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs b/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs
index 729caba28..f7fe21949 100644
--- a/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs
+++ b/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs
@@ -10,7 +10,8 @@ namespace Decompiler
 	{
 		public static T WithAnnotation<T>(this T node, object annotation) where T : AstNode
 		{
-			node.AddAnnotation(annotation);
+			if (annotation != null)
+				node.AddAnnotation(annotation);
 			return node;
 		}
 	}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs b/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs
new file mode 100644
index 000000000..36f6d4eb5
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs
@@ -0,0 +1,42 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
+
+using System;
+using System.Linq;
+using ICSharpCode.NRefactory.CSharp;
+using Mono.Cecil;
+
+namespace Decompiler.Transforms
+{
+	public class ConvertConstructorCallIntoInitializer : DepthFirstAstVisitor<object, object>
+	{
+		public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
+		{
+			ExpressionStatement stmt = constructorDeclaration.Body.Statements.FirstOrDefault() as ExpressionStatement;
+			if (stmt == null)
+				return null;
+			InvocationExpression invocation = stmt.Expression as InvocationExpression;
+			if (invocation == null)
+				return null;
+			MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;
+			if (mre != null && mre.MemberName == ".ctor") {
+				ConstructorInitializer ci = new ConstructorInitializer();
+				if (mre.Target is ThisReferenceExpression)
+					ci.ConstructorInitializerType = ConstructorInitializerType.This;
+				else if (mre.Target is BaseReferenceExpression)
+					ci.ConstructorInitializerType = ConstructorInitializerType.Base;
+				else
+					return null;
+				// Move arguments from invocation to initializer:
+				var arguments = invocation.Arguments.ToArray();
+				invocation.Arguments = null;
+				ci.Arguments = arguments;
+				// Add the initializer:
+				constructorDeclaration.Initializer = ci.WithAnnotation(invocation.Annotation<MethodReference>());
+				// Remove the statement:
+				stmt.Remove();
+			}
+			return null;
+		}
+	}
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
new file mode 100644
index 000000000..4f3786120
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
@@ -0,0 +1,130 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
+
+using System;
+using System.Linq;
+using ICSharpCode.Decompiler;
+using ICSharpCode.NRefactory.CSharp;
+using Mono.Cecil;
+
+namespace Decompiler.Transforms
+{
+	/// <summary>
+	/// Converts "new Action(obj, ldftn(func))" into "new Action(obj.func)".
+	/// For anonymous methods, creates an AnonymousMethodExpression.
+	/// </summary>
+	public class DelegateConstruction : DepthFirstAstVisitor<object, object>
+	{
+		internal sealed class Annotation
+		{
+			/// <summary>
+			/// ldftn or ldvirtftn?
+			/// </summary>
+			public readonly bool IsVirtual;
+			
+			/// <summary>
+			/// The method being decompiled.
+			/// </summary>
+			public readonly TypeDefinition ContainingType;
+			
+			public Annotation(bool isVirtual, TypeDefinition containingType)
+			{
+				this.IsVirtual = isVirtual;
+				this.ContainingType = containingType;
+			}
+		}
+		
+		public override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data)
+		{
+			if (objectCreateExpression.Arguments.Count() == 2) {
+				Expression obj = objectCreateExpression.Arguments.First();
+				Expression func = objectCreateExpression.Arguments.Last();
+				Annotation annotation = func.Annotation<Annotation>();
+				if (annotation != null) {
+					IdentifierExpression methodIdent = (IdentifierExpression)((InvocationExpression)func).Arguments.Single();
+					MethodReference method = methodIdent.Annotation<MethodReference>();
+					if (method != null) {
+						if (HandleAnonymousMethod(objectCreateExpression, obj, method, annotation.ContainingType))
+							return null;
+						// Perform the transformation to "new Action(obj.func)".
+						obj.Remove();
+						methodIdent.Remove();
+						if (!annotation.IsVirtual && obj is ThisReferenceExpression) {
+							// maybe it's getting the pointer of a base method?
+							if (method.DeclaringType != annotation.ContainingType) {
+								obj = new BaseReferenceExpression();
+							}
+						}
+						if (!annotation.IsVirtual && obj is NullReferenceExpression && !method.HasThis) {
+							// We're loading a static method.
+							// However it is possible to load extension methods with an instance, so we compare the number of arguments:
+							bool isExtensionMethod = false;
+							TypeReference delegateType = objectCreateExpression.Type.Annotation<TypeReference>();
+							if (delegateType != null) {
+								TypeDefinition delegateTypeDef = delegateType.Resolve();
+								if (delegateTypeDef != null) {
+									MethodDefinition invokeMethod = delegateTypeDef.Methods.FirstOrDefault(m => m.Name == "Invoke");
+									if (invokeMethod != null) {
+										isExtensionMethod = (invokeMethod.Parameters.Count + 1 == method.Parameters.Count);
+									}
+								}
+							}
+							if (!isExtensionMethod) {
+								obj = new TypeReferenceExpression { Type = AstBuilder.ConvertType(method.DeclaringType) };
+							}
+						}
+						// now transform the identifier into a member reference
+						MemberReferenceExpression mre = new MemberReferenceExpression {
+							Target = obj,
+							MemberName = methodIdent.Identifier,
+							TypeArguments = methodIdent.TypeArguments
+						};
+						mre.AddAnnotation(method);
+						objectCreateExpression.Arguments = new [] { mre };
+						return null;
+					}
+				}
+			}
+			return base.VisitObjectCreateExpression(objectCreateExpression, data);
+		}
+		
+		bool HandleAnonymousMethod(ObjectCreateExpression objectCreateExpression, Expression target, MethodReference methodRef, TypeDefinition containingType)
+		{
+			// Anonymous methods are defined in the same assembly, so there's no need to Resolve().
+			MethodDefinition method = methodRef as MethodDefinition;
+			if (method == null || !method.Name.StartsWith("<", StringComparison.Ordinal))
+				return false;
+			if (!(method.IsCompilerGenerated() || method.DeclaringType.IsCompilerGenerated()))
+				return false;
+			TypeDefinition methodContainingType = method.DeclaringType;
+			// check that methodContainingType is within containingType
+			while (methodContainingType != containingType) {
+				methodContainingType = methodContainingType.DeclaringType;
+				if (methodContainingType == null)
+					return false;
+			}
+			
+			// Decompile the anonymous method:
+			BlockStatement body = AstMethodBodyBuilder.CreateMethodBody(method);
+			TransformationPipeline.RunTransformationsUntil(body, v => v is DelegateConstruction);
+			body.AcceptVisitor(this, null);
+			
+			AnonymousMethodExpression ame = new AnonymousMethodExpression();
+			if (method.Parameters.All(p => string.IsNullOrEmpty(p.Name))) {
+				ame.HasParameterList = false;
+			} else {
+				ame.HasParameterList = true;
+				ame.Parameters = AstBuilder.MakeParameters(method.Parameters);
+			}
+			ame.Body = body;
+			// Replace all occurrences of 'this' in the method body with the delegate's target:
+			foreach (AstNode node in body.Descendants) {
+				if (node is ThisReferenceExpression)
+					node.ReplaceWith(target.Clone());
+				
+			}
+			objectCreateExpression.ReplaceWith(ame);
+			return true;
+		}
+	}
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/RemoveDeadLabels.cs b/ICSharpCode.Decompiler/Ast/Transforms/RemoveDeadLabels.cs
new file mode 100644
index 000000000..b8f65771a
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/RemoveDeadLabels.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using ICSharpCode.NRefactory.CSharp;
+
+namespace Decompiler.Transforms.Ast
+{
+	public class RemoveDeadLabels : DepthFirstAstVisitor<object, object>
+	{
+		List<string> usedLabels = new List<string>();
+		bool collectingUsedLabels;
+		
+		public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
+		{
+			collectingUsedLabels = true;
+			base.VisitConstructorDeclaration(constructorDeclaration, data);
+			collectingUsedLabels = false;
+			base.VisitConstructorDeclaration(constructorDeclaration, data);
+			return null;
+		}
+		
+		public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
+		{
+			collectingUsedLabels = true;
+			base.VisitMethodDeclaration(methodDeclaration, data);
+			collectingUsedLabels = false;
+			base.VisitMethodDeclaration(methodDeclaration, data);
+			return null;
+		}
+		
+		public override object VisitAccessor(Accessor accessor, object data)
+		{
+			collectingUsedLabels = true;
+			base.VisitAccessor(accessor, data);
+			collectingUsedLabels = false;
+			return base.VisitAccessor(accessor, data);
+		}
+		
+		public override object VisitGotoStatement(GotoStatement gotoStatement, object data)
+		{
+			if (collectingUsedLabels) {
+				usedLabels.Add(gotoStatement.Label);
+			}
+			return null;
+		}
+		
+		public override object VisitLabelStatement(LabelStatement labelStatement, object data)
+		{
+			if (!collectingUsedLabels) {
+				if (!usedLabels.Contains(labelStatement.Label)) {
+					labelStatement.Remove();
+				}
+			}
+			return null;
+		}
+	}
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs b/ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs
index 0719e8f65..d45f5d121 100644
--- a/ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs
+++ b/ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs
@@ -1,17 +1,15 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-
 using ICSharpCode.NRefactory.CSharp;
 
 namespace Decompiler.Transforms.Ast
 {
-	/*
 	public class RemoveGotos: DepthFirstAstVisitor<object, object>
 	{
-		Stack<Statement> enteredLoops = new Stack<Statement>();
+		Stack<ForStatement> enteredLoops = new Stack<ForStatement>();
 		
-		Statement CurrentLoop {
+		ForStatement CurrentLoop {
 			get {
 				if (enteredLoops.Count > 0) {
 					return enteredLoops.Peek();
@@ -29,32 +27,25 @@ namespace Decompiler.Transforms.Ast
 			return null;
 		}
 		
-		public override object VisitWhileStatement(WhileStatement whileStatement, object data)
-		{
-			enteredLoops.Push(whileStatement);
-			base.VisitWhileStatement(whileStatement, data);
-			enteredLoops.Pop();
-			return null;
-		}
+//		public override object VisitWhileStatement(WhileStatement whileStatement, object data)
+//		{
+//			enteredLoops.Push(whileStatement);
+//			base.VisitWhileStatement(whileStatement, data);
+//			enteredLoops.Pop();
+//			return null;
+//		}
 		
 		public override object VisitBlockStatement(BlockStatement blockStatement, object data)
 		{
 			base.VisitBlockStatement(blockStatement, data);
 			
 			// Remove redundant jump at the end of block
-			INode lastStmt = blockStatement.Children.Last();
-			// End of while loop
-			if (lastStmt is ContinueStatement && 
-			    blockStatement.Parent is DoLoopStatement)
-			{
-				blockStatement.Children.Remove(lastStmt);
-				return null;
-			}
+			AstNode lastStmt = blockStatement.Children.LastOrDefault();
 			// End of for loop
 			if (lastStmt is ContinueStatement && 
 			    blockStatement.Parent is ForStatement)
 			{
-				blockStatement.Children.Remove(lastStmt);
+				lastStmt.Remove();
 				return null;
 			}
 			// End of method
@@ -62,7 +53,7 @@ namespace Decompiler.Transforms.Ast
 			    (blockStatement.Parent is MethodDeclaration || blockStatement.Parent is ConstructorDeclaration) &&
 			    ((ReturnStatement)lastStmt).Expression.IsNull)
 			{
-				blockStatement.Children.Remove(lastStmt);
+				lastStmt.Remove();
 				return null;
 			}
 			
@@ -75,7 +66,7 @@ namespace Decompiler.Transforms.Ast
 		{
 			if (statement == null) throw new ArgumentNullException();
 			
-			Statement next = (Statement)statement.Next();
+			Statement next = (Statement)statement.NextSibling;
 			
 			if (next != null) {
 				return EnterBlockStatement(next);
@@ -105,12 +96,12 @@ namespace Decompiler.Transforms.Ast
 			// Iterator; Condition; Body
 			if (statement is ForStatement) {
 				ForStatement forLoop = statement as ForStatement;
-				if (forLoop.Iterator.Count > 0) {
-					return forLoop.Iterator[0];
+				if (forLoop.Iterators.Any()) {
+					return forLoop.Iterators.First();
 				} else if (!forLoop.Condition.IsNull) {
 					return forLoop.Condition;
 				} else {
-					return EnterBlockStatement((Statement)forLoop.EmbeddedStatement.Children.First());
+					return EnterBlockStatement((Statement)forLoop.EmbeddedStatement.FirstChild);
 				}
 			}
 			
@@ -125,14 +116,12 @@ namespace Decompiler.Transforms.Ast
 			// For loop starts as follows: Initializers; Condition; Body
 			if (statement is ForStatement) {
 				ForStatement forLoop = statement as ForStatement;
-				if (forLoop.Initializers.Count > 0) {
-					return forLoop.Initializers[0];
+				if (forLoop.Initializers.Any()) {
+				    	return forLoop.Initializers.First();
 				} else if (!forLoop.Condition.IsNull) {
 					return forLoop.Condition;
-				} else if (forLoop.EmbeddedStatement is BlockStatement &&
-					       forLoop.EmbeddedStatement.Children.Count > 0) {
-					statement = (Statement)forLoop.EmbeddedStatement.Children.First();
-					return EnterBlockStatement(statement);  // Simplify again
+				} else if (forLoop.EmbeddedStatement.Children.FirstOrDefault() is Statement) {
+					return EnterBlockStatement((Statement)forLoop.EmbeddedStatement.FirstChild);  // Simplify again
 				}
 			}
 			
@@ -142,11 +131,11 @@ namespace Decompiler.Transforms.Ast
 		public override object VisitGotoStatement(GotoStatement gotoStatement, object data)
 		{
 			// Remove redundant goto which goes to a label that imideately follows
-			INode fallthoughTarget = GetNextStatement(gotoStatement);
+			AstNode fallthoughTarget = GetNextStatement(gotoStatement);
 			while(true) {
 				if (fallthoughTarget is LabelStatement) {
 				    if ((fallthoughTarget as LabelStatement).Label == gotoStatement.Label) {
-						RemoveCurrentNode();
+						gotoStatement.Remove();
 						return null;
 					} else {
 						fallthoughTarget = GetNextStatement((LabelStatement)fallthoughTarget);
@@ -159,10 +148,10 @@ namespace Decompiler.Transforms.Ast
 			// Replace goto with 'break'
 			// Break statement moves right outside the looop
 			if (CurrentLoop != null) {
-				INode breakTarget = GetNextStatement(CurrentLoop);
+				AstNode breakTarget = GetNextStatement(CurrentLoop);
 				if ((breakTarget is LabelStatement) &&
 				    (breakTarget as LabelStatement).Label == gotoStatement.Label) {
-					ReplaceCurrentNode(new BreakStatement());
+					gotoStatement.ReplaceWith(new BreakStatement());
 					return null;
 				}
 			}
@@ -171,24 +160,24 @@ namespace Decompiler.Transforms.Ast
 			// Continue statement which moves at the very end of loop
 			if (CurrentLoop != null &&
 			    (CurrentLoop.EmbeddedStatement is BlockStatement) &&
-			    ((CurrentLoop.EmbeddedStatement as BlockStatement).Children.Last() as LabelStatement) != null &&
-			    ((CurrentLoop.EmbeddedStatement as BlockStatement).Children.Last() as LabelStatement).Label == gotoStatement.Label) {
-				ReplaceCurrentNode(new ContinueStatement());
+			    ((CurrentLoop.EmbeddedStatement as BlockStatement).LastChild as LabelStatement) != null &&
+			    ((CurrentLoop.EmbeddedStatement as BlockStatement).LastChild as LabelStatement).Label == gotoStatement.Label) {
+				gotoStatement.ReplaceWith(new ContinueStatement());
 				return null;
 			}
 			
 			// Replace goto with 'continue'
 			// Continue statement which moves at the very start of for loop
 			if (CurrentLoop != null) {
-				INode continueTarget = ExitBlockStatement(CurrentLoop); // The start of the loop
+				AstNode continueTarget = ExitBlockStatement(CurrentLoop); // The start of the loop
 				if ((continueTarget is LabelStatement) &&
 				    (continueTarget as LabelStatement).Label == gotoStatement.Label) {
-					ReplaceCurrentNode(new ContinueStatement());
+					gotoStatement.ReplaceWith(new ContinueStatement());
 					return null;
 				}
 			}
 			
 			return null;
 		}
-	}*/
+	}
 }
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/Idioms.cs b/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs
similarity index 87%
rename from ICSharpCode.Decompiler/Ast/Transforms/Idioms.cs
rename to ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs
index 32670ad8e..25215179f 100644
--- a/ICSharpCode.Decompiler/Ast/Transforms/Idioms.cs
+++ b/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs
@@ -5,9 +5,13 @@ using Mono.Cecil;
 using Ast = ICSharpCode.NRefactory.CSharp;
 using ICSharpCode.NRefactory.CSharp;
 
-namespace Decompiler.Transforms.Ast
+namespace Decompiler.Transforms
 {
-	public class Idioms: DepthFirstAstVisitor<object, object>
+	/// <summary>
+	/// Replaces method calls with the appropriate operator expressions.
+	/// Also simplifies "x = x op y" into "x op= y" where possible.
+	/// </summary>
+	public class ReplaceMethodCallsWithOperators : DepthFirstAstVisitor<object, object>
 	{
 		public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
 		{
@@ -58,6 +62,19 @@ namespace Decompiler.Transforms.Ast
 				);
 				return null;
 			}
+			if (methodRef.Name == "op_Explicit" && arguments.Length == 1) {
+				arguments[0].Remove(); // detach argument
+				invocationExpression.ReplaceWith(
+					arguments[0].CastTo(AstBuilder.ConvertType(methodRef.ReturnType, methodRef.MethodReturnType))
+					.WithAnnotation(methodRef)
+				);
+				return null;
+			}
+			if (methodRef.Name == "op_Implicit" && arguments.Length == 1) {
+				arguments[0].Remove(); // detach argument
+				invocationExpression.ReplaceWith(arguments[0]);
+				return null;
+			}
 			
 			return null;
 		}
@@ -162,7 +179,7 @@ namespace Decompiler.Transforms.Ast
 							break;
 					}
 					if (assignment.Operator != AssignmentOperatorType.Assign) {
-						// If we found a shorter operators, get rid of the BinaryOperatorExpression:
+						// If we found a shorter operator, get rid of the BinaryOperatorExpression:
 						assignment.Right = binary.Right;
 					}
 				}
@@ -174,18 +191,5 @@ namespace Decompiler.Transforms.Ast
 		{
 			return left is IdentifierExpression; // TODO
 		}
-		
-		/*
-		public override object VisitCastExpression(CastExpression castExpression, object data)
-		{
-			MethodReference typeRef = invocationExpression.Annotation<TypeReference>();
-			if (typeRef.FullName == Constants.Int32 &&
-			    castExpression.Expression is MemberReferenceExpression &&
-			    (castExpression.Expression as MemberReferenceExpression).MemberName == "Length") {
-				ReplaceCurrentNode(castExpression.Expression);
-				return null;
-			}
-			return base.VisitCastExpression(castExpression, data);
-		}*/
 	}
 }
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/RestoreLoop.cs b/ICSharpCode.Decompiler/Ast/Transforms/RestoreLoop.cs
index ed3d91015..09f07d78e 100644
--- a/ICSharpCode.Decompiler/Ast/Transforms/RestoreLoop.cs
+++ b/ICSharpCode.Decompiler/Ast/Transforms/RestoreLoop.cs
@@ -1,10 +1,9 @@
 using System;
-
+using System.Linq;
 using ICSharpCode.NRefactory.CSharp;
 
 namespace Decompiler.Transforms.Ast
 {
-	/*
 	public class RestoreLoop: DepthFirstAstVisitor<object, object>
 	{
 		public override object VisitForStatement(ForStatement forStatement, object data)
@@ -12,25 +11,25 @@ namespace Decompiler.Transforms.Ast
 			base.VisitForStatement(forStatement, data);
 			
 			// Restore loop initializer
-			if (forStatement.Initializers.Count == 0) {
-				LocalVariableDeclaration varDeclr = forStatement.Previous() as LocalVariableDeclaration;
+			if (!forStatement.Initializers.Any()) {
+				VariableDeclarationStatement varDeclr = forStatement.PrevSibling as VariableDeclarationStatement;
 				if (varDeclr != null) {
 					varDeclr.ReplaceWith(Statement.Null);
-					forStatement.Initializers.Add(varDeclr);
+					forStatement.Initializers = new Statement[] { varDeclr };
 				}
 			}
 			
 			// Restore loop condition
 			if (forStatement.Condition.IsNull &&
-				forStatement.EmbeddedStatement.Children.Count >= 3)
+			    forStatement.EmbeddedStatement.Children.Count() >= 3)
 			{
-				IfElseStatement  condition = forStatement.EmbeddedStatement.Children[0] as IfElseStatement;
-				BreakStatement   breakStmt = forStatement.EmbeddedStatement.Children[1] as BreakStatement;
-				LabelStatement   label     = forStatement.EmbeddedStatement.Children[2] as LabelStatement;
+				IfElseStatement  condition = forStatement.EmbeddedStatement.Children.First() as IfElseStatement;
+				BreakStatement   breakStmt = forStatement.EmbeddedStatement.Children.Skip(1).First() as BreakStatement;
+				LabelStatement   label     = forStatement.EmbeddedStatement.Children.Skip(2).First() as LabelStatement;
 				if (condition != null && breakStmt != null && label != null &&
-				    condition.TrueStatement.Count == 1)
+				    condition.TrueStatement.Children.Count() == 1)
 				{
-					GotoStatement gotoStmt = condition.TrueStatement[0] as GotoStatement;
+					GotoStatement gotoStmt = condition.TrueStatement.FirstChild as GotoStatement;
 					if (gotoStmt != null && gotoStmt.Label == label.Label) {
 						condition.Remove();
 						breakStmt.Remove();
@@ -41,34 +40,34 @@ namespace Decompiler.Transforms.Ast
 			
 			// Restore loop condition (version 2)
 			if (forStatement.Condition.IsNull) {
-				IfElseStatement condition = forStatement.EmbeddedStatement.Children.First() as IfElseStatement;
+				IfElseStatement condition = forStatement.EmbeddedStatement.FirstChild as IfElseStatement;
 				if (condition != null &&
-				    condition.TrueStatement.Count == 1 &&
-				    condition.TrueStatement[0] is BlockStatement &&
-				    condition.TrueStatement[0].Children.Count == 1 &&
-				    condition.TrueStatement[0].Children.First() is BreakStatement &&
-				    condition.FalseStatement.Count == 1 &&
-				    condition.FalseStatement[0] is BlockStatement &&
-				    condition.FalseStatement[0].Children.Count == 0)
+				    condition.TrueStatement.Children.Any() &&
+				    condition.TrueStatement.FirstChild is BlockStatement &&
+				    condition.TrueStatement.Children.Count() == 1 &&
+				    condition.TrueStatement.FirstChild.FirstChild is BreakStatement &&
+				    condition.FalseStatement.Children.Any() &&
+				    condition.FalseStatement.FirstChild is BlockStatement &&
+				    condition.FalseStatement.Children.Count() == 0)
 				{
 					condition.Remove();
-					forStatement.Condition = new UnaryOperatorExpression(condition.Condition, UnaryOperatorType.Not);
+					forStatement.Condition = new UnaryOperatorExpression() { Expression = condition.Condition, Operator = UnaryOperatorType.Not };
 				}
 			}
 			
 			// Restore loop iterator
-			if (forStatement.EmbeddedStatement.Children.Count > 0 &&
-			    forStatement.Iterator.Count == 0)
+			if (forStatement.EmbeddedStatement.Children.Any() &&
+			    !forStatement.Iterators.Any())
 			{
-				ExpressionStatement lastStmt = forStatement.EmbeddedStatement.Children.Last() as ExpressionStatement;
+				ExpressionStatement lastStmt = forStatement.EmbeddedStatement.LastChild as ExpressionStatement;
 				if (lastStmt != null &&
 				    (lastStmt.Expression is AssignmentExpression || lastStmt.Expression is UnaryOperatorExpression)) {
 					lastStmt.Remove();
-					forStatement.Iterator.Add(lastStmt);
+					forStatement.Iterators = new Statement[] { lastStmt };
 				}
 			}
 			
 			return null;
 		}
-	}*/
+	}
 }
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/SimplifyTypeReferences.cs b/ICSharpCode.Decompiler/Ast/Transforms/SimplifyTypeReferences.cs
deleted file mode 100644
index c179ffdac..000000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/SimplifyTypeReferences.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-
-using ICSharpCode.NRefactory.CSharp;
-
-namespace Decompiler.Transforms.Ast
-{
-	public class SimplifyTypeReferences: DepthFirstAstVisitor<object, object>
-	{
-		string currentNamepace = string.Empty;
-		string currentClass = null;
-		
-		public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data)
-		{
-			currentNamepace = namespaceDeclaration.Name;
-			base.VisitNamespaceDeclaration(namespaceDeclaration, data);
-			currentNamepace = string.Empty;
-			return null;
-		}
-		
-		public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
-		{
-			currentClass = currentNamepace + "." + typeDeclaration.Name;
-			base.VisitTypeDeclaration(typeDeclaration, data);
-			currentClass = null;
-			return null;
-		}
-	}
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs
new file mode 100644
index 000000000..8c2d5b235
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs
@@ -0,0 +1,50 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
+
+using System;
+using ICSharpCode.NRefactory.CSharp;
+
+namespace Decompiler.Transforms
+{
+	public static class TransformationPipeline
+	{
+		public static IAstVisitor<object, object>[] CreatePipeline()
+		{
+			return new IAstVisitor<object, object>[] {
+				new DelegateConstruction(),
+				new ConvertConstructorCallIntoInitializer(),
+				new ReplaceMethodCallsWithOperators()
+			};
+		}
+		
+		public static void RunTransformations(AstNode node)
+		{
+			RunTransformationsUntil(node, null);
+		}
+		
+		public static void RunTransformationsUntil(AstNode node, Predicate<IAstVisitor<object, object>> abortCondition)
+		{
+			if (node == null)
+				return;
+			for (int i = 0; i < 4; i++) {
+				if (Options.ReduceAstJumps) {
+					node.AcceptVisitor(new Transforms.Ast.RemoveGotos(), null);
+					node.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null);
+				}
+				if (Options.ReduceAstLoops) {
+					node.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null);
+				}
+				if (Options.ReduceAstOther) {
+					node.AcceptVisitor(new Transforms.Ast.RemoveEmptyElseBody(), null);
+					node.AcceptVisitor(new Transforms.Ast.PushNegation(), null);
+				}
+			}
+			
+			foreach (var visitor in CreatePipeline()) {
+				if (abortCondition != null && abortCondition(visitor))
+					return;
+				node.AcceptVisitor(visitor, null);
+			}
+		}
+	}
+}
diff --git a/ICSharpCode.Decompiler/CecilExtensions.cs b/ICSharpCode.Decompiler/CecilExtensions.cs
index 4c17373ec..a97ed2427 100644
--- a/ICSharpCode.Decompiler/CecilExtensions.cs
+++ b/ICSharpCode.Decompiler/CecilExtensions.cs
@@ -158,5 +158,16 @@ namespace ICSharpCode.Decompiler
 			}
 			return accessorMethods;
 		}
+		
+		public static bool IsCompilerGenerated(this ICustomAttributeProvider provider)
+		{
+			if (provider.HasCustomAttributes) {
+				foreach (CustomAttribute a in provider.CustomAttributes) {
+					if (a.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute")
+						return true;
+				}
+			}
+			return false;
+		}
 	}
 }
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index a45af9653..77a18ab6b 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -50,16 +50,19 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Ast\AstBuilder.cs" />
-    <Compile Include="Ast\AstMetodBodyBuilder.cs" />
+    <Compile Include="Ast\AstMethodBodyBuilder.cs" />
     <Compile Include="Ast\CommentStatement.cs" />
     <Compile Include="Ast\NRefactoryExtensions.cs" />
     <Compile Include="Ast\TextOutputFormatter.cs" />
-    <Compile Include="Ast\Transforms\Idioms.cs" />
+    <Compile Include="Ast\Transforms\ConvertConstructorCallIntoInitializer.cs" />
+    <Compile Include="Ast\Transforms\DelegateConstruction.cs" />
+    <Compile Include="Ast\Transforms\ReplaceMethodCallsWithOperators.cs" />
     <Compile Include="Ast\Transforms\PushNegation.cs" />
+    <Compile Include="Ast\Transforms\RemoveDeadLabels.cs" />
     <Compile Include="Ast\Transforms\RemoveEmptyElseBody.cs" />
     <Compile Include="Ast\Transforms\RemoveGotos.cs" />
     <Compile Include="Ast\Transforms\RestoreLoop.cs" />
-    <Compile Include="Ast\Transforms\SimplifyTypeReferences.cs" />
+    <Compile Include="Ast\Transforms\TransformationPipeline.cs" />
     <Compile Include="CecilExtensions.cs" />
     <Compile Include="Disassembler\CodeMappings.cs" />
     <Compile Include="Disassembler\DisassemblerHelpers.cs" />
diff --git a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
index 9c9b768f8..e520437f0 100644
--- a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
+++ b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
@@ -32,6 +32,7 @@ namespace Decompiler
 		{
 			public ILLabel  Label;    // Non-null only if needed
 			public int      Offset;
+			public int      EndOffset;
 			public OpCode   OpCode;
 			public object   Operand;
 			public int?     PopCount; // Null means pop all
@@ -94,6 +95,8 @@ namespace Decompiler
 		Dictionary<Instruction, ByteCode> instrToByteCode = new Dictionary<Instruction, ByteCode>();
 		Dictionary<ILVariable, bool> allowInline = new Dictionary<ILVariable, bool>();
 		
+		public List<ILVariable> Variables;
+		
 		public List<ILNode> Build(MethodDefinition methodDef, bool optimize)
 		{
 			this.methodDef = methodDef;
@@ -118,6 +121,7 @@ namespace Decompiler
 				MethodBodyRocks.ExpandMacro(ref opCode, ref operand, methodDef.Body);
 				ByteCode byteCode = new ByteCode() {
 					Offset      = inst.Offset,
+					EndOffset   = inst.Next != null ? inst.Next.Offset : methodDef.Body.CodeSize,
 					OpCode      = opCode,
 					Operand     = operand,
 					PopCount    = inst.GetPopCount(),
@@ -247,27 +251,27 @@ namespace Decompiler
 			}
 			
 			// Convert local varibles
-			List<ILVariable> vars = methodDef.Body.Variables.Select(v => new ILVariable() { Name = string.IsNullOrEmpty(v.Name) ?  "var_" + v.Index : v.Name }).ToList();
-			int[] numReads  = new int[vars.Count];
-			int[] numWrites = new int[vars.Count];
+			Variables = methodDef.Body.Variables.Select(v => new ILVariable() { Name = string.IsNullOrEmpty(v.Name) ?  "var_" + v.Index : v.Name, Type = v.VariableType }).ToList();
+			int[] numReads  = new int[Variables.Count];
+			int[] numWrites = new int[Variables.Count];
 			foreach(ByteCode byteCode in body) {
 				if (byteCode.OpCode == OpCodes.Ldloc) {
 					int index = ((VariableDefinition)byteCode.Operand).Index;
-					byteCode.Operand = vars[index];
+					byteCode.Operand = Variables[index];
 					numReads[index]++;
 				}
 				if (byteCode.OpCode == OpCodes.Stloc) {
 					int index = ((VariableDefinition)byteCode.Operand).Index;
-					byteCode.Operand = vars[index];
+					byteCode.Operand = Variables[index];
 					numWrites[index]++;
 				}
 			}
 			
 			// Find which variables we can inline
 			if (this.optimize) {
-				for (int i = 0; i < vars.Count; i++) {
+				for (int i = 0; i < Variables.Count; i++) {
 					if (numReads[i] == 1 && numWrites[i] == 1) {
-						allowInline[vars[i]] = true;
+						allowInline[Variables[i]] = true;
 					}
 				}
 			}
@@ -360,6 +364,7 @@ namespace Decompiler
 				MethodBodyRocks.ExpandMacro(ref opCode, ref operand, methodDef.Body);
 				
 				ILExpression expr = new ILExpression(opCode, operand);
+				expr.ILRanges.Add(new ILRange() { From = byteCode.Offset, To = byteCode.EndOffset });
 				
 				// Label for this instruction
 				if (byteCode.Label != null) {
@@ -417,6 +422,9 @@ namespace Decompiler
 							bool canInline;
 							allowInline.TryGetValue((ILVariable)arg.Operand, out canInline);
 							if (arg.Operand == currExpr.Operand && canInline) {
+								// Assigne the ranges for optimized away instrustions somewhere
+								currExpr.Arguments[0].ILRanges.AddRange(currExpr.ILRanges);
+								currExpr.Arguments[0].ILRanges.AddRange(nextExpr.Arguments[j].ILRanges);
 								ast.RemoveAt(i);
 								nextExpr.Arguments[j] = currExpr.Arguments[0]; // Inline the stloc body
 								i -= 2; // Try the same index again
diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
index c3e3e7e1b..18cc956a0 100644
--- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
+++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
@@ -14,25 +14,27 @@ namespace Decompiler.ControlFlow
 		
 		public void Optimize(ILBlock method)
 		{
-			var blocks = method.GetSelfAndChildrenRecursive<ILBlock>().ToList();
+			foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>().ToList()) {
+				SplitToMovableBlocks(block);
+			}
 			
-			foreach(ILBlock block in blocks) {
+			foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>().Where(b => !(b is ILMoveableBlock)).ToList()) {
 				ControlFlowGraph graph;
-				
-				SplitToMovableBlocks(block);
-				
 				graph = BuildGraph(block.Body, block.EntryPoint);
 				graph.ComputeDominance();
 				graph.ComputeDominanceFrontier();
-				block.Body = FindLoops(new HashSet<ControlFlowNode>(graph.Nodes.Skip(3)), graph.EntryPoint);
-	
+				block.Body = FindLoops(new HashSet<ControlFlowNode>(graph.Nodes.Skip(3)), graph.EntryPoint, true);
+			}
+			
+			foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>().Where(b => !(b is ILMoveableBlock)).ToList()) {
+				ControlFlowGraph graph;
 				graph = BuildGraph(block.Body, block.EntryPoint);
 				graph.ComputeDominance();
 				graph.ComputeDominanceFrontier();
 				block.Body = FindConditions(new HashSet<ControlFlowNode>(graph.Nodes.Skip(3)), graph.EntryPoint);
 			}
 			
-			OrderNodes(method);
+			// OrderNodes(method);
 			FlattenNestedMovableBlocks(method);
 			SimpleGotoRemoval(method);
 			RemoveDeadLabels(method);
@@ -53,6 +55,7 @@ namespace Decompiler.ControlFlow
 		void SplitToMovableBlocks(ILBlock block)
 		{
 			// Remve no-ops
+			// TODO: Assign the no-op range to someting
 			block.Body = block.Body.Where(n => !(n is ILExpression && ((ILExpression)n).OpCode == OpCodes.Nop)).ToList();
 			
 			List<ILNode> moveableBlocks = new List<ILNode>();
@@ -153,7 +156,7 @@ namespace Decompiler.ControlFlow
 			return new ControlFlowGraph(cfNodes.ToArray());
 		}
 		
-		static List<ILNode> FindLoops(HashSet<ControlFlowNode> nodes, ControlFlowNode entryPoint)
+		List<ILNode> FindLoops(HashSet<ControlFlowNode> nodes, ControlFlowNode entryPoint, bool excludeEntryPoint)
 		{
 			List<ILNode> result = new List<ILNode>();
 			
@@ -164,14 +167,16 @@ namespace Decompiler.ControlFlow
 				
 				if (nodes.Contains(node)
 			    		&& node.DominanceFrontier.Contains(node)
-			    		&& node != entryPoint)
+			    		&& (node != entryPoint || !excludeEntryPoint))
 				{
 					HashSet<ControlFlowNode> loopContents = new HashSet<ControlFlowNode>();
 					FindLoopContents(nodes, loopContents, node, node);
 					
 					// Move the content into loop block
 					nodes.ExceptWith(loopContents);
-					result.Add(new ILLoop() { ContentBlock = new ILBlock(FindLoops(loopContents, node)) });
+					ILLabel entryLabel = new ILLabel() { Name = "Loop_" + (nextBlockIndex++) };
+					((ILBlock)node.UserData).Body.Insert(0, entryLabel);
+					result.Add(new ILLoop() { ContentBlock = new ILBlock(FindLoops(loopContents, node, true)) { EntryPoint = entryLabel } });
 				}
 
 				// Using the dominator tree should ensure we find the the widest loop first
@@ -206,58 +211,118 @@ namespace Decompiler.ControlFlow
 			while(agenda.Count > 0) {
 				ControlFlowNode node = agenda.Dequeue();
 				
-				ILMoveableBlock block = node.UserData as ILMoveableBlock;
-				
 				// Find a block that represents a simple condition
-				if (nodes.Contains(node) && block != null && block.Body.Count == 3) {
+				if (nodes.Contains(node)) {
 					
-					ILLabel      label      = block.Body[0] as ILLabel;
-					ILExpression condBranch = block.Body[1] as ILExpression;
-					ILExpression statBranch = block.Body[2] as ILExpression;
+					ILMoveableBlock block = node.UserData as ILMoveableBlock;
 					
-					if (label != null &&  
-					    condBranch != null && condBranch.Operand is ILLabel && condBranch.Arguments.Count > 0 &&
-					    statBranch != null && statBranch.Operand is ILLabel && statBranch.Arguments.Count == 0)
-					{
-						ControlFlowNode condTarget;
-						ControlFlowNode statTarget;
-						if (labelToCfNode.TryGetValue((ILLabel)condBranch.Operand, out condTarget) &&
-						    labelToCfNode.TryGetValue((ILLabel)statBranch.Operand, out statTarget))
+					if (block != null && block.Body.Count == 3) {
+						
+						ILLabel      label      = block.Body[0] as ILLabel;
+						ILExpression condBranch = block.Body[1] as ILExpression;
+						ILExpression statBranch = block.Body[2] as ILExpression;
+						
+						// Switch
+						if (label != null &&  
+						    condBranch != null && condBranch.Operand is ILLabel[] && condBranch.Arguments.Count > 0 &&
+						    statBranch != null && statBranch.Operand is ILLabel   && statBranch.Arguments.Count == 0)
+						{
+							ILSwitch ilSwitch = new ILSwitch() { Condition = condBranch };
+							
+							// Replace the two branches with a conditional structure - this preserves the node label
+							block.Body.Remove(condBranch);
+							block.Body.Remove(statBranch);
+							block.Body.Add(ilSwitch);
+							
+							ControlFlowNode statTarget = null;
+							labelToCfNode.TryGetValue((ILLabel)statBranch.Operand, out statTarget);
+							
+							// Pull in the conditional code
+							HashSet<ControlFlowNode> frontiers = new HashSet<ControlFlowNode>();
+							
+							if (statTarget != null)
+								frontiers.UnionWith(statTarget.DominanceFrontier);
+							
+							foreach(ILLabel condLabel in (ILLabel[])condBranch.Operand) {
+								ControlFlowNode condTarget = null;
+								labelToCfNode.TryGetValue(condLabel, out condTarget);
+								
+								if (condTarget != null)
+									frontiers.UnionWith(condTarget.DominanceFrontier);
+							}
+							
+							foreach(ILLabel condLabel in (ILLabel[])condBranch.Operand) {
+								ControlFlowNode condTarget = null;
+								labelToCfNode.TryGetValue(condLabel, out condTarget);
+								
+								ILBlock caseBlock = new ILBlock() { EntryPoint = condLabel };
+								if (condTarget != null && !frontiers.Contains(condTarget)) {
+									HashSet<ControlFlowNode> content = FindDominatedNodes(nodes, condTarget);
+									nodes.ExceptWith(content);
+									caseBlock.Body.AddRange(FindConditions(content, condTarget));
+								}
+								ilSwitch.CaseBlocks.Add(caseBlock);
+							}
+							
+							// The labels will not be used - kill them
+							condBranch.Operand = null;
+							
+							result.Add(block);
+							nodes.Remove(node);
+						}
+						
+						// Two-way branch
+						if (label != null &&  
+						    condBranch != null && condBranch.Operand is ILLabel && condBranch.Arguments.Count > 0 &&
+						    statBranch != null && statBranch.Operand is ILLabel && statBranch.Arguments.Count == 0)
 						{
+							ControlFlowNode statTarget = null;
+							labelToCfNode.TryGetValue((ILLabel)statBranch.Operand, out statTarget);
+							ControlFlowNode condTarget = null;
+							labelToCfNode.TryGetValue((ILLabel)condBranch.Operand, out condTarget);
+							
 							ILCondition condition = new ILCondition() {
 							    Condition  = condBranch,
 							    TrueBlock  = new ILBlock() { EntryPoint = (ILLabel)condBranch.Operand },
 							    FalseBlock = new ILBlock() { EntryPoint = (ILLabel)statBranch.Operand }
 							};
 							
-							// The label will not be used - kill it
-							condBranch.Operand = null;
-							
-							// Replace the two branches with a conditional structure
+							// Replace the two branches with a conditional structure - this preserves the node label
 							block.Body.Remove(condBranch);
 							block.Body.Remove(statBranch);
 							block.Body.Add(condition);
-							result.Add(block);
 							
 							// Pull in the conditional code
 							HashSet<ControlFlowNode> frontiers = new HashSet<ControlFlowNode>();
-							frontiers.UnionWith(condTarget.DominanceFrontier);
-							frontiers.UnionWith(statTarget.DominanceFrontier);
+							if (statTarget != null)
+								frontiers.UnionWith(statTarget.DominanceFrontier);
+							if (condTarget != null)
+								frontiers.UnionWith(condTarget.DominanceFrontier);
 							
-							if (!frontiers.Contains(condTarget)) {
+							if (condTarget != null && !frontiers.Contains(condTarget)) {
 								HashSet<ControlFlowNode> content = FindDominatedNodes(nodes, condTarget);
 								nodes.ExceptWith(content);
 								condition.TrueBlock.Body.AddRange(FindConditions(content, condTarget));
 							}
-							if (!frontiers.Contains(statTarget)) {
+							if (statTarget != null && !frontiers.Contains(statTarget)) {
 								HashSet<ControlFlowNode> content = FindDominatedNodes(nodes, statTarget);
 								nodes.ExceptWith(content);
 								condition.FalseBlock.Body.AddRange(FindConditions(content, statTarget));
 							}
 							
+							// The label will not be used - kill it
+							condBranch.Operand = null;
+							
+							result.Add(block);
 							nodes.Remove(node);
 						}
 					}
+					
+					// Add the node now so that we have good ordering
+					if (nodes.Contains(node)) {
+						result.Add((ILNode)node.UserData);
+						nodes.Remove(node);
+					}
 				}
 
 				// Using the dominator tree should ensure we find the the widest loop first
@@ -290,7 +355,8 @@ namespace Decompiler.ControlFlow
 					}
 				}
 			}
-			result.Add(head);
+			if (nodes.Contains(head))
+				result.Add(head);
 			
 			return result;
 		}
@@ -404,6 +470,7 @@ namespace Decompiler.ControlFlow
 		
 		void SimpleGotoRemoval(ILBlock ast)
 		{
+			// TODO: Assign IL ranges from br to something else
 			var blocks = ast.GetSelfAndChildrenRecursive<ILBlock>().ToList();
 			foreach(ILBlock block in blocks) {
 				for (int i = 0; i < block.Body.Count; i++) {
diff --git a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
index 3601c794b..61756612f 100644
--- a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
+++ b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
@@ -1,7 +1,7 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Text;
-
 using Decompiler.ControlFlow;
 using Mono.Cecil;
 using Mono.Cecil.Cil;
@@ -44,10 +44,16 @@ namespace Decompiler
 		{
 			yield break;
 		}
+		
+		public override string ToString()
+		{
+			return this.GetType().Name;
+		}
 	}
 	
 	public class ILBlock: ILNode
 	{
+		// TODO: This should really be a goto, not a label
 		public ILLabel EntryPoint;
 		
 		public List<ILNode> Body;
@@ -101,17 +107,13 @@ namespace Decompiler
 			if (this.FinallyBlock != null)
 				yield return this.FinallyBlock;
 		}
-		
-		public override string ToString()
-		{
-			return "Try-Catch{}";
-		}
 	}
 	
 	public class ILVariable
 	{
 		public string Name;
 		public bool   IsGenerated;
+		public TypeReference Type;
 		
 		public override string ToString()
 		{
@@ -119,17 +121,31 @@ namespace Decompiler
 		}
 	}
 	
+	public class ILRange
+	{
+		public int From;
+		public int To;   // Exlusive
+		
+		public override string ToString()
+		{
+			return string.Format("{0}-{1}", From, To);
+		}
+	}
+	
 	public class ILExpression: ILNode
 	{
 		public OpCode OpCode { get; set; }
 		public object Operand { get; set; }
 		public List<ILExpression> Arguments { get; set; }
+		// Mapping to the original instructions (useful for debugging)
+		public List<ILRange> ILRanges { get; set; }
 		
 		public ILExpression(OpCode opCode, object operand, params ILExpression[] args)
 		{
 			this.OpCode = opCode;
 			this.Operand = operand;
 			this.Arguments = new List<ILExpression>(args);
+			this.ILRanges  = new List<ILRange>(1);
 		}
 		
 		public IEnumerable<ILLabel> GetBranchTargets()
@@ -143,6 +159,27 @@ namespace Decompiler
 			}
 		}
 		
+		public List<ILRange> GetILRanges()
+		{
+			List<ILRange> ranges = new List<ILRange>();
+			foreach(ILExpression expr in this.GetSelfAndChildrenRecursive<ILExpression>()) {
+				ranges.AddRange(expr.ILRanges);
+			}
+			ranges = ranges.OrderBy(r => r.From).ToList();
+			for (int i = 0; i < ranges.Count - 1;) {
+				ILRange curr = ranges[i];
+				ILRange next = ranges[i + 1];
+				// Merge consequtive ranges if they intersect
+				if (curr.From <= next.From && next.From <= curr.To) {
+					curr.To = Math.Max(curr.To, next.To);
+					ranges.RemoveAt(i + 1);
+				} else {
+					i++;
+				}
+			}
+			return ranges;
+		}
+		
 		public override IEnumerable<ILNode> GetChildren()
 		{
 			return Arguments;
@@ -191,4 +228,18 @@ namespace Decompiler
 			yield return FalseBlock;
 		}
 	}
+	
+	public class ILSwitch: ILNode
+	{
+		public ILExpression Condition;
+		public List<ILBlock> CaseBlocks = new List<ILBlock>();
+		
+		public override IEnumerable<ILNode> GetChildren()
+		{
+			yield return Condition;
+			foreach (ILBlock caseBlock in this.CaseBlocks) {
+				yield return caseBlock;
+			}
+		}
+	}
 }
diff --git a/ILSpy/CSharpLanguage.cs b/ILSpy/CSharpLanguage.cs
index 5fdf8ea58..3368f1594 100644
--- a/ILSpy/CSharpLanguage.cs
+++ b/ILSpy/CSharpLanguage.cs
@@ -17,9 +17,11 @@
 // DEALINGS IN THE SOFTWARE.
 
 using System;
+using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using Decompiler;
+using Decompiler.Transforms;
 using ICSharpCode.Decompiler;
 using ICSharpCode.NRefactory.CSharp;
 using Mono.Cecil;
@@ -31,8 +33,33 @@ namespace ICSharpCode.ILSpy
 	/// </summary>
 	public class CSharpLanguage : Language
 	{
+		string name = "C#";
+		Predicate<IAstVisitor<object, object>> transformAbortCondition;
+		
+		public CSharpLanguage()
+		{
+		}
+		
+		#if DEBUG
+		internal static IEnumerable<CSharpLanguage> GetDebugLanguages()
+		{
+			string lastTransformName = "no transforms";
+			foreach (Type _transformType in TransformationPipeline.CreatePipeline().Select(v => v.GetType()).Distinct()) {
+				Type transformType = _transformType; // copy for lambda
+				yield return new CSharpLanguage {
+					transformAbortCondition = v => transformType.IsInstanceOfType(v),
+					name = "C# - " + lastTransformName
+				};
+				lastTransformName = "after " + transformType.Name;
+			}
+			yield return new CSharpLanguage {
+				name = "C# - " + lastTransformName
+			};
+		}
+		#endif
+		
 		public override string Name {
-			get { return "C#"; }
+			get { return name; }
 		}
 		
 		public override string FileExtension {
@@ -43,35 +70,35 @@ namespace ICSharpCode.ILSpy
 		{
 			AstBuilder codeDomBuilder = new AstBuilder();
 			codeDomBuilder.AddMethod(method);
-			codeDomBuilder.GenerateCode(output);
+			codeDomBuilder.GenerateCode(output, transformAbortCondition);
 		}
 		
 		public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options)
 		{
 			AstBuilder codeDomBuilder = new AstBuilder();
 			codeDomBuilder.AddProperty(property);
-			codeDomBuilder.GenerateCode(output);
+			codeDomBuilder.GenerateCode(output, transformAbortCondition);
 		}
 		
 		public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
 		{
 			AstBuilder codeDomBuilder = new AstBuilder();
 			codeDomBuilder.AddField(field);
-			codeDomBuilder.GenerateCode(output);
+			codeDomBuilder.GenerateCode(output, transformAbortCondition);
 		}
 		
 		public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options)
 		{
 			AstBuilder codeDomBuilder = new AstBuilder();
 			codeDomBuilder.AddEvent(ev);
-			codeDomBuilder.GenerateCode(output);
+			codeDomBuilder.GenerateCode(output, transformAbortCondition);
 		}
 		
 		public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
 		{
 			AstBuilder codeDomBuilder = new AstBuilder();
 			codeDomBuilder.AddType(type);
-			codeDomBuilder.GenerateCode(output);
+			codeDomBuilder.GenerateCode(output, transformAbortCondition);
 		}
 		
 		public override string TypeToString(TypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes)
diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj
index ea9ce1f0f..6a2e2140d 100644
--- a/ILSpy/ILSpy.csproj
+++ b/ILSpy/ILSpy.csproj
@@ -237,8 +237,5 @@
     <Folder Include="TreeNodes" />
     <Folder Include="TextView" />
   </ItemGroup>
-  <ItemGroup>
-    <Content Include="ProfilingSessions\Session20110214_003955.sdps" />
-  </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
 </Project>
\ No newline at end of file
diff --git a/ILSpy/Language.cs b/ILSpy/Language.cs
index fe1b34d85..ea4306dc7 100644
--- a/ILSpy/Language.cs
+++ b/ILSpy/Language.cs
@@ -120,11 +120,15 @@ namespace ICSharpCode.ILSpy
 		/// <summary>
 		/// A list of all languages.
 		/// </summary>
-		public static readonly ReadOnlyCollection<Language> AllLanguages = Array.AsReadOnly(
+		public static readonly ReadOnlyCollection<Language> AllLanguages = new List<Language>(
 			new Language[] {
 				new CSharpLanguage(),
 				new ILLanguage(true)
-			});
+			}
+			#if DEBUG
+			.Concat(CSharpLanguage.GetDebugLanguages())
+			#endif
+		).AsReadOnly();
 		
 		/// <summary>
 		/// Gets a language using its name.
diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml
index a79644072..c9423e9aa 100644
--- a/ILSpy/MainWindow.xaml
+++ b/ILSpy/MainWindow.xaml
@@ -11,6 +11,7 @@
 	MinHeight="200"
 	UseLayoutRounding="True"
 	TextOptions.TextFormattingMode="Display"
+	Icon="pack://application:,,,/ILSpy;component/images/Find.png"
 	FocusManager.FocusedElement="{Binding ElementName=treeView}"
 >
 	<Window.Resources>
diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstComparer.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstComparer.cs
index ab74a4fc5..61d6fd4f1 100644
--- a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstComparer.cs
+++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstComparer.cs
@@ -31,6 +31,8 @@ namespace ICSharpCode.NRefactory.CSharp
 			bool? result = true;
 			while (result != false && (child1 != null || child2 != null)) {
 				result &= AreEqual(child1, child2);
+				child1 = child1.NextSibling;
+				child2 = child2.NextSibling;
 			}
 			if (nodeTypesWithoutExtraInfo.Contains(nodeType))
 				return result;