[svn] r7184: nemerle/trunk/ncc/codedom/NemerleCodeGenerator.n

akhropov svnadmin at nemerle.org
Mon Jan 1 17:46:55 CET 2007


Log:
adjust to better suit Windows Form Designer and formatting improvements

Author: akhropov
Date: Mon Jan  1 17:46:34 2007
New Revision: 7184

Modified:
   nemerle/trunk/ncc/codedom/NemerleCodeGenerator.n

Modified: nemerle/trunk/ncc/codedom/NemerleCodeGenerator.n
==============================================================================
--- nemerle/trunk/ncc/codedom/NemerleCodeGenerator.n	(original)
+++ nemerle/trunk/ncc/codedom/NemerleCodeGenerator.n	Mon Jan  1 17:46:34 2007
@@ -5,6 +5,8 @@
 //  Atsushi Enomoto <atsushi at ximian.com>
 //  Kamil Skalski <nazgul at nemerle.org>
 //
+//  modified by Andrey Khropov <andrey.khropov at gmail.com>
+//
 // This derived part of the source code is published as public domain.
 //
 // Original: CSharpCodeGenerator.cs
@@ -38,6 +40,7 @@
 using System;
 using System.CodeDom;
 using System.CodeDom.Compiler;
+using System.Globalization;
 using System.IO;
 using System.Reflection;
 using System.Collections;
@@ -46,6 +49,11 @@
 {
   public class NemerleCodeGenerator : CodeGenerator
   {
+    protected enum BracingType
+    {
+      | C | Block | Indent
+    }
+
     mutable dont_write_semicolon : bool = false;
     mutable id : int = 0;
 
@@ -56,6 +64,56 @@
 
     public this () { }
 
+    #region Output-related
+
+    /* AKhropov: The following hacks are needed to be able to call all Generate* methods directly
+                 with your custom Output
+    */
+
+    mutable options : CodeGeneratorOptions = null;
+
+    protected new Options : CodeGeneratorOptions
+    {
+      get { if (options != null) options else base.Options }
+      set { options = value; }
+    }
+
+    protected BracingStyle : BracingType
+    {
+      get { 
+        match (Options.BracingStyle) {
+          | "Block"  => BracingType.Block
+          | "Indent" => BracingType.Indent
+          | "C" | _  => BracingType.C
+        }
+      }
+    }
+
+    mutable output : IndentedTextWriter = null;
+
+    protected new Output : TextWriter
+    {
+      get { if (output != null) output else base.Output }
+      set { 
+        when (Options == null) 
+          options = CodeGeneratorOptions();
+        output = IndentedTextWriter(value,Options.IndentString);
+      }
+    }
+
+    protected new Indent : int
+    {
+      get { if (base.Output != null) base.Indent else output.Indent }
+      set {
+        when (base.Output != null)
+          base.Indent = value;
+        when (output != null)
+          output.Indent = value;
+      }
+    }
+
+    #endregion
+
     protected override NullToken : string
     {
       get { "null" }
@@ -102,6 +160,36 @@
       Output.Write ("base");
     }
     
+    protected mutable inNestedBinary : bool = false;
+
+    protected override GenerateBinaryOperatorExpression (e : CodeBinaryOperatorExpression) : void
+    {
+      def output = Output;
+
+      mutable first = false;
+      output.Write("(");
+      GenerateExpression(e.Left);
+      output.Write(" ");
+      when ((e.Left is CodeBinaryOperatorExpression) || (e.Right is CodeBinaryOperatorExpression)) {
+        when (!inNestedBinary) {
+          first = true;
+          inNestedBinary = true;
+          Indent += 3;
+        }
+        ContinueOnNewLine("");
+      }
+      OutputOperator(e.Operator);
+      output.Write(" ");
+      GenerateExpression(e.Right);
+      output.Write(")");
+
+      when (first)
+      {
+        Indent -= 3;
+        inNestedBinary = false;
+      }
+    }
+    
     protected override GenerateCastExpression (expression : CodeCastExpression) : void
     {
       def output = Output;
@@ -112,7 +200,6 @@
       output.Write( ")" );
     }
 
-
     protected override GenerateCompileUnitStart (_compileUnit : CodeCompileUnit) : void
     {
       GenerateComment( CodeComment( "------------------------------------------------------------------------------" ) );
@@ -124,6 +211,10 @@
       GenerateComment( CodeComment( "     the code is regenerated." ) );
       GenerateComment( CodeComment( " </autogenerated>" ) );
       GenerateComment( CodeComment( "------------------------------------------------------------------------------" ) );
+
+      when (Options.BracingStyle == "Indent")
+        Output.WriteLine("#pragma indent");
+
       Output.WriteLine();
     }
 
@@ -146,6 +237,38 @@
       output.Write( ')' );
     }
 
+    protected override GenerateDirectives (directives : CodeDirectiveCollection) : void
+    {
+      when (directives.Count > 0) {
+        def output = Output;
+
+        output.WriteLine("");
+        foreach (dir in directives)
+        {
+          | dir is CodeRegionDirective =>
+            match(dir.RegionMode)
+            {
+              | Start => output.WriteLine($"#region $(dir.RegionText)")
+              | End   => output.WriteLine("#endregion ")
+              | None  => ()
+            }
+
+          | _ => () // Ignored
+        }
+        output.WriteLine("");
+      }
+    }
+
+    protected override GenerateSingleFloatValue (f : float) : void
+    {
+       Output.Write(f.ToString("R", CultureInfo.InvariantCulture));
+    }
+
+    protected override GenerateDoubleValue (d : double) : void
+    {
+       Output.Write(d.ToString("R", CultureInfo.InvariantCulture));
+    }
+
     protected override GenerateFieldReferenceExpression (expression : CodeFieldReferenceExpression) : void
     {
       def targetObject = expression.TargetObject;
@@ -188,6 +311,7 @@
     
     protected override GenerateSnippetExpression (expression : CodeSnippetExpression) : void
     {
+      // TODO : maybe special handling for some snippets (Nemerle-specific code)
       Output.Write (expression.Value);
     }
     
@@ -277,18 +401,18 @@
       GenerateStatement( statement.IncrementStatement );
       output.Write( ") " );
       dont_write_semicolon = false;
-      output.WriteLine('{');
-      ++Indent;
-      GenerateStatements(statement.Statements);
-      --Indent;
-      output.WriteLine('}');
+
+      GenerateBlock(statement.Statements);
     }
 
         protected new GenerateStatements(c : CodeStatementCollection) : void
         {
           foreach (x is CodeStatement in c) GenerateStatement(x);
           when (c.Count > 0 && (c[c.Count - 1] is CodeVariableDeclarationStatement))
-            Output.WriteLine("();");
+        match (BracingStyle) {
+          | C | Block => Output.WriteLine("();");
+          | Indent    => Output.WriteLine("()");
+        }
         }
 
         protected override GenerateThrowExceptionStatement (statement : CodeThrowExceptionStatement) : void
@@ -345,23 +469,20 @@
 
       GenerateExpression (statement.Condition);
 
-      output.WriteLine( ") {" );
-      ++Indent;
-      GenerateStatements (statement.TrueStatements);
-      --Indent;
+      output.Write( ") " );
+
+      GenerateBlock ( statement.TrueStatements, false );
 
-      when (falses.Count > 0) {
-        output.Write ('}');
+      if (falses.Count > 0) {
         if (this.Options.ElseOnClosing)
           output.Write(' ');
         else
           output.WriteLine ();
-        output.WriteLine ("else {");
-        ++Indent;
-        GenerateStatements (falses);
-        --Indent;
+        output.Write ("else ");
+        GenerateBlock ( falses );
       }
-      output.WriteLine( '}' );
+      else
+        output.WriteLine(); 
     }
 
     protected override GenerateTryCatchFinallyStatement (statement : CodeTryCatchFinallyStatement) : void
@@ -369,14 +490,13 @@
       def output = Output;
       def options = this.Options;
 
-      output.WriteLine ("try {");
-      ++Indent;
-      GenerateStatements (statement.TryStatements);
-      --Indent;
-      output.Write ('}');
+      output.Write ("try ");
+      GenerateBlock (statement.TryStatements);
 
       when (statement.CatchClauses.Count > 0) {
-        output.WriteLine ( " catch {" );
+        output.WriteLine ( " catch " );
+        def bs = BracingStyle;
+        OutputBlockStart (bs);
                 ++Indent;
         foreach (clause is CodeCatchClause in statement.CatchClauses) {
           output.Write ("| ");
@@ -387,22 +507,19 @@
           --Indent;
         }
                 --Indent;
-                output.Write("}");
+        OutputBlockEnd (bs,false);
             }
 
       def finallies = statement.FinallyStatements;
-      when ( finallies.Count > 0 ) {
+      if ( finallies.Count > 0 ) {
         if ( options.ElseOnClosing )
           output.Write( ' ' );
         else
           output.WriteLine();
-        output.WriteLine( "finally {" );
-        ++Indent;
-        GenerateStatements( finallies );
-        --Indent;
-        output.WriteLine( '}' );
+        output.Write( "finally " );
+        GenerateBlock (finallies);
       }
-
+      else
       output.WriteLine();
     }
 
@@ -447,6 +564,21 @@
       throw NotSupportedException ("Labeled statement is not supported in Nemerle language.");
     }
 
+    protected override GenerateSnippetCompileUnit(e : CodeSnippetCompileUnit) : void
+    {
+      GenerateDirectives(e.StartDirectives);
+
+      when (e.LinePragma != null)
+        GenerateLinePragmaStart(e.LinePragma);
+      
+      Output.WriteLine(e.Value); // TODO : maybe special handling for some snippets (Nemerle-specific code)
+
+      when (e.LinePragma != null)
+        GenerateLinePragmaEnd(e.LinePragma);
+
+      GenerateDirectives(e.EndDirectives);
+    }
+
     protected override GenerateVariableDeclarationStatement (statement : CodeVariableDeclarationStatement) : void
     {
       def output = Output;
@@ -557,7 +689,8 @@
       }
     }
 
-    private OutputTypeAttributes (declaration : CodeTypeDeclaration) : void
+    // TODO: different signature from parent
+    protected new OutputTypeAttributes (declaration : CodeTypeDeclaration) : void
     {
         def output = Output;
         def attributes = declaration.TypeAttributes;
@@ -609,9 +742,16 @@
 
     protected override GenerateSnippetMember (member : CodeSnippetTypeMember) : void
     {
+      // TODO : maybe special handling for some snippets (Nemerle-specific code)
       Output.Write (member.Text);
     }
     
+    protected override GenerateSnippetStatement (_ : CodeSnippetStatement) : void
+    {
+      // TODO : maybe special handling for some snippets (Nemerle-specific code)
+      throw NotSupportedException ("Snippet Statements are not supported in Nemerle language.");
+    }
+    
     protected override GenerateEntryPointMethod (method : CodeEntryPointMethod, declaration : CodeTypeDeclaration) : void
     {
       method.Name = "Main";
@@ -657,7 +797,7 @@
       OutputType (method.ReturnType);
 
       if ( (attributes %& MemberAttributes.ScopeMask) == MemberAttributes.Abstract 
-           || declaration.IsInterface)
+           || declaration.IsInterface )
         output.WriteLine ( ';' );
       else {
                 when (privateType != null)
@@ -668,11 +808,7 @@
               output.Write (GetSafeName (method.Name));
                 }
 
-                output.WriteLine ( " {" );
-        ++Indent;
-        GenerateStatements (method.Statements);
-        --Indent;
-        output.WriteLine ( '}' );
+        GenerateBlock (method.Statements);
       }
     }
 
@@ -703,7 +839,9 @@
       {
                      OutputTypeNamePair( property.Type, GetSafeName (property.Name));
       }
-      output.WriteLine (" {");
+
+      def bs = BracingStyle;
+      OutputBlockStart (bs);
       ++Indent;
 
       if (declaration.IsInterface)
@@ -715,29 +853,19 @@
       {
         when (property.HasGet)
         {
-          output.WriteLine ("get {");
-          ++Indent;
-
-          GenerateStatements (property.GetStatements);
-
-          --Indent;
-          output.WriteLine ("}");
+          output.Write ("get ");
+          GenerateBlock (property.GetStatements);
         }
 
        when (property.HasSet)
         {
-          output.WriteLine ("set {");
-          ++Indent;
-
-          GenerateStatements (property.SetStatements);
-
-          --Indent;
-          output.WriteLine ("}");
+          output.Write ("set ");
+          GenerateBlock (property.SetStatements);
         }
       }
 
       --Indent;
-      output.WriteLine ("}");
+      OutputBlockEnd (bs);
     }
 
     protected override GenerateConstructor(constructor : CodeConstructor, _declaration : CodeTypeDeclaration) : void
@@ -749,7 +877,9 @@
       Output.Write ("this (");
       OutputParameters (constructor.Parameters);
       Output.Write (") ");
-      Output.WriteLine ("{");
+
+      def bs = BracingStyle;
+      OutputBlockStart (bs);
       ++Indent;
       when (constructor.ChainedConstructorArgs.Count > 0)
       {
@@ -781,16 +911,27 @@
       };
       GenerateStatements (constructor.Statements);
       --Indent;
-      Output.WriteLine ('}');
+      OutputBlockEnd (bs);
     }
     
     protected override GenerateTypeConstructor (constructor : CodeTypeConstructor) : void
     {
-      Output.WriteLine ("static this () {");
-      ++Indent;
-      GenerateStatements (constructor.Statements);
-      --Indent;
-      Output.WriteLine ('}');
+      Output.Write ("static this () ");
+      GenerateBlock (constructor.Statements);
+    }
+
+    protected new GenerateTypes (e : CodeNamespace) : void
+    {
+      def output = Output;
+      def options = Options;
+
+      foreach (typeDecl is CodeTypeDeclaration in e.Types)
+      {
+        when (options.BlankLinesBetweenMembers)
+          output.WriteLine();
+     
+        (this:ICodeGenerator).GenerateCodeFromType(typeDecl, (output :> IndentedTextWriter).InnerWriter, options);
+      }
     }
 
     protected override GenerateTypeStart (declaration : CodeTypeDeclaration) : void
@@ -825,7 +966,7 @@
       if (declaration is CodeTypeDelegate)
         output.Write ( "(" );
       else
-        output.WriteLine ( "{" );
+        OutputBlockStart (BracingStyle);
       ++Indent;
     }
 
@@ -842,7 +983,17 @@
         Output.WriteLine (";");
       }
       else
-        Output.WriteLine ("}");
+        OutputBlockEnd (BracingStyle);
+    }
+
+    protected override GenerateNamespace (ns : CodeNamespace) : void
+    {
+      GenerateCommentStatements(ns.Comments);
+      GenerateNamespaceStart(ns);
+      GenerateNamespaceImports(ns);
+      Output.WriteLine("");
+      GenerateTypes(ns);
+      GenerateNamespaceEnd(ns);
     }
 
     protected override GenerateNamespaceStart (ns : CodeNamespace) : void
@@ -853,7 +1004,7 @@
       when ( name != null && name != "" ) {
         output.Write( "namespace " );
         output.Write( GetSafeName (name) );
-        output.WriteLine( " {" );
+        OutputBlockStart (BracingStyle);
         ++Indent;
       }
     }
@@ -863,7 +1014,7 @@
       def name = ns.Name;
       when ( name != null && name != "" ) {
         --Indent;
-        Output.WriteLine( "}" );
+        OutputBlockEnd (BracingStyle);
       }
     }
 
@@ -912,6 +1063,134 @@
       Output.Write (GetTypeOutput (ty));
     }
 
+    protected override OutputAttributeArgument (arg : CodeAttributeArgument) : void
+    {
+      def output = Output;
+      when ((arg.Name != null) && (arg.Name.Length > 0))
+      {
+        OutputIdentifier(arg.Name);
+        output.Write("=");
+      }
+      (this:ICodeGenerator).GenerateCodeFromExpression(arg.Value, (output :> IndentedTextWriter).InnerWriter, Options);
+    }
+
+    protected override OutputAttributeDeclarations (attributes : CodeAttributeDeclarationCollection) : void
+    {
+      when (attributes.Count != 0)
+      {
+        def output = Output;
+        GenerateAttributeDeclarationsStart (attributes);
+
+        mutable first1 = true;
+        foreach (attrDecl is CodeAttributeDeclaration in attributes)
+        {
+          if (first1)
+            first1 = false;
+          else
+            output.Write (", ");
+
+          output.Write (attrDecl.Name);
+          when (attrDecl.Arguments.Count != 0)
+          {
+            output.Write ("(");
+            mutable first2 = true;
+            foreach (attrArg is CodeAttributeArgument in attrDecl.Arguments)
+            {
+              if (first2)
+                first2 = false;
+              else
+                output.Write(", ");
+              OutputAttributeArgument (attrArg);
+            }
+            output.Write(")");
+          }
+        }
+        GenerateAttributeDeclarationsEnd (attributes);
+      }
+    }
+  
+    protected override OutputMemberAccessModifier (attributes : MemberAttributes) : void
+    {
+      def output = Output;
+      def accessMask = attributes %& MemberAttributes.AccessMask;
+      
+      match (accessMask)
+      {
+        | MemberAttributes.Public => 
+          output.Write("public ");
+
+        | MemberAttributes.Private => 
+          output.Write("private ");
+
+        | MemberAttributes.Family => 
+          output.Write("protected ");
+
+        | MemberAttributes.Assembly => 
+          output.Write("internal ");
+
+        | MemberAttributes.FamilyOrAssembly => 
+          output.Write("protected internal ");
+
+        | _ =>
+          throw NotSupportedException("Unsupported access attribute");
+      }
+    }
+
+    protected override OutputMemberScopeModifier(attributes : MemberAttributes) : void
+    {
+      def output = Output;
+
+      when (attributes %&& MemberAttributes.New)
+        output.Write("new ");
+      
+      match (attributes %& MemberAttributes.ScopeMask)
+      {
+        | MemberAttributes.Abstract => 
+          output.Write("abstract ");
+
+        | MemberAttributes.Final => 
+          output.Write("sealed ");
+
+        | MemberAttributes.Static => // TODO: is static mutually exclusive with other flags?
+          output.Write("static ");
+
+        | MemberAttributes.Override => 
+          output.Write("override ");
+
+        | _ => ()
+      }
+    }
+
+    protected override OutputIdentifier (ident : string) : void
+    {
+      Output.Write(ident);
+    }
+
+    protected override OutputParameters (parameters : CodeParameterDeclarationExpressionCollection) : void
+    {
+      mutable first = true;
+      def isManyParams = parameters.Count > 15; // TODO: maybe this should be regulated by settings
+
+      when (isManyParams)
+        Indent += 3;
+
+      foreach (e is CodeParameterDeclarationExpression in parameters)
+      {
+        if (first)
+          first = false;
+        else
+          Output.Write(", ");
+
+        when (isManyParams)
+          ContinueOnNewLine("");
+
+        GenerateExpression(e);
+      }
+
+      when (isManyParams)
+        Indent -= 3;
+    }
+
     protected override QuoteSnippetString (value : string) : string
     {
       // FIXME: this is weird, but works.
@@ -934,6 +1213,36 @@
       OutputType (e.Type);
     }
 
+    protected override GeneratePrimitiveExpression (e : CodePrimitiveExpression) : void
+    {
+      match (e.Value)
+      {
+        | null => Output.Write(NullToken);
+        | v is string =>
+          Output.Write(QuoteSnippetString(v));
+        | v is char =>
+          Output.Write("'" + v.ToString() + "'");
+        | v is byte =>
+          Output.Write(v.ToString(CultureInfo.InvariantCulture));
+        | v is short =>
+          Output.Write(v.ToString(CultureInfo.InvariantCulture));
+        | v is int =>
+          Output.Write(v.ToString(CultureInfo.InvariantCulture));
+        | v is long =>
+          Output.Write(v.ToString(CultureInfo.InvariantCulture));
+        | v is float =>
+          GenerateSingleFloatValue(v);
+        | v is double =>
+          GenerateDoubleValue(v);
+        | v is decimal =>
+          GenerateDecimalValue(v);
+        | v is bool =>
+          Output.Write( if(v) "true" else "false" ); 
+        | v => 
+          throw ArgumentException($"InvalidPrimitiveType: $(v.GetType().ToString())");
+      }
+    }
+
     protected override GenerateTypeOfExpression (e : CodeTypeOfExpression) : void
     {
       Output.Write ("typeof(");
@@ -941,16 +1250,85 @@
       Output.Write (")");
     }
 
+    protected GenerateBlock (statements : CodeStatementCollection, endLastLine : bool = true) : void
+    {
+      def bs = BracingStyle;
+      OutputBlockStart (bs);
+
+      ++Indent;
+      GenerateStatements (statements);
+      --Indent;
+
+      OutputBlockEnd (bs, endLastLine);
+    }
+
+    protected OutputBlockStart (bs : BracingType) : void
+    {
+      | C      => Output.WriteLine('{');
+      | Block  => { Output.WriteLine(); Output.WriteLine('{'); }
+      | Indent => ()
+    }
+
+    protected OutputBlockEnd (bs : BracingType, endLastLine : bool = true) : void
+    {
+      match (bs) {
+        | C      => if (endLastLine) Output.WriteLine('}') else Output.Write('}');
+        | Block  => Output.WriteLine('}');
+        | Indent => () //Output.WriteLine(); //TODO
+      }
+    }
+
     protected override OutputOperator (op : CodeBinaryOperatorType) : void
     {
-      | CodeBinaryOperatorType.BitwiseAnd =>
-        Output.Write(" & ");
+      | Add                => Output.Write("+");
+      | Subtract           => Output.Write("-");
+      | Multiply           => Output.Write("*");
+      | Divide             => Output.Write("/");
+      | Modulus            => Output.Write("%");
+      | Assign             => Output.Write("=");
+      | IdentityInequality => Output.Write("!=");
+      | IdentityEquality   => Output.Write("==");
+      | ValueEquality      => Output.Write("==");
+      | BitwiseOr          => Output.Write("|");
+      | BitwiseAnd         => Output.Write("&");
+      | BooleanOr          => Output.Write("||");
+      | BooleanAnd         => Output.Write("&&");
+      | LessThan           => Output.Write("<");
+      | LessThanOrEqual    => Output.Write("<=");
+      | GreaterThan        => Output.Write(">");
+      | GreaterThanOrEqual => Output.Write(">=");
+    }
+
+    protected override OutputExpressionList (expressions : CodeExpressionCollection, newlineBetweenItems : bool) : void
+    {
+      def output = Output;
+      def options = Options;
               
-      | CodeBinaryOperatorType.BitwiseOr =>
-        Output.Write(" | ");
+      mutable first = true;
+      Indent++;
+      foreach (e is CodeExpression in expressions)
+      {
+        if (first)
+          first = false;
+        else if (newlineBetweenItems)
+          ContinueOnNewLine(",");
+        else
+          output.Write(", ");
+        (this:ICodeGenerator).GenerateCodeFromExpression(e, (output :> IndentedTextWriter).InnerWriter, options);
+      }
+      Indent--;
+    }
                 
-      | _ =>
-        base.OutputOperator(op);
+    protected override OutputDirection (dir : FieldDirection) : void
+    {
+      | In  => ()
+      | Out => Output.Write("out ");
+      | Ref => Output.Write("ref ");
+    }
+
+    protected override ContinueOnNewLine(st : string) : void
+    {
+      Output.WriteLine(st);
     }
 
     /* 



More information about the svn mailing list