[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