/NObjectiveAST/RegenAST.cs

http://nobjective.googlecode.com/ · C# · 199 lines · 153 code · 40 blank · 6 comment · 33 complexity · 5e469e973d5770d1989a979a0b247166 MD5 · raw file

  1. //
  2. // Copyright (C) 2008 Eugeny Grishul
  3. //
  4. // See license in License.txt
  5. //
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Diagnostics;
  11. using ICSharpCode.NRefactory.Ast;
  12. using System.Reflection;
  13. using ICSharpCode.NRefactory.PrettyPrinter;
  14. using System.IO;
  15. namespace NObjectiveASTRegen
  16. {
  17. internal static class RegenAST
  18. {
  19. [STAThread]
  20. private static void Main( string[] args )
  21. {
  22. var compilationUnit = new CompilationUnit();
  23. var @namespace = new NamespaceDeclaration( "NObjectiveAST" );
  24. compilationUnit.Children.Add( @namespace );
  25. var visitorsInterface = new TypeDeclaration( Modifiers.Public | Modifiers.Partial, null );
  26. visitorsInterface.Type = ClassType.Interface;
  27. visitorsInterface.Name = "IAstVisitor";
  28. var traversalVisitor = new TypeDeclaration( Modifiers.Public | Modifiers.Partial, null );
  29. traversalVisitor.Type = ClassType.Class;
  30. traversalVisitor.Name = "TraversalVisitor";
  31. traversalVisitor.BaseTypes = new List<TypeReference> { new TypeReference( visitorsInterface.Name ) };
  32. @namespace.Children.Add( visitorsInterface );
  33. @namespace.Children.Add( traversalVisitor );
  34. {
  35. var visitNode = new MethodDeclaration();
  36. visitNode.Modifier = Modifiers.Public;
  37. visitNode.Name = "Visit";
  38. visitNode.Parameters.Add( new ParameterDeclarationExpression( new TypeReference( "Node" ), "node" ) );
  39. visitNode.TypeReference = new TypeReference( "object" );
  40. visitNode.Body = new BlockStatement();
  41. visitNode.Body.Children.Add( new ReturnStatement( new InvocationExpression( new MemberReferenceExpression( new IdentifierExpression( "node" ), "AcceptVisitor" ), new List<Expression> { new ThisReferenceExpression() } ) ) );
  42. traversalVisitor.Children.Add( visitNode );
  43. }
  44. foreach( var nodeType in Assembly.GetExecutingAssembly().GetTypes().Where( x => !x.IsAbstract && x.GetClassHierarchy().Contains( typeof( NObjectiveAST.Node ) ) ).OrderBy( x => x.Name ) )
  45. {
  46. var visitMethod = new MethodDeclaration();
  47. visitMethod.Name = "Visit";
  48. visitMethod.Parameters.Add( new ParameterDeclarationExpression( new TypeReference( nodeType.Name ), "node" ) );
  49. visitMethod.TypeReference = new TypeReference( "object" );
  50. visitorsInterface.Children.Add( visitMethod );
  51. visitMethod = new MethodDeclaration();
  52. visitMethod.Body = new BlockStatement();
  53. visitMethod.Modifier = Modifiers.Public | Modifiers.Virtual;
  54. visitMethod.Name = "Visit";
  55. visitMethod.Parameters.Add( new ParameterDeclarationExpression( new TypeReference( nodeType.Name ), "node" ) );
  56. visitMethod.TypeReference = new TypeReference( "object" );
  57. foreach( var astField in nodeType.GetFields( BindingFlags.Instance | BindingFlags.NonPublic ).Where( x => x.FieldType.GetClassHierarchy().Contains( typeof( NObjectiveAST.Node ) ) ).Where( x => x.Name != "Parent" ).OrderBy( x => x.Name ) )
  58. {
  59. var block = new BlockStatement();
  60. block.AddChild( new ExpressionStatement( new InvocationExpression( new IdentifierExpression( "BeginVisit" ), new List<Expression> { new PrimitiveExpression( GetPropertyName( astField.Name ), GetPropertyName( astField.Name ) ), new MemberReferenceExpression( new IdentifierExpression( "node" ), GetPropertyName( astField.Name ) ) } ) ) );
  61. block.AddChild( new ExpressionStatement( new InvocationExpression( new MemberReferenceExpression( new MemberReferenceExpression( new IdentifierExpression( "node" ), GetPropertyName( astField.Name ) ), "AcceptVisitor" ), new List<Expression> { new ThisReferenceExpression() } ) ) );
  62. block.AddChild( new ExpressionStatement( new InvocationExpression( new IdentifierExpression( "EndVisit" ), new List<Expression> { new PrimitiveExpression( GetPropertyName( astField.Name ), GetPropertyName( astField.Name ) ), new MemberReferenceExpression( new IdentifierExpression( "node" ), GetPropertyName( astField.Name ) ) } ) ) );
  63. visitMethod.Body.AddChild( new IfElseStatement( new BinaryOperatorExpression( new MemberReferenceExpression( new IdentifierExpression( "node" ), GetPropertyName( astField.Name ) ), BinaryOperatorType.InEquality, new PrimitiveExpression( null, "null" ) ), block ) );
  64. }
  65. foreach( var astField in nodeType.GetFields( BindingFlags.Instance | BindingFlags.NonPublic ).Where( x => x.FieldType.IsGenericType && x.FieldType.GetGenericTypeDefinition() == typeof( List<> ) && x.FieldType.GetGenericArguments()[0].GetClassHierarchy().Contains( typeof( NObjectiveAST.Node ) ) ).OrderBy( x => x.Name ) )
  66. {
  67. var block = new BlockStatement();
  68. var foreachBlock = new BlockStatement();
  69. foreachBlock.AddChild( new ExpressionStatement( new InvocationExpression( new IdentifierExpression( "BeginVisit" ), new List<Expression> { new PrimitiveExpression( GetPropertyName( astField.Name ), GetPropertyName( astField.Name ) ), new IdentifierExpression( "item" ) } ) ) );
  70. foreachBlock.AddChild( new ExpressionStatement( new InvocationExpression( new MemberReferenceExpression( new IdentifierExpression( "item" ), "AcceptVisitor" ), new List<Expression> { new ThisReferenceExpression() } ) ) );
  71. foreachBlock.AddChild( new ExpressionStatement( new InvocationExpression( new IdentifierExpression( "EndVisit" ), new List<Expression> { new PrimitiveExpression( GetPropertyName( astField.Name ), GetPropertyName( astField.Name ) ), new IdentifierExpression( "item" ) } ) ) );
  72. block.AddChild( new ExpressionStatement( new InvocationExpression( new IdentifierExpression( "BeginVisitChildren" ), new List<Expression> { new PrimitiveExpression( GetPropertyName( astField.Name ), GetPropertyName( astField.Name ) ), new MemberReferenceExpression( new IdentifierExpression( "node" ), GetPropertyName( astField.Name ) ) } ) ) );
  73. block.AddChild( new ForeachStatement( new TypeReference( "var" ), "item", new MemberReferenceExpression( new IdentifierExpression( "node" ), GetPropertyName( astField.Name ) ), foreachBlock ) );
  74. block.AddChild( new ExpressionStatement( new InvocationExpression( new IdentifierExpression( "EndVisitChildren" ), new List<Expression> { new PrimitiveExpression( GetPropertyName( astField.Name ), GetPropertyName( astField.Name ) ), new MemberReferenceExpression( new IdentifierExpression( "node" ), GetPropertyName( astField.Name ) ) } ) ) );
  75. visitMethod.Body.AddChild( new IfElseStatement( new BinaryOperatorExpression( new MemberReferenceExpression( new IdentifierExpression( "node" ), GetPropertyName( astField.Name ) ), BinaryOperatorType.InEquality, new PrimitiveExpression( null, "null" ) ), block ) );
  76. }
  77. visitMethod.Body.Children.Add( new ReturnStatement( new PrimitiveExpression( null, "null" ) ) );
  78. traversalVisitor.Children.Add( visitMethod );
  79. var astNodeExtension = new TypeDeclaration( Modifiers.Public, null );
  80. astNodeExtension.Type = ClassType.Class;
  81. astNodeExtension.Modifier |= Modifiers.Partial;
  82. astNodeExtension.Name = nodeType.Name;
  83. var acceptVisitor = new MethodDeclaration();
  84. acceptVisitor.Modifier = Modifiers.Public | Modifiers.Override;
  85. acceptVisitor.Name = "AcceptVisitor";
  86. acceptVisitor.Attributes.Add( new AttributeSection { Attributes = new List<ICSharpCode.NRefactory.Ast.Attribute> { new ICSharpCode.NRefactory.Ast.Attribute( typeof( DebuggerStepThroughAttribute ).Name, null, null ) } } );
  87. acceptVisitor.Parameters.Add( new ParameterDeclarationExpression( new TypeReference( "IAstVisitor" ), "visitor" ) );
  88. acceptVisitor.TypeReference = new TypeReference( "object" );
  89. acceptVisitor.Body = new BlockStatement();
  90. acceptVisitor.Body.Children.Add( new ReturnStatement( new InvocationExpression( new MemberReferenceExpression( new IdentifierExpression( "visitor" ), "Visit" ), new List<Expression> { new ThisReferenceExpression() } ) ) );
  91. foreach( var item in nodeType.GetFields( BindingFlags.Instance | BindingFlags.NonPublic ).Where( x => x.Name.StartsWith( "_" ) ) )
  92. {
  93. var getBlock = new BlockStatement();
  94. var setBlock = new BlockStatement();
  95. getBlock.AddChild( new ReturnStatement( new IdentifierExpression( item.Name ) ) );
  96. Expression assignment = new IdentifierExpression( "value" );
  97. if( item.FieldType.GetClassHierarchy().Contains( typeof( NObjectiveAST.Node ) ) || ( item.FieldType.IsGenericType && item.FieldType.GetGenericTypeDefinition() == typeof( List<> ) && item.FieldType.GetGenericArguments()[0].GetClassHierarchy().Contains( typeof( NObjectiveAST.Node ) ) ) )
  98. assignment = new InvocationExpression( new IdentifierExpression( "SetParent" ), new List<Expression> { assignment } );
  99. setBlock.AddChild( new ExpressionStatement( new AssignmentExpression( new IdentifierExpression( item.Name ), AssignmentOperatorType.Assign, assignment ) ) );
  100. List<AttributeSection> attributes = null;
  101. if( item.FieldType.IsEnum || item.FieldType == typeof( string ) || item.FieldType == typeof( int ) || item.FieldType == typeof( uint ) || item.FieldType == typeof( long ) || item.FieldType == typeof( ulong ) || item.FieldType == typeof( short ) || item.FieldType == typeof( ushort ) || item.FieldType == typeof( byte ) || item.FieldType == typeof( sbyte ) || item.FieldType == typeof( bool ) )
  102. {
  103. attributes = new List<AttributeSection>();
  104. attributes.Add( new AttributeSection { Attributes = new List<ICSharpCode.NRefactory.Ast.Attribute> { new ICSharpCode.NRefactory.Ast.Attribute() { Name = "XmlAttribute" } } } );
  105. }
  106. var property = new PropertyDeclaration( Modifiers.Public, attributes, GetPropertyName( item.Name ), null );
  107. property.TypeReference = GetTypeReference( item.FieldType );
  108. property.GetRegion = new PropertyGetRegion( getBlock, null );
  109. property.SetRegion = new PropertySetRegion( setBlock, null );
  110. astNodeExtension.AddChild( property );
  111. }
  112. astNodeExtension.Children.Add( acceptVisitor );
  113. @namespace.Children.Add( astNodeExtension );
  114. }
  115. var outputVisitor = new CSharpOutputVisitor();
  116. outputVisitor.VisitCompilationUnit( compilationUnit, null );
  117. //using( var writer )
  118. File.WriteAllText( @"..\..\Visitors.Generated.cs", NObjectiveAST.Properties.Resources.FileHeader + outputVisitor.Text );
  119. }
  120. private static string GetPropertyName( string name )
  121. {
  122. return char.ToUpper( name[1] ) + name.Substring( 2 );
  123. }
  124. private static TypeReference GetTypeReference( Type type )
  125. {
  126. var result = new TypeReference( "" );
  127. if( type.IsGenericType )
  128. {
  129. result.Type = type.GetGenericTypeDefinition().Name.Split( '`' )[0];
  130. foreach( var genericArgument in type.GetGenericArguments() )
  131. {
  132. result.GenericTypes.Add( GetTypeReference( genericArgument ) );
  133. }
  134. }
  135. else
  136. result.Type = type.Name;
  137. return result;
  138. }
  139. internal static IEnumerable<Type> GetClassHierarchy( this Type type )
  140. {
  141. var result = type;
  142. while( result != null )
  143. {
  144. yield return result;
  145. result = result.BaseType;
  146. }
  147. }
  148. }
  149. }
  150. namespace NObjectiveAST
  151. {
  152. public class OutputVisitor
  153. {
  154. public static string GetNodeText( NObjectiveAST.Node node )
  155. {
  156. return "";
  157. }
  158. }
  159. }