PageRenderTime 117ms CodeModel.GetById 30ms app.highlight 74ms RepoModel.GetById 1ms app.codeStats 1ms

/NRefactory/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs

http://github.com/icsharpcode/ILSpy
C# | 2282 lines | 1898 code | 359 blank | 25 comment | 266 complexity | 9cc08f9a5125d3b1ef3bac7e12e363a3 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
   2// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
   3
   4using System;
   5using System.Collections.Generic;
   6using System.Linq;
   7
   8using ICSharpCode.NRefactory.PatternMatching;
   9using ICSharpCode.NRefactory.TypeSystem;
  10using ICSharpCode.NRefactory.VB.Ast;
  11
  12namespace ICSharpCode.NRefactory.VB.Visitors
  13{
  14	public interface IEnvironmentProvider
  15	{
  16		string RootNamespace { get; }
  17		string GetTypeNameForAttribute(CSharp.Attribute attribute);
  18		TypeKind GetTypeKindForAstType(CSharp.AstType type);
  19		TypeCode ResolveExpression(CSharp.Expression expression);
  20		bool? IsReferenceType(CSharp.Expression expression);
  21		//ITypeResolveContext ResolveContext { get; }
  22		IType ResolveType(AstType type, TypeDeclaration entity = null);
  23		bool IsMethodGroup(CSharp.Expression expression);
  24		bool HasEvent(Expression expression);
  25	}
  26	
  27	/// <summary>
  28	/// Description of CSharpToVBConverterVisitor.
  29	/// </summary>
  30	public class CSharpToVBConverterVisitor : CSharp.IAstVisitor<object, VB.AstNode>
  31	{
  32		IEnvironmentProvider provider;
  33		Stack<BlockStatement> blocks;
  34		Stack<TypeDeclaration> types;
  35		Stack<MemberInfo> members;
  36		
  37		class MemberInfo
  38		{
  39			public bool inIterator;
  40		}
  41		
  42		public CSharpToVBConverterVisitor(IEnvironmentProvider provider)
  43		{
  44			this.provider = provider;
  45			this.blocks = new Stack<BlockStatement>();
  46			this.types = new Stack<TypeDeclaration>();
  47			this.members = new Stack<MemberInfo>();
  48		}
  49		
  50		public AstNode VisitAnonymousMethodExpression(CSharp.AnonymousMethodExpression anonymousMethodExpression, object data)
  51		{
  52			members.Push(new MemberInfo());
  53			
  54			var expr = new MultiLineLambdaExpression() {
  55				IsSub = true,
  56				Body = (BlockStatement)anonymousMethodExpression.Body.AcceptVisitor(this, data)
  57			};
  58			
  59			ConvertNodes(anonymousMethodExpression.Parameters, expr.Parameters);
  60			
  61			if (members.Pop().inIterator) {
  62				expr.Modifiers |= LambdaExpressionModifiers.Iterator;
  63			}
  64			
  65			return EndNode(anonymousMethodExpression, expr);
  66		}
  67		
  68		public AstNode VisitUndocumentedExpression(CSharp.UndocumentedExpression undocumentedExpression, object data)
  69		{
  70			var invocation = new InvocationExpression();
  71			
  72			switch (undocumentedExpression.UndocumentedExpressionType) {
  73				case CSharp.UndocumentedExpressionType.ArgListAccess:
  74				case CSharp.UndocumentedExpressionType.ArgList:
  75					invocation.Target = new IdentifierExpression { Identifier = "__ArgList" };
  76					break;
  77				case CSharp.UndocumentedExpressionType.RefValue:
  78					invocation.Target = new IdentifierExpression { Identifier = "__RefValue" };
  79					break;
  80				case CSharp.UndocumentedExpressionType.RefType:
  81					invocation.Target = new IdentifierExpression { Identifier = "__RefType" };
  82					break;
  83				case CSharp.UndocumentedExpressionType.MakeRef:
  84					invocation.Target = new IdentifierExpression { Identifier = "__MakeRef" };
  85					break;
  86				default:
  87					throw new Exception("Invalid value for UndocumentedExpressionType");
  88			}
  89			
  90			ConvertNodes(undocumentedExpression.Arguments, invocation.Arguments);
  91			
  92			return EndNode(undocumentedExpression, invocation);
  93		}
  94		
  95		public AstNode VisitArrayCreateExpression(CSharp.ArrayCreateExpression arrayCreateExpression, object data)
  96		{
  97			var expr = new ArrayCreateExpression() {
  98				Type = (AstType)arrayCreateExpression.Type.AcceptVisitor(this, data),
  99				Initializer = (ArrayInitializerExpression)arrayCreateExpression.Initializer.AcceptVisitor(this, data)
 100			};
 101			ConvertNodes(arrayCreateExpression.Arguments, expr.Arguments,
 102			             n => new BinaryOperatorExpression(n, BinaryOperatorType.Subtract, new PrimitiveExpression(1)));
 103			ConvertNodes(arrayCreateExpression.AdditionalArraySpecifiers, expr.AdditionalArraySpecifiers);
 104			
 105			return EndNode(arrayCreateExpression, expr);
 106		}
 107		
 108		public AstNode VisitArrayInitializerExpression(CSharp.ArrayInitializerExpression arrayInitializerExpression, object data)
 109		{
 110			var expr = new ArrayInitializerExpression();
 111			ConvertNodes(arrayInitializerExpression.Elements, expr.Elements);
 112			
 113			return EndNode(arrayInitializerExpression, expr);
 114		}
 115		
 116		public AstNode VisitAsExpression(CSharp.AsExpression asExpression, object data)
 117		{
 118			return EndNode(asExpression, new CastExpression(CastType.TryCast, (AstType)asExpression.Type.AcceptVisitor(this, data), (Expression)asExpression.Expression.AcceptVisitor(this, data)));
 119		}
 120		
 121		public AstNode VisitAssignmentExpression(CSharp.AssignmentExpression assignmentExpression, object data)
 122		{
 123			var left = (Expression)assignmentExpression.Left.AcceptVisitor(this, data);
 124			var op = AssignmentOperatorType.None;
 125			var right = (Expression)assignmentExpression.Right.AcceptVisitor(this, data);
 126			
 127			switch (assignmentExpression.Operator) {
 128				case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Assign:
 129					op = AssignmentOperatorType.Assign;
 130					break;
 131				case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Add:
 132					if (provider.HasEvent(left)) {
 133						var addHandler = new AddRemoveHandlerStatement { IsAddHandler = true };
 134						addHandler.EventExpression = left;
 135						addHandler.DelegateExpression = right;
 136						return EndNode(assignmentExpression, addHandler);
 137					}
 138					op = AssignmentOperatorType.Add;
 139					break;
 140				case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Subtract:
 141					if (provider.HasEvent(left)) {
 142						var addHandler = new AddRemoveHandlerStatement { IsAddHandler = false };
 143						addHandler.EventExpression = left;
 144						addHandler.DelegateExpression = right;
 145						return EndNode(assignmentExpression, addHandler);
 146					}
 147					op = AssignmentOperatorType.Subtract;
 148					break;
 149				case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Multiply:
 150					op = AssignmentOperatorType.Multiply;
 151					break;
 152				case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Divide:
 153					op = AssignmentOperatorType.Divide;
 154					break;
 155				case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Modulus:
 156					op = AssignmentOperatorType.Assign;
 157					right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.Modulus, right);
 158					break;
 159				case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ShiftLeft:
 160					op = AssignmentOperatorType.ShiftLeft;
 161					break;
 162				case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ShiftRight:
 163					op = AssignmentOperatorType.ShiftRight;
 164					break;
 165				case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.BitwiseAnd:
 166					op = AssignmentOperatorType.Assign;
 167					right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.BitwiseAnd, right);
 168					break;
 169				case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.BitwiseOr:
 170					op = AssignmentOperatorType.Assign;
 171					right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.BitwiseOr, right);
 172					break;
 173				case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ExclusiveOr:
 174					op = AssignmentOperatorType.Assign;
 175					right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.ExclusiveOr, right);
 176					break;
 177				default:
 178					throw new Exception("Invalid value for AssignmentOperatorType: " + assignmentExpression.Operator);
 179			}
 180			
 181			var expr = new AssignmentExpression(left, op, right);
 182			return EndNode(assignmentExpression, expr);
 183		}
 184		
 185		public AstNode VisitBaseReferenceExpression(CSharp.BaseReferenceExpression baseReferenceExpression, object data)
 186		{
 187			InstanceExpression result = new InstanceExpression(InstanceExpressionType.MyBase, baseReferenceExpression.StartLocation);
 188			
 189			return EndNode(baseReferenceExpression, result);
 190		}
 191		
 192		public AstNode VisitBinaryOperatorExpression(CSharp.BinaryOperatorExpression binaryOperatorExpression, object data)
 193		{
 194			var left = (Expression)binaryOperatorExpression.Left.AcceptVisitor(this, data);
 195			var op = BinaryOperatorType.None;
 196			var right = (Expression)binaryOperatorExpression.Right.AcceptVisitor(this, data);
 197			
 198			switch (binaryOperatorExpression.Operator) {
 199				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.BitwiseAnd:
 200					op = BinaryOperatorType.BitwiseAnd;
 201					break;
 202				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.BitwiseOr:
 203					op = BinaryOperatorType.BitwiseOr;
 204					break;
 205				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ConditionalAnd:
 206					op = BinaryOperatorType.LogicalAnd;
 207					break;
 208				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ConditionalOr:
 209					op = BinaryOperatorType.LogicalOr;
 210					break;
 211				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ExclusiveOr:
 212					op = BinaryOperatorType.ExclusiveOr;
 213					break;
 214				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.GreaterThan:
 215					op = BinaryOperatorType.GreaterThan;
 216					break;
 217				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.GreaterThanOrEqual:
 218					op = BinaryOperatorType.GreaterThanOrEqual;
 219					break;
 220				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Equality:
 221					if (IsReferentialEquality(binaryOperatorExpression))
 222						op = BinaryOperatorType.ReferenceEquality;
 223					else
 224						op = BinaryOperatorType.Equality;
 225					break;
 226				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.InEquality:
 227					if (IsReferentialEquality(binaryOperatorExpression))
 228						op = BinaryOperatorType.ReferenceInequality;
 229					else
 230						op = BinaryOperatorType.InEquality;
 231					break;
 232				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.LessThan:
 233					op = BinaryOperatorType.LessThan;
 234					break;
 235				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.LessThanOrEqual:
 236					op = BinaryOperatorType.LessThanOrEqual;
 237					break;
 238				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Add:
 239					// TODO might be string concatenation
 240					op = BinaryOperatorType.Add;
 241					break;
 242				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Subtract:
 243					op = BinaryOperatorType.Subtract;
 244					break;
 245				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Multiply:
 246					op = BinaryOperatorType.Multiply;
 247					break;
 248				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Divide:
 249					op = BinaryOperatorType.Divide;
 250					break;
 251				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Modulus:
 252					op = BinaryOperatorType.Modulus;
 253					break;
 254				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ShiftLeft:
 255					op = BinaryOperatorType.ShiftLeft;
 256					break;
 257				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ShiftRight:
 258					op = BinaryOperatorType.ShiftRight;
 259					break;
 260				case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.NullCoalescing:
 261					var nullCoalescing = new ConditionalExpression {
 262						ConditionExpression = left,
 263						FalseExpression = right
 264					};
 265					return EndNode(binaryOperatorExpression, nullCoalescing);
 266				default:
 267					throw new Exception("Invalid value for BinaryOperatorType: " + binaryOperatorExpression.Operator);
 268			}
 269			
 270			return EndNode(binaryOperatorExpression, new BinaryOperatorExpression(left, op, right));
 271		}
 272		
 273		bool IsReferentialEquality(CSharp.BinaryOperatorExpression binaryOperatorExpression)
 274		{
 275			var left = provider.IsReferenceType(binaryOperatorExpression.Left);
 276			var right = provider.IsReferenceType(binaryOperatorExpression.Right);
 277			
 278			var leftCode = provider.ResolveExpression(binaryOperatorExpression.Left);
 279			var rightCode = provider.ResolveExpression(binaryOperatorExpression.Right);
 280			
 281			return (left == true || right == true) && (leftCode != TypeCode.String && rightCode != TypeCode.String);
 282		}
 283		
 284		public AstNode VisitCastExpression(CSharp.CastExpression castExpression, object data)
 285		{
 286			var expr = new CastExpression();
 287			
 288			expr.Type = (AstType)castExpression.Type.AcceptVisitor(this, data);
 289			// TODO read additional type information from annotation
 290			// (int)x is equivalent to CInt(Math.Truncate(x))
 291			expr.CastType = GetCastType(expr.Type, null);
 292			expr.Expression = (Expression)castExpression.Expression.AcceptVisitor(this, data);
 293			
 294			if (expr.CastType != CastType.CType)
 295				expr.Type = null;
 296			
 297			return EndNode(castExpression, expr);
 298		}
 299		
 300		CastType GetCastType(AstType type, object typeInformation)
 301		{
 302			var primType = type as PrimitiveType;
 303			if (primType == null)
 304				return CastType.CType;
 305			
 306			switch (primType.Keyword) {
 307				case "Boolean":
 308					return CastType.CBool;
 309				case "Byte":
 310					return CastType.CByte;
 311				case "Char":
 312					return CastType.CChar;
 313				case "Date":
 314					return CastType.CDate;
 315				case "Double":
 316					return CastType.CDbl;
 317				case "Decimal":
 318					return CastType.CDec;
 319				case "Integer":
 320					return CastType.CInt;
 321				case "Long":
 322					return CastType.CLng;
 323				case "Object":
 324					return CastType.CObj;
 325				case "SByte":
 326					return CastType.CSByte;
 327				case "Short":
 328					return CastType.CShort;
 329				case "Single":
 330					return CastType.CSng;
 331				case "String":
 332					return CastType.CStr;
 333				case "UInteger":
 334					return CastType.CUInt;
 335				case "ULong":
 336					return CastType.CULng;
 337				case "UShort":
 338					return CastType.CUShort;
 339			}
 340			
 341			return CastType.CType;
 342		}
 343		
 344		public AstNode VisitCheckedExpression(CSharp.CheckedExpression checkedExpression, object data)
 345		{
 346			blocks.Peek().AddChild(new Comment(" The following expression was wrapped in a checked-expression", false), AstNode.Roles.Comment);
 347			return EndNode(checkedExpression, checkedExpression.Expression.AcceptVisitor(this, data));
 348		}
 349		
 350		public AstNode VisitConditionalExpression(CSharp.ConditionalExpression conditionalExpression, object data)
 351		{
 352			var cond = new ConditionalExpression() {
 353				ConditionExpression = (Expression)conditionalExpression.Condition.AcceptVisitor(this, data),
 354				TrueExpression = (Expression)conditionalExpression.TrueExpression.AcceptVisitor(this, data),
 355				FalseExpression = (Expression)conditionalExpression.FalseExpression.AcceptVisitor(this, data)
 356			};
 357			
 358			return EndNode(conditionalExpression, cond);
 359		}
 360		
 361		public AstNode VisitDefaultValueExpression(CSharp.DefaultValueExpression defaultValueExpression, object data)
 362		{
 363			// Nothing is equivalent to default(T) for reference and value types.
 364			return EndNode(defaultValueExpression, new PrimitiveExpression(null));
 365		}
 366		
 367		public AstNode VisitDirectionExpression(CSharp.DirectionExpression directionExpression, object data)
 368		{
 369			return EndNode(directionExpression, (Expression)directionExpression.Expression.AcceptVisitor(this, data));
 370		}
 371		
 372		public AstNode VisitIdentifierExpression(CSharp.IdentifierExpression identifierExpression, object data)
 373		{
 374			var expr = new IdentifierExpression();
 375			expr.Identifier = new Identifier(identifierExpression.Identifier, TextLocation.Empty);
 376			ConvertNodes(identifierExpression.TypeArguments, expr.TypeArguments);
 377			if (provider.IsMethodGroup(identifierExpression)) {
 378				return EndNode(identifierExpression, new UnaryOperatorExpression(UnaryOperatorType.AddressOf, expr));
 379			}
 380			
 381			return EndNode(identifierExpression, expr);
 382		}
 383		
 384		public AstNode VisitIndexerExpression(CSharp.IndexerExpression indexerExpression, object data)
 385		{
 386			var expr = new InvocationExpression((Expression)indexerExpression.Target.AcceptVisitor(this, data));
 387			ConvertNodes(indexerExpression.Arguments, expr.Arguments);
 388			return EndNode(indexerExpression, expr);
 389		}
 390		
 391		public AstNode VisitInvocationExpression(CSharp.InvocationExpression invocationExpression, object data)
 392		{
 393			var expr = new InvocationExpression((Expression)invocationExpression.Target.AcceptVisitor(this, data));
 394			ConvertNodes(invocationExpression.Arguments, expr.Arguments);
 395			return EndNode(invocationExpression, expr);
 396		}
 397		
 398		public AstNode VisitIsExpression(CSharp.IsExpression isExpression, object data)
 399		{
 400			var expr = new TypeOfIsExpression() {
 401				Type = (AstType)isExpression.Type.AcceptVisitor(this, data),
 402				TypeOfExpression = (Expression)isExpression.Expression.AcceptVisitor(this, data)
 403			};
 404			
 405			return EndNode(isExpression, expr);
 406		}
 407		
 408		public AstNode VisitLambdaExpression(CSharp.LambdaExpression lambdaExpression, object data)
 409		{
 410			LambdaExpression expr = null;
 411			
 412			if (lambdaExpression.Body is CSharp.Expression) {
 413				var singleLine = new SingleLineFunctionLambdaExpression() {
 414					EmbeddedExpression = (Expression)lambdaExpression.Body.AcceptVisitor(this, data)
 415				};
 416				ConvertNodes(lambdaExpression.Parameters, singleLine.Parameters);
 417				expr = singleLine;
 418			} else
 419				throw new NotImplementedException();
 420			
 421			return EndNode(lambdaExpression, expr);
 422		}
 423		
 424		public AstNode VisitMemberReferenceExpression(CSharp.MemberReferenceExpression memberReferenceExpression, object data)
 425		{
 426			var memberAccessExpression = new MemberAccessExpression();
 427			
 428			memberAccessExpression.Target = (Expression)memberReferenceExpression.Target.AcceptVisitor(this, data);
 429			memberAccessExpression.MemberName = new Identifier(memberReferenceExpression.MemberName, TextLocation.Empty);
 430			ConvertNodes(memberReferenceExpression.TypeArguments, memberAccessExpression.TypeArguments);
 431			if (provider.IsMethodGroup(memberReferenceExpression)) {
 432				return EndNode(memberReferenceExpression, new UnaryOperatorExpression(UnaryOperatorType.AddressOf, memberAccessExpression));
 433			}
 434			
 435			return EndNode(memberReferenceExpression, memberAccessExpression);
 436		}
 437		
 438		public AstNode VisitNamedArgumentExpression(CSharp.NamedArgumentExpression namedArgumentExpression, object data)
 439		{
 440			Expression expr = new NamedArgumentExpression {
 441				Identifier = namedArgumentExpression.Name,
 442				Expression = (Expression)namedArgumentExpression.Expression.AcceptVisitor(this, data)
 443			};
 444			
 445			return EndNode(namedArgumentExpression, expr);
 446		}
 447		
 448		public AstNode VisitNamedExpression(CSharp.NamedExpression namedExpression, object data)
 449		{
 450			Expression expr = new FieldInitializerExpression {
 451				IsKey = true,
 452				Identifier = namedExpression.Name,
 453				Expression = (Expression)namedExpression.Expression.AcceptVisitor(this, data)
 454			};
 455			return EndNode(namedExpression, expr);
 456		}
 457		
 458		public AstNode VisitNullReferenceExpression(CSharp.NullReferenceExpression nullReferenceExpression, object data)
 459		{
 460			return EndNode(nullReferenceExpression, new PrimitiveExpression(null));
 461		}
 462		
 463		public AstNode VisitObjectCreateExpression(CSharp.ObjectCreateExpression objectCreateExpression, object data)
 464		{
 465			var expr = new ObjectCreationExpression((AstType)objectCreateExpression.Type.AcceptVisitor(this, data));
 466			ConvertNodes(objectCreateExpression.Arguments, expr.Arguments);
 467			var arg1 = expr.Arguments.FirstOrDefault() as UnaryOperatorExpression;
 468			if (arg1 != null && arg1.Operator == UnaryOperatorType.AddressOf) {
 469				arg1.Remove();
 470				return EndNode(objectCreateExpression, arg1);
 471			}
 472			if (!objectCreateExpression.Initializer.IsNull)
 473				expr.Initializer = (ArrayInitializerExpression)objectCreateExpression.Initializer.AcceptVisitor(this, data);
 474			
 475			return EndNode(objectCreateExpression, expr);
 476		}
 477		
 478		public AstNode VisitAnonymousTypeCreateExpression(CSharp.AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data)
 479		{
 480			var expr = new AnonymousObjectCreationExpression();
 481			
 482			ConvertNodes(anonymousTypeCreateExpression.Initializers, expr.Initializer);
 483			
 484			return EndNode(anonymousTypeCreateExpression, expr);
 485		}
 486		
 487		public AstNode VisitParenthesizedExpression(CSharp.ParenthesizedExpression parenthesizedExpression, object data)
 488		{
 489			var result = new ParenthesizedExpression();
 490			
 491			result.Expression = (Expression)parenthesizedExpression.Expression.AcceptVisitor(this, data);
 492			
 493			return EndNode(parenthesizedExpression, result);
 494		}
 495		
 496		public AstNode VisitPointerReferenceExpression(CSharp.PointerReferenceExpression pointerReferenceExpression, object data)
 497		{
 498			return EndNode(pointerReferenceExpression,((Expression)pointerReferenceExpression.Target.AcceptVisitor(this, data)).Invoke("Dereference").Member(pointerReferenceExpression.MemberName));
 499		}
 500		
 501		public AstNode VisitPrimitiveExpression(CSharp.PrimitiveExpression primitiveExpression, object data)
 502		{
 503			Expression expr;
 504			
 505			if (!string.IsNullOrEmpty(primitiveExpression.Value as string) || primitiveExpression.Value is char)
 506				expr = ConvertToConcat(primitiveExpression.Value.ToString());
 507			else
 508				expr = new PrimitiveExpression(primitiveExpression.Value);
 509			
 510			return EndNode(primitiveExpression, expr);
 511		}
 512		
 513		Expression ConvertToConcat(string literal)
 514		{
 515			Stack<Expression> parts = new Stack<Expression>();
 516			int start = 0;
 517			
 518			for (int i = 0; i < literal.Length; i++) {
 519				string part;
 520				switch (literal[i]) {
 521					case '\0':
 522						part = literal.Substring(start, i - start);
 523						if (!string.IsNullOrEmpty(part))
 524							parts.Push(new PrimitiveExpression(part));
 525						parts.Push(new IdentifierExpression("vbNullChar"));
 526						start = i + 1;
 527						break;
 528					case '\b':
 529						part = literal.Substring(start, i - start);
 530						if (!string.IsNullOrEmpty(part))
 531							parts.Push(new PrimitiveExpression(part));
 532						parts.Push(new IdentifierExpression("vbBack"));
 533						start = i + 1;
 534						break;
 535					case '\f':
 536						part = literal.Substring(start, i - start);
 537						if (!string.IsNullOrEmpty(part))
 538							parts.Push(new PrimitiveExpression(part));
 539						parts.Push(new IdentifierExpression("vbFormFeed"));
 540						start = i + 1;
 541						break;
 542					case '\r':
 543						part = literal.Substring(start, i - start);
 544						if (!string.IsNullOrEmpty(part))
 545							parts.Push(new PrimitiveExpression(part));
 546						if (i + 1 < literal.Length && literal[i + 1] == '\n') {
 547							i++;
 548							parts.Push(new IdentifierExpression("vbCrLf"));
 549						} else
 550							parts.Push(new IdentifierExpression("vbCr"));
 551						start = i + 1;
 552						break;
 553					case '\n':
 554						part = literal.Substring(start, i - start);
 555						if (!string.IsNullOrEmpty(part))
 556							parts.Push(new PrimitiveExpression(part));
 557						parts.Push(new IdentifierExpression("vbLf"));
 558						start = i + 1;
 559						break;
 560					case '\t':
 561						part = literal.Substring(start, i - start);
 562						if (!string.IsNullOrEmpty(part))
 563							parts.Push(new PrimitiveExpression(part));
 564						parts.Push(new IdentifierExpression("vbTab"));
 565						start = i + 1;
 566						break;
 567					case '\v':
 568						part = literal.Substring(start, i - start);
 569						if (!string.IsNullOrEmpty(part))
 570							parts.Push(new PrimitiveExpression(part));
 571						parts.Push(new IdentifierExpression("vbVerticalTab"));
 572						start = i + 1;
 573						break;
 574					default:
 575						if ((int)literal[i] > 255) {
 576							part = literal.Substring(start, i - start);
 577							if (!string.IsNullOrEmpty(part))
 578								parts.Push(new PrimitiveExpression(part));
 579							parts.Push(new InvocationExpression(new IdentifierExpression("ChrW"), new PrimitiveExpression((int)literal[i])));
 580						} else
 581							continue;
 582						start = i + 1;
 583						break;
 584				}
 585				
 586			}
 587			
 588			if (start < literal.Length) {
 589				string part = literal.Substring(start);
 590				parts.Push(new PrimitiveExpression(part));
 591			}
 592			
 593			Expression current = parts.Pop();
 594			
 595			while (parts.Any())
 596				current = new BinaryOperatorExpression(parts.Pop(), BinaryOperatorType.Concat, current);
 597			
 598			return current;
 599		}
 600		
 601		public AstNode VisitSizeOfExpression(CSharp.SizeOfExpression sizeOfExpression, object data)
 602		{
 603			return EndNode(
 604				sizeOfExpression,
 605				new InvocationExpression(
 606					new IdentifierExpression() { Identifier = "__SizeOf" },
 607					new TypeReferenceExpression((AstType)sizeOfExpression.Type.AcceptVisitor(this, data))
 608				)
 609			);
 610		}
 611		
 612		public AstNode VisitStackAllocExpression(CSharp.StackAllocExpression stackAllocExpression, object data)
 613		{
 614			return EndNode(
 615				stackAllocExpression,
 616				new InvocationExpression(
 617					new IdentifierExpression() { Identifier = "__StackAlloc" },
 618					new TypeReferenceExpression((AstType)stackAllocExpression.Type.AcceptVisitor(this, data)),
 619					(Expression)stackAllocExpression.CountExpression.AcceptVisitor(this, data)
 620				)
 621			);
 622		}
 623		
 624		public AstNode VisitThisReferenceExpression(CSharp.ThisReferenceExpression thisReferenceExpression, object data)
 625		{
 626			InstanceExpression result = new InstanceExpression(InstanceExpressionType.Me, thisReferenceExpression.StartLocation);
 627			return EndNode(thisReferenceExpression, result);
 628		}
 629		
 630		public AstNode VisitTypeOfExpression(CSharp.TypeOfExpression typeOfExpression, object data)
 631		{
 632			var expr = new GetTypeExpression();
 633			expr.Type = (AstType)typeOfExpression.Type.AcceptVisitor(this, data);
 634			return EndNode(typeOfExpression, expr);
 635		}
 636		
 637		public AstNode VisitTypeReferenceExpression(CSharp.TypeReferenceExpression typeReferenceExpression, object data)
 638		{
 639			var expr = new TypeReferenceExpression((AstType)typeReferenceExpression.Type.AcceptVisitor(this, data));
 640			return EndNode(typeReferenceExpression, expr);
 641		}
 642		
 643		public AstNode VisitUnaryOperatorExpression(CSharp.UnaryOperatorExpression unaryOperatorExpression, object data)
 644		{
 645			Expression expr;
 646
 647			switch (unaryOperatorExpression.Operator) {
 648				case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Not:
 649				case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.BitNot:
 650					expr = new UnaryOperatorExpression() {
 651						Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data),
 652						Operator = UnaryOperatorType.Not
 653					};
 654					break;
 655				case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Minus:
 656					expr = new UnaryOperatorExpression() {
 657						Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data),
 658						Operator = UnaryOperatorType.Minus
 659					};
 660					break;
 661				case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Plus:
 662					expr = new UnaryOperatorExpression() {
 663						Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data),
 664						Operator = UnaryOperatorType.Plus
 665					};
 666					break;
 667				case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Increment:
 668					expr = new InvocationExpression();
 669					((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__Increment" };
 670					((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data));
 671					break;
 672				case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.PostIncrement:
 673					expr = new InvocationExpression();
 674					((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__PostIncrement" };
 675					((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data));
 676					break;
 677				case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Decrement:
 678					expr = new InvocationExpression();
 679					((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__Decrement" };
 680					((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data));
 681					break;
 682				case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.PostDecrement:
 683					expr = new InvocationExpression();
 684					((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__PostDecrement" };
 685					((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data));
 686					break;
 687				case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.AddressOf:
 688					expr = new UnaryOperatorExpression() {
 689						Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data),
 690						Operator = UnaryOperatorType.AddressOf
 691					};
 692					break;
 693				case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Dereference:
 694					expr = new InvocationExpression();
 695					((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__Dereference" };
 696					((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data));
 697					break;
 698				case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Await:
 699					expr = new UnaryOperatorExpression() {
 700						Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data),
 701						Operator = UnaryOperatorType.Await
 702					};
 703					break;
 704				default:
 705					throw new Exception("Invalid value for UnaryOperatorType");
 706			}
 707			
 708			return EndNode(unaryOperatorExpression, expr);
 709		}
 710		
 711		public AstNode VisitUncheckedExpression(CSharp.UncheckedExpression uncheckedExpression, object data)
 712		{
 713			blocks.Peek().AddChild(new Comment(" The following expression was wrapped in a unchecked-expression", false), AstNode.Roles.Comment);
 714			return EndNode(uncheckedExpression, uncheckedExpression.Expression.AcceptVisitor(this, data));
 715		}
 716		
 717		public AstNode VisitQueryExpression(CSharp.QueryExpression queryExpression, object data)
 718		{
 719			var expr = new QueryExpression();
 720			ConvertNodes(queryExpression.Clauses, expr.QueryOperators);
 721			return EndNode(queryExpression, expr);
 722		}
 723		
 724		public AstNode VisitQueryContinuationClause(CSharp.QueryContinuationClause queryContinuationClause, object data)
 725		{
 726			throw new NotImplementedException();
 727		}
 728		
 729		public AstNode VisitQueryFromClause(CSharp.QueryFromClause queryFromClause, object data)
 730		{
 731			var op = new FromQueryOperator();
 732			op.Variables.Add(
 733				new CollectionRangeVariableDeclaration {
 734					Identifier = new VariableIdentifier { Name = queryFromClause.Identifier },
 735					Type = (AstType)queryFromClause.Type.AcceptVisitor(this, data),
 736					Expression = (Expression)queryFromClause.Expression.AcceptVisitor(this, data)
 737				}
 738			);
 739			
 740			return EndNode(queryFromClause, op);
 741		}
 742		
 743		public AstNode VisitQueryLetClause(CSharp.QueryLetClause queryLetClause, object data)
 744		{
 745			throw new NotImplementedException();
 746		}
 747		
 748		public AstNode VisitQueryWhereClause(CSharp.QueryWhereClause queryWhereClause, object data)
 749		{
 750			throw new NotImplementedException();
 751		}
 752		
 753		public AstNode VisitQueryJoinClause(CSharp.QueryJoinClause queryJoinClause, object data)
 754		{
 755			throw new NotImplementedException();
 756		}
 757		
 758		public AstNode VisitQueryOrderClause(CSharp.QueryOrderClause queryOrderClause, object data)
 759		{
 760			var op = new OrderByQueryOperator();
 761			
 762			ConvertNodes(queryOrderClause.Orderings, op.Expressions);
 763			
 764			return EndNode(queryOrderClause, op);
 765		}
 766		
 767		public AstNode VisitQueryOrdering(CSharp.QueryOrdering queryOrdering, object data)
 768		{
 769			var expr = new OrderExpression();
 770			
 771			expr.Direction = (QueryOrderingDirection)queryOrdering.Direction;
 772			expr.Expression = (Expression)queryOrdering.Expression.AcceptVisitor(this, data);
 773			
 774			return EndNode(queryOrdering, expr);
 775		}
 776		
 777		int selectVarCount = 0;
 778		
 779		public AstNode VisitQuerySelectClause(CSharp.QuerySelectClause querySelectClause, object data)
 780		{
 781			var op = new SelectQueryOperator();
 782			
 783			op.Variables.Add(
 784				new VariableInitializer {
 785					Identifier = new VariableIdentifier { Name = "SelectVar" + selectVarCount },
 786					Expression = (Expression)querySelectClause.Expression.AcceptVisitor(this, data)
 787				});
 788			
 789			return EndNode(querySelectClause, op);
 790		}
 791		
 792		public AstNode VisitQueryGroupClause(CSharp.QueryGroupClause queryGroupClause, object data)
 793		{
 794			var op = new GroupByQueryOperator();
 795			
 796			throw new NotImplementedException();
 797			
 798			//return EndNode(queryGroupClause, op);
 799		}
 800		
 801		public AstNode VisitAttribute(CSharp.Attribute attribute, object data)
 802		{
 803			var attr = new VB.Ast.Attribute();
 804			AttributeTarget target;
 805			Enum.TryParse(((CSharp.AttributeSection)attribute.Parent).AttributeTarget, true, out target);
 806			attr.Target = target;
 807			attr.Type = (AstType)attribute.Type.AcceptVisitor(this, data);
 808			ConvertNodes(attribute.Arguments, attr.Arguments);
 809			
 810			return EndNode(attribute, attr);
 811		}
 812		
 813		public AstNode VisitAttributeSection(CSharp.AttributeSection attributeSection, object data)
 814		{
 815			AttributeBlock block = new AttributeBlock();
 816			ConvertNodes(attributeSection.Attributes, block.Attributes);
 817			return EndNode(attributeSection, block);
 818		}
 819		
 820		public AstNode VisitDelegateDeclaration(CSharp.DelegateDeclaration delegateDeclaration, object data)
 821		{
 822			var result = new DelegateDeclaration();
 823			
 824			ConvertNodes(delegateDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), result.Attributes);
 825			ConvertNodes(delegateDeclaration.ModifierTokens, result.ModifierTokens);
 826			result.Name = new Identifier(delegateDeclaration.Name, TextLocation.Empty);
 827			result.IsSub = IsSub(delegateDeclaration.ReturnType);
 828			ConvertNodes(delegateDeclaration.Parameters, result.Parameters);
 829			ConvertNodes(delegateDeclaration.TypeParameters, result.TypeParameters);
 830			ConvertNodes(delegateDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), result.ReturnTypeAttributes);
 831			if (!result.IsSub)
 832				result.ReturnType = (AstType)delegateDeclaration.ReturnType.AcceptVisitor(this, data);
 833			return EndNode(delegateDeclaration, result);
 834		}
 835		
 836		public AstNode VisitNamespaceDeclaration(CSharp.NamespaceDeclaration namespaceDeclaration, object data)
 837		{
 838			var newNamespace = new NamespaceDeclaration();
 839			
 840			foreach (string id in namespaceDeclaration.Identifiers) {
 841				newNamespace.Identifiers.Add(new Identifier(id, TextLocation.Empty));
 842			}
 843			ConvertNodes(namespaceDeclaration.Members, newNamespace.Members);
 844			
 845			return EndNode(namespaceDeclaration, newNamespace);
 846		}
 847		
 848		public AstNode VisitTypeDeclaration(CSharp.TypeDeclaration typeDeclaration, object data)
 849		{
 850			// TODO add missing features!
 851			
 852			if (typeDeclaration.ClassType == CSharp.ClassType.Enum) {
 853				var type = new EnumDeclaration();
 854				CopyAnnotations(typeDeclaration, type);
 855				
 856				ConvertNodes(typeDeclaration.Attributes, type.Attributes);
 857				ConvertNodes(typeDeclaration.ModifierTokens, type.ModifierTokens);
 858				
 859				if (typeDeclaration.BaseTypes.Any()) {
 860					var first = typeDeclaration.BaseTypes.First();
 861					
 862					type.UnderlyingType = (AstType)first.AcceptVisitor(this, data);
 863				}
 864				
 865				type.Name = new Identifier(typeDeclaration.Name, TextLocation.Empty);
 866				
 867				ConvertNodes(typeDeclaration.Members, type.Members);
 868				
 869				return EndNode(typeDeclaration, type);
 870			} else {
 871				var type = new TypeDeclaration();
 872				CopyAnnotations(typeDeclaration, type);
 873				
 874				CSharp.Attribute stdModAttr;
 875				
 876				if (typeDeclaration.ClassType == CSharp.ClassType.Class && HasAttribute(typeDeclaration.Attributes, "Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute", out stdModAttr)) {
 877					type.ClassType = ClassType.Module;
 878					// remove AttributeSection if only one attribute is present
 879					var attrSec = (CSharp.AttributeSection)stdModAttr.Parent;
 880					if (attrSec.Attributes.Count == 1)
 881						attrSec.Remove();
 882					else
 883						stdModAttr.Remove();
 884				} else {
 885					switch (typeDeclaration.ClassType) {
 886						case CSharp.ClassType.Class:
 887							type.ClassType = ClassType.Class;
 888							break;
 889						case CSharp.ClassType.Struct:
 890							type.ClassType = ClassType.Struct;
 891							break;
 892						case CSharp.ClassType.Interface:
 893							type.ClassType = ClassType.Interface;
 894							break;
 895						default:
 896							throw new InvalidOperationException("Invalid value for ClassType");
 897					}
 898				}
 899				
 900				if ((typeDeclaration.Modifiers & CSharp.Modifiers.Static) == CSharp.Modifiers.Static) {
 901					type.ClassType = ClassType.Module;
 902					typeDeclaration.Modifiers &= ~CSharp.Modifiers.Static;
 903				}
 904				
 905				ConvertNodes(typeDeclaration.Attributes, type.Attributes);
 906				ConvertNodes(typeDeclaration.ModifierTokens, type.ModifierTokens);
 907				
 908				if (typeDeclaration.BaseTypes.Any()) {
 909					var first = typeDeclaration.BaseTypes.First();
 910					
 911					if (provider.GetTypeKindForAstType(first) != TypeKind.Interface) {
 912						ConvertNodes(typeDeclaration.BaseTypes.Skip(1), type.ImplementsTypes);
 913						type.InheritsType = (AstType)first.AcceptVisitor(this, data);
 914					} else
 915						ConvertNodes(typeDeclaration.BaseTypes, type.ImplementsTypes);
 916				}
 917				
 918				type.Name = typeDeclaration.Name;
 919				
 920				types.Push(type);
 921				ConvertNodes(typeDeclaration.Members, type.Members);
 922				types.Pop();
 923				
 924				return EndNode(typeDeclaration, type);
 925			}
 926		}
 927		
 928		public AstNode VisitUsingAliasDeclaration(CSharp.UsingAliasDeclaration usingAliasDeclaration, object data)
 929		{
 930			var imports = new ImportsStatement();
 931			
 932			var clause = new AliasImportsClause() {
 933				Name = new Identifier(usingAliasDeclaration.Alias, TextLocation.Empty),
 934				Alias = (AstType)usingAliasDeclaration.Import.AcceptVisitor(this, data)
 935			};
 936			
 937			imports.AddChild(clause, ImportsStatement.ImportsClauseRole);
 938			
 939			return EndNode(usingAliasDeclaration, imports);
 940		}
 941		
 942		public AstNode VisitUsingDeclaration(CSharp.UsingDeclaration usingDeclaration, object data)
 943		{
 944			var imports = new ImportsStatement();
 945			
 946			var clause = new MemberImportsClause() {
 947				Member = (AstType)usingDeclaration.Import.AcceptVisitor(this, data)
 948			};
 949			
 950			imports.AddChild(clause, ImportsStatement.ImportsClauseRole);
 951			
 952			return EndNode(usingDeclaration, imports);
 953		}
 954		
 955		public AstNode VisitExternAliasDeclaration(CSharp.ExternAliasDeclaration externAliasDeclaration, object data)
 956		{
 957			throw new NotImplementedException();
 958		}
 959		
 960		public AstNode VisitBlockStatement(CSharp.BlockStatement blockStatement, object data)
 961		{
 962			var block = new BlockStatement();
 963			blocks.Push(block);
 964			ConvertNodes(blockStatement, block.Statements);
 965			blocks.Pop();
 966			return EndNode(blockStatement, block);
 967		}
 968		
 969		public AstNode VisitBreakStatement(CSharp.BreakStatement breakStatement, object data)
 970		{
 971			var exit = new ExitStatement(ExitKind.None);
 972			
 973			foreach (var stmt in breakStatement.Ancestors) {
 974				if (stmt is CSharp.MethodDeclaration) {
 975					exit.ExitKind = IsSub(((CSharp.MethodDeclaration)stmt).ReturnType) ? ExitKind.Sub : ExitKind.Function;
 976					break;
 977				}
 978				if (stmt is CSharp.PropertyDeclaration) {
 979					exit.ExitKind = ExitKind.Property;
 980					break;
 981				}
 982				if (stmt is CSharp.DoWhileStatement) {
 983					exit.ExitKind = ExitKind.Do;
 984					break;
 985				}
 986				if (stmt is CSharp.ForStatement || stmt is CSharp.ForeachStatement) {
 987					exit.ExitKind = ExitKind.For;
 988					break;
 989				}
 990				if (stmt is CSharp.WhileStatement) {
 991					exit.ExitKind = ExitKind.While;
 992					break;
 993				}
 994				if (stmt is CSharp.SwitchStatement) {
 995					exit.ExitKind = ExitKind.Select;
 996					break;
 997				}
 998				if (stmt is CSharp.TryCatchStatement) {
 999					exit.ExitKind = ExitKind.Try;
1000					break;
1001				}
1002			}
1003			
1004			return EndNode(breakStatement, exit);
1005		}
1006		
1007		public AstNode VisitCheckedStatement(CSharp.CheckedStatement checkedStatement, object data)
1008		{
1009			blocks.Peek().AddChild(new Comment(" The following expression was wrapped in a checked-statement", false), AstNode.Roles.Comment);
1010			var body = (BlockStatement)checkedStatement.Body.AcceptVisitor(this, data);
1011			
1012			foreach (var stmt in body) {
1013				stmt.Remove();
1014				blocks.Peek().Add(stmt);
1015			}
1016			
1017			return EndNode<AstNode>(checkedStatement, null);
1018		}
1019		
1020		public AstNode VisitContinueStatement(CSharp.ContinueStatement continueStatement, object data)
1021		{
1022			var @continue = new ContinueStatement(ContinueKind.None);
1023			
1024			foreach (var stmt in continueStatement.Ancestors) {
1025				if (stmt is CSharp.DoWhileStatement) {
1026					@continue.ContinueKind = ContinueKind.Do;
1027					break;
1028				}
1029				if (stmt is CSharp.ForStatement || stmt is CSharp.ForeachStatement) {
1030					@continue.ContinueKind = ContinueKind.For;
1031					break;
1032				}
1033				if (stmt is CSharp.WhileStatement) {
1034					@continue.ContinueKind = ContinueKind.While;
1035					break;
1036				}
1037			}
1038			
1039			return EndNode(continueStatement, @continue);
1040		}
1041		
1042		public AstNode VisitDoWhileStatement(CSharp.DoWhileStatement doWhileStatement, object data)
1043		{
1044			var stmt = new DoLoopStatement();
1045			
1046			stmt.ConditionType = ConditionType.LoopWhile;
1047			stmt.Expression = (Expression)doWhileStatement.Condition.AcceptVisitor(this, data);
1048			stmt.Body = (BlockStatement)doWhileStatement.EmbeddedStatement.AcceptVisitor(this, data);
1049			
1050			return EndNode(doWhileStatement, stmt);
1051		}
1052		
1053		public AstNode VisitEmptyStatement(CSharp.EmptyStatement emptyStatement, object data)
1054		{
1055			return EndNode<Statement>(emptyStatement, null);
1056		}
1057		
1058		public AstNode VisitExpressionStatement(CSharp.ExpressionStatement expressionStatement, object data)
1059		{
1060			var node = expressionStatement.Expression.AcceptVisitor(this, data);
1061			if (node is Expression)
1062				node = new ExpressionStatement((Expression)node);
1063			return EndNode(expressionStatement, node);
1064		}
1065		
1066		public AstNode VisitFixedStatement(CSharp.FixedStatement fixedStatement, object data)
1067		{
1068			var block = blocks.Peek();
1069			block.AddChild(new Comment(" Emulating fixed-Statement, might not be entirely correct!", false), AstNode.Roles.Comment);
1070			
1071			var variables = new LocalDeclarationStatement();
1072			variables.Modifiers = Modifiers.Dim;
1073			var stmt = new TryStatement();
1074			stmt.FinallyBlock = new BlockStatement();
1075			foreach (var decl in fixedStatement.Variables) {
1076				var v = new VariableDeclaratorWithTypeAndInitializer {
1077					Identifiers = { new VariableIdentifier { Name = decl.Name } },
1078					Type = new SimpleType("GCHandle"),
1079					Initializer = new InvocationExpression(
1080						new MemberAccessExpression { Target = new IdentifierExpression { Identifier = "GCHandle" }, MemberName = "Alloc" },
1081						(Expression)decl.Initializer.AcceptVisitor(this, data),
1082						new MemberAccessExpression { Target = new IdentifierExpression { Identifier = "GCHandleType" }, MemberName = "Pinned" }
1083					)
1084				};
1085				variables.Variables.Add(v);
1086				stmt.FinallyBlock.Add(new IdentifierExpression { Identifier = decl.Name }.Invoke("Free"));
1087			}
1088			
1089			block.Add(variables);
1090			
1091			stmt.Body = (BlockStatement)fixedStatement.EmbeddedStatement.AcceptVisitor(this, data);
1092			
1093			foreach (var ident in stmt.Body.Descendants.OfType<IdentifierExpression>()) {
1094				ident.ReplaceWith(expr => ((Expression)expr).Invoke("AddrOfPinnedObject"));
1095			}
1096			
1097			return EndNode(fixedStatement, stmt);
1098		}
1099		
1100		public AstNode VisitForeachStatement(CSharp.ForeachStatement foreachStatement, object data)
1101		{
1102			var stmt = new ForEachStatement() {
1103				Body = (BlockStatement)foreachStatement.EmbeddedStatement.AcceptVisitor(this, data),
1104				InExpression = (Expression)foreachStatement.InExpression.AcceptVisitor(this, data),
1105				Variable = new VariableInitializer() {
1106					Identifier = new VariableIdentifier() { Name = foreachStatement.VariableName },
1107					Type = (AstType)foreachStatement.VariableType.AcceptVisitor(this, data)
1108				}
1109			};
1110			
1111			return EndNode(foreachStatement, stmt);
1112		}
1113		
1114		public AstNode VisitForStatement(CSharp.ForStatement forStatement, object data)
1115		{
1116			// for (;;) ;
1117			if (!forStatement.Initializers.Any() && forStatement.Condition.IsNull && !forStatement.Iterators.Any())
1118				return EndNode(forStatement, new WhileStatement() { Condition = new PrimitiveExpression(true), Body = (BlockStatement)forStatement.EmbeddedStatement.AcceptVisitor(this, data) });
1119			
1120			CSharp.AstNode counterLoop = new CSharp.ForStatement() {
1121				Initializers = {
1122					new NamedNode(
1123						"iteratorVar",
1124						new Choice {
1125							new CSharp.VariableDeclarationStatement {
1126								Type = new Choice {
1127									new CSharp.PrimitiveType("long"),
1128									new CSharp.PrimitiveType("ulong"),
1129									new CSharp.PrimitiveType("int"),
1130									new CSharp.PrimitiveType("uint"),
1131									new CSharp.PrimitiveType("short"),
1132									new CSharp.PrimitiveType("ushort"),
1133									new CSharp.PrimitiveType("sbyte"),
1134									new CSharp.PrimitiveType("byte")
1135								},
1136								Variables = {
1137									new AnyNode()
1138								}
1139							},
1140							new CSharp.ExpressionStatement(
1141								new CSharp.AssignmentExpression()
1142							)
1143						})
1144				},
1145				Condition = new NamedNode(
1146					"condition",
1147					new CSharp.BinaryOperatorExpression {
1148						Left = new NamedNode("ident", new CSharp.IdentifierExpression(Pattern.AnyString)),
1149						Operator = CSharp.BinaryOperatorType.Any,
1150						Right = new AnyNode("endExpr")
1151					}),
1152				Iterators = {
1153					new CSharp.ExpressionStatement(
1154						new NamedNode(
1155							"increment",
1156							new CSharp.AssignmentExpression {
1157								Left = new Backreference("ident"),
1158								Operator = CSharp.AssignmentOperatorType.Any,
1159								Right = new NamedNode("factor", new AnyNode())
1160							}
1161						)
1162					)
1163				},
1164				EmbeddedStatement = new NamedNode("body", new AnyNode())
1165			};
1166			
1167			var match = counterLoop.Match(forStatement);
1168			
1169			if (match.Success) {
1170				var init = match.Get<CSharp.Statement>("iteratorVar").SingleOrDefault();
1171				
1172				AstNode iteratorVariable;
1173				
1174				if (init is CSharp.VariableDeclarationStatement) {
1175					var var = ((CSharp.VariableDeclarationStatement)init).Variables.First();
1176					iteratorVariable = new VariableInitializer() {
1177						Identifier = new VariableIdentifier { Name = var.Name },
1178						Type = (AstType)((CSharp.VariableDeclarationStatement)init).Type.AcceptVisitor(this, data),
1179						Expression = (Expression)var.Initializer.AcceptVisitor(this, data)
1180					};
1181				} else if (init is CSharp.ExpressionStatement) {
1182					iteratorVariable = init.AcceptVisitor(this, data);
1183				} else goto end;
1184				
1185				Expression toExpr = Expression.Null;
1186				
1187				var cond = match.Get<CSharp.BinaryOperatorExpression>("condition").SingleOrDefault();
1188				var endExpr = (Expression)match.Get<CSharp.Expression>("endExpr").SingleOrDefault().AcceptVisitor(this, data);
1189				
1190				if (cond.Operator == CSharp.BinaryOperatorType.LessThanOrEqual ||
1191				    cond.Operator == CSharp.BinaryOperatorType.GreaterThanOrEqual) {
1192					toExpr = endExpr;
1193				}
1194				
1195				if (cond.Operator == CSharp.BinaryOperatorType.LessThan)
1196					toExpr = new BinaryOperatorExpression(endExpr, BinaryOperatorType.Subtract, new PrimitiveExpression(1));
1197				if (cond.Operator == CSharp.BinaryOperatorType.GreaterThan)
1198					toExpr = new BinaryOperatorExpression(endExpr, BinaryOperatorType.Add, new PrimitiveExpression(1));
1199				
1200				Expression stepExpr = Expression.Null;
1201				
1202				var increment = match.Get<CSharp.AssignmentExpression>("increment").SingleOrDefault();
1203				var factorExpr = (Expression)match.Get<CSharp.Expression>("factor").SingleOrDefault().AcceptVisitor(this, data);
1204				
1205				if (increment.Operator == CSharp.AssignmentOperatorType.Add && (factorExpr is PrimitiveExpression && !IsEqual(((PrimitiveExpression)factorExpr).Value, 1)))
1206					stepExpr = factorExpr;
1207				if (increment.Operator == CSharp.AssignmentOperatorType.Subtract)
1208					stepExpr = new UnaryOperatorExpression(UnaryOperatorType.Minus, factorExpr);
1209				
1210				return new ForStatement() {
1211					Variable = iteratorVariable,
1212					ToExpression = toExpr,
1213					StepExpression = stepExpr,
1214					Body = (BlockStatement)match.Get<CSharp.Statement>("body").Single().AcceptVisitor(this, data)
1215				};
1216			}
1217			
1218		end:
1219			var stmt = new WhileStatement() {
1220				Condition = (Expression)forStatement.Condition.AcceptVisitor(this, data),
1221				Body = (BlockStatement)forStatement.EmbeddedStatement.AcceptVisitor(this, data)
1222			};
1223			ConvertNodes(forStatement.Iterators, stmt.Body.Statements);
1224			foreach (var initializer in forStatement.Initializers)
1225				blocks.Peek().Statements.Add((Statement)initializer.AcceptVisitor(this, data));
1226			
1227			return EndNode(forStatement, stmt);
1228		}
1229		
1230		bool IsEqual(object value, int num)
1231		{
1232			if (value is byte)
1233				return (byte)value == num;
1234			if (value is sbyte)
1235				return (sbyte)value == num;
1236			if (value is short)
1237				return (short)value == num;
1238			if (value is ushort)
1239				return (ushort)value == num;
1240			if (value is int)
1241				return (int)value == num;
1242			if (value is uint)
1243				return (uint)value == num;
1244			if (value is long)
1245				return (long)value == num;
1246			if (value is ulong)
1247				return (ulong)value == (ulong)num;
1248			
1249			throw new InvalidCastException();
1250		}
1251		
1252		public AstNode VisitGotoCaseStatement(CSharp.GotoCaseStatement gotoCaseStatement, object data)
1253		{
1254			throw new NotImplementedException();
1255		}
1256		
1257		public AstNode VisitGotoDefaultStatement(CSharp.GotoDefaultStatement gotoDefaultStatement, object data)
1258		{
1259			throw new NotImplementedException();
1260		}
1261		
1262		public AstNode VisitGotoStatement(CSharp.GotoStatement gotoStatement, object data)
1263		{
1264			return EndNode(gotoStatement, new GoToStatement() { Label = new IdentifierExpression() { Identifier = gotoStatement.Label } });
1265		}
1266		
1267		public AstNode VisitIfElseStatement(CSharp.IfElseStatement ifElseStatement, object data)
1268		{
1269			var stmt = new IfElseStatement();
1270			
1271			stmt.Condition = (Expression)ifElseStatement.Condition.AcceptVisitor(this, data);
1272			stmt.Body = (Statement)ifElseStatement.TrueStatement.AcceptVisitor(this, data);
1273			stmt.ElseBlock = (Statement)ifElseStatement.FalseStatement.AcceptVisitor(this, data);
1274			
1275			return EndNode(ifElseStatement, stmt);
1276		}
1277		
1278		public AstNode VisitLabelStatement(CSharp.LabelStatement labelStatement, object data)
1279		{
1280			return EndNode(labelStatement, new LabelDeclarationStatement() { Label = new IdentifierExpression() { Identifier = labelStatement.Label } });
1281		}
1282		
1283		public AstNode VisitLockStatement(CSharp.LockStatement lockStatement, object data)
1284		{
1285			var stmt = new SyncLockStatement();
1286			
1287			stmt.Expression = (Expression)lockStatement.Expression.AcceptVisitor(this, data);
1288			stmt.Body = (BlockStatement)lockStatement.EmbeddedStatement.AcceptVisitor(this, data);
1289			
1290			return EndNode(lockStatement, stmt);
1291		}
1292		
1293		public AstNode VisitReturnStatement(CSharp.ReturnStatement returnStatement, object data)
1294		{
1295			var stmt = new ReturnStatement((Expression)returnStatement.Expression.AcceptVisitor(this, data));
1296			
1297			return EndNode(returnStatement, stmt);
1298		}
1299		
1300		public AstNode VisitSwitchStatement(CSharp.SwitchStatement switchStatement, object data)
1301		{
1302			var stmt = new SelectStatement() { Expression = (Expression)switchStatement.Expression.AcceptVisitor(this, data) };
1303			ConvertNodes(switchStatement.SwitchSections, stmt.Cases);
1304			
1305			return EndNode(switchStatement, stmt);
1306		}
1307		
1308		public AstNode VisitSwitchSection(CSharp.SwitchSection switchSection, object data)
1309		{
1310			var caseStmt = new CaseStatement();
1311			ConvertNodes(switchSection.CaseLabels, caseStmt.Clauses

Large files files are truncated, but you can click here to view the full file