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