The Labs \ Source Viewer \ SSCLI \ Microsoft.JScript \ JSCodeGenerator

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace Microsoft.JScript
  16. {
  17.    
  18.     using System.Diagnostics;
  19.     using System;
  20.     using System.IO;
  21.     using System.Collections;
  22.     using System.Reflection;
  23.     using System.CodeDom;
  24.     using System.CodeDom.Compiler;
  25.     using System.Globalization;
  26.     using System.Security;
  27.     using System.Security.Permissions;
  28.     using System.Text;
  29.     using System.Text.RegularExpressions;
  30.     using Microsoft.JScript.Vsa;
  31.    
  32.     [System.ComponentModel.DesignerCategory("code")]
  33.     [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
  34.     public sealed class JScriptCodeProvider : CodeDomProvider
  35.     {
  36.         private JSCodeGenerator generator;
  37.        
  38.         public JScriptCodeProvider()
  39.         {
  40.             generator = new JSCodeGenerator();
  41.         }
  42.        
  43.         public override ICodeGenerator CreateGenerator()
  44.         {
  45.             return (ICodeGenerator)generator;
  46.         }
  47.        
  48.         public override ICodeCompiler CreateCompiler()
  49.         {
  50.             return (ICodeCompiler)generator;
  51.         }
  52.        
  53.         public override string FileExtension {
  54.             get { return "js"; }
  55.         }
  56.     }
  57.    
  58.     // JScript (ECMAScript) Code Generator.
  59.     // [stesty] - This class used to be dependent on CSCodeGenerator but that dependency was removed
  60.     // when the source got moved over to the VSA tree. Since we are still dependent on
  61.     // CodeCompiler, \\urtdist\builds\SRC\XXXX\DNA\CompMod\System\CodeDOM\Compiler\CodeCompiler.cs
  62.     // should be consulted when fixing new bugs here.
  63.     //
  64.     [System.ComponentModel.DesignerCategory("code")]
  65.     internal sealed class JSCodeGenerator : CodeCompiler
  66.     {
  67.         private const int MaxLineLength = 80;
  68.        
  69.         private const GeneratorSupport LanguageSupport = GeneratorSupport.ArraysOfArrays | GeneratorSupport.AssemblyAttributes | GeneratorSupport.EntryPointMethod | GeneratorSupport.MultidimensionalArrays | GeneratorSupport.StaticConstructors | GeneratorSupport.PublicStaticMembers | GeneratorSupport.DeclareEnums | GeneratorSupport.DeclareInterfaces | GeneratorSupport.TryCatchStatements;
  70.        
  71.         private bool forLoopHack = false;
  72.         private bool isArgumentList = true;
  73.        
  74.         private static Hashtable keywords;
  75.        
  76.         static JSCodeGenerator()
  77.         {
  78.             // build the keywords hashtable
  79.             keywords = new Hashtable(150);
  80.             object obj = new object();
  81.             // a
  82.             keywords["abstract"] = obj;
  83.             keywords["assert"] = obj;
  84.             // b
  85.             keywords["boolean"] = obj;
  86.             keywords["break"] = obj;
  87.             keywords["byte"] = obj;
  88.             // c
  89.             keywords["case"] = obj;
  90.             keywords["catch"] = obj;
  91.             keywords["char"] = obj;
  92.             keywords["class"] = obj;
  93.             keywords["const"] = obj;
  94.             keywords["continue"] = obj;
  95.             // d
  96.             keywords["debugger"] = obj;
  97.             keywords["decimal"] = obj;
  98.             keywords["default"] = obj;
  99.             keywords["delete"] = obj;
  100.             keywords["do"] = obj;
  101.             keywords["double"] = obj;
  102.             // e
  103.             keywords["else"] = obj;
  104.             keywords["ensure"] = obj;
  105.             keywords["enum"] = obj;
  106.             keywords["event"] = obj;
  107.             keywords["export"] = obj;
  108.             keywords["extends"] = obj;
  109.             // f
  110.             keywords["false"] = obj;
  111.             keywords["final"] = obj;
  112.             keywords["finally"] = obj;
  113.             keywords["float"] = obj;
  114.             keywords["for"] = obj;
  115.             keywords["function"] = obj;
  116.             // g
  117.             keywords["get"] = obj;
  118.             keywords["goto"] = obj;
  119.             // i
  120.             keywords["if"] = obj;
  121.             keywords["implements"] = obj;
  122.             keywords["import"] = obj;
  123.             keywords["in"] = obj;
  124.             keywords["instanceof"] = obj;
  125.             keywords["int"] = obj;
  126.             keywords["invariant"] = obj;
  127.             keywords["interface"] = obj;
  128.             keywords["internal"] = obj;
  129.             // l
  130.             keywords["long"] = obj;
  131.             // n
  132.             keywords["namespace"] = obj;
  133.             keywords["native"] = obj;
  134.             keywords["new"] = obj;
  135.             keywords["null"] = obj;
  136.             // p
  137.             keywords["package"] = obj;
  138.             keywords["private"] = obj;
  139.             keywords["protected"] = obj;
  140.             keywords["public"] = obj;
  141.             // r
  142.             keywords["require"] = obj;
  143.             keywords["return"] = obj;
  144.             // s
  145.             keywords["sbyte"] = obj;
  146.             keywords["scope"] = obj;
  147.             keywords["set"] = obj;
  148.             keywords["short"] = obj;
  149.             keywords["static"] = obj;
  150.             keywords["super"] = obj;
  151.             keywords["switch"] = obj;
  152.             keywords["synchronized"] = obj;
  153.             // t
  154.             keywords["this"] = obj;
  155.             keywords["throw"] = obj;
  156.             keywords["throws"] = obj;
  157.             keywords["transient"] = obj;
  158.             keywords["true"] = obj;
  159.             keywords["try"] = obj;
  160.             keywords["typeof"] = obj;
  161.             // u
  162.             keywords["use"] = obj;
  163.             keywords["uint"] = obj;
  164.             keywords["ulong"] = obj;
  165.             keywords["ushort"] = obj;
  166.             // v
  167.             keywords["var"] = obj;
  168.             keywords["void"] = obj;
  169.             keywords["volatile"] = obj;
  170.             // w
  171.             keywords["while"] = obj;
  172.             keywords["with"] = obj;
  173.         }
  174.        
  175.         private string mainClassName = null;
  176.         private string mainMethodName = null;
  177.         private static Regex outputReg = new Regex("(([^(]+)(\\(([0-9]+),([0-9]+)\\))[ \\t]*:[ \\t]+)?(fatal )?(error|warning)[ \\t]+([A-Z]+[0-9]+)[ \\t]*:[ \\t]*(.*)");
  178.        
  179.         protected override string CmdArgsFromParameters(CompilerParameters options)
  180.         {
  181.             StringBuilder sb = new StringBuilder(128);
  182.             // Do not output the target type here because it can only appear once on the command line and we
  183.             // would like the user to be able to specify a target type in CompilerParameters.CompilerOptions.
  184.            
  185.             // if '/' separates dir, use '-' as switch
  186.             string cmdLineSwitch = Path.DirectorySeparatorChar == '/' ? "-" : "/";
  187.            
  188.             sb.Append(cmdLineSwitch + "utf8output ");
  189.            
  190.             object obj = new object();
  191.             Hashtable refs = new Hashtable(20);
  192.             foreach (string s in options.ReferencedAssemblies) {
  193.                 // we do not want to have more than one reference to any given assembly
  194.                 if (refs[s] == null) {
  195.                     refs[s] = obj;
  196.                     sb.Append(cmdLineSwitch + "r:");
  197.                     sb.Append("\"");
  198.                     sb.Append(s);
  199.                     sb.Append("\" ");
  200.                 }
  201.             }
  202.             sb.Append(cmdLineSwitch + "out:");
  203.             sb.Append("\"");
  204.             sb.Append(options.OutputAssembly);
  205.             sb.Append("\" ");
  206.             if (options.IncludeDebugInformation) {
  207.                 sb.Append(cmdLineSwitch + "d:DEBUG ");
  208.                 sb.Append(cmdLineSwitch + "debug+ ");
  209.             }
  210.             else {
  211.                 sb.Append(cmdLineSwitch + "debug- ");
  212.             }
  213.             if (options.TreatWarningsAsErrors) {
  214.                 sb.Append(cmdLineSwitch + "warnaserror ");
  215.             }
  216.             if (options.WarningLevel >= 0) {
  217.                 sb.Append(cmdLineSwitch + "w:" + options.WarningLevel.ToString(CultureInfo.InvariantCulture) + " ");
  218.             }
  219.             // We append options.CompilerOptions in JSInProcCompiler.ParseCompilerOptions
  220.            
  221.             return sb.ToString();
  222.         }
  223.        
  224.         // Gets the name of the compiler executable.
  225.         protected override string CompilerName {
  226.             get { return "jsc.exe"; }
  227.         }
  228.        
  229.         protected override string CreateEscapedIdentifier(string name)
  230.         {
  231.             if (IsKeyword(name)) {
  232.                 return "\\" + name;
  233.             }
  234.             return name;
  235.         }
  236.        
  237.         protected override string CreateValidIdentifier(string name)
  238.         {
  239.             if (IsKeyword(name)) {
  240.                 return "$" + name;
  241.             }
  242.             return name;
  243.         }
  244.        
  245.         // Gets the file extension to use for source files.
  246.         protected override string FileExtension {
  247.             get { return ".js"; }
  248.         }
  249.        
  250.         protected override CompilerResults FromFileBatch(CompilerParameters options, string[] fileNames)
  251.         {
  252.             string outputFile = options.TempFiles.AddExtension("out");
  253.             CompilerResults results = new CompilerResults(options.TempFiles);
  254.            
  255.             if (options.OutputAssembly == null || options.OutputAssembly.Length == 0) {
  256.                 options.OutputAssembly = results.TempFiles.AddExtension("dll", !options.GenerateInMemory);
  257.             }
  258.            
  259.             // For debug mode, we construct a command line for debugging with JSC. The command line is
  260.             // only partially formed at this stage; the rest of it will be added and written to a response
  261.             // file by JSInProcCompiler.
  262.            
  263.             string partialCmdLine = null;
  264.             if (options.IncludeDebugInformation) {
  265.                 results.TempFiles.AddExtension("ildb");
  266.                 partialCmdLine = this.CmdArgsFromParameters(options);
  267.             }
  268.            
  269.             results.NativeCompilerReturnValue = 0;
  270.             try {
  271.                 JSInProcCompiler jsc = new JSInProcCompiler();
  272.                 results.NativeCompilerReturnValue = jsc.Compile(options, partialCmdLine, fileNames, outputFile);
  273.             }
  274.             catch {
  275.                 // internal compiler error
  276.                 results.NativeCompilerReturnValue = 10;
  277.             }
  278.            
  279.             // parse the output looking for errors and warnings
  280.             try {
  281.                 StreamReader compilerOutput = new StreamReader(outputFile);
  282.                 try {
  283.                     string line = compilerOutput.ReadLine();
  284.                     while (line != null) {
  285.                         results.Output.Add(line);
  286.                         ProcessCompilerOutputLine(results, line);
  287.                         line = compilerOutput.ReadLine();
  288.                     }
  289.                 }
  290.                 finally {
  291.                     compilerOutput.Close();
  292.                 }
  293.             }
  294.             catch (Exception e) {
  295.                 // could not open output file -- provide some other error information
  296.                 results.Output.Add(JScriptException.Localize("No error output", CultureInfo.CurrentUICulture));
  297.                 results.Output.Add(e.ToString());
  298.             }
  299.             catch {
  300.                 // could not open output file -- provide some other error information
  301.                 results.Output.Add(JScriptException.Localize("No error output", CultureInfo.CurrentUICulture));
  302.             }
  303.             if ((results.NativeCompilerReturnValue == 0) && options.GenerateInMemory) {
  304.                 FileStream fs = new FileStream(options.OutputAssembly, FileMode.Open, FileAccess.Read, FileShare.Read);
  305.                 try {
  306.                     int fileLen = (int)fs.Length;
  307.                     byte[] b = new byte[fileLen];
  308.                     fs.Read(b, 0, fileLen);
  309.                     results.CompiledAssembly = Assembly.Load(b, null, options.Evidence);
  310.                 }
  311.                 finally {
  312.                     fs.Close();
  313.                 }
  314.             }
  315.             else {
  316.                 results.PathToAssembly = Path.GetFullPath(options.OutputAssembly);
  317.             }
  318.             results.Evidence = options.Evidence;
  319.             return results;
  320.         }
  321.        
  322.         protected override void GenerateArgumentReferenceExpression(CodeArgumentReferenceExpression e)
  323.         {
  324.             OutputIdentifier(e.ParameterName);
  325.         }
  326.        
  327.         protected override void GenerateArrayCreateExpression(CodeArrayCreateExpression e)
  328.         {
  329.             CodeExpressionCollection init = e.Initializers;
  330.             if (init.Count > 0) {
  331.                 Output.Write("[");
  332.                 Indent++;
  333.                 OutputExpressionList(init);
  334.                 Indent--;
  335.                 Output.Write("]");
  336.             }
  337.             else {
  338.                 Output.Write("new ");
  339.                 Output.Write(GetBaseTypeOutput(e.CreateType.BaseType));
  340.                 Output.Write("[");
  341.                 if (e.SizeExpression != null) {
  342.                     GenerateExpression(e.SizeExpression);
  343.                 }
  344.                 else {
  345.                     Output.Write(e.Size.ToString(CultureInfo.InvariantCulture));
  346.                 }
  347.                 Output.Write("]");
  348.             }
  349.         }
  350.        
  351.         protected override void GenerateArrayIndexerExpression(CodeArrayIndexerExpression e)
  352.         {
  353.             GenerateExpression(e.TargetObject);
  354.             Output.Write("[");
  355.             bool first = true;
  356.             foreach (CodeExpression exp in e.Indices) {
  357.                 if (first) {
  358.                     first = false;
  359.                 }
  360.                 else {
  361.                     Output.Write(", ");
  362.                 }
  363.                 GenerateExpression(exp);
  364.             }
  365.             Output.Write("]");
  366.         }
  367.        
  368.         private void GenerateAssemblyAttributes(CodeAttributeDeclarationCollection attributes)
  369.         {
  370.             if (attributes.Count == 0)
  371.                 return;
  372.             IEnumerator en = attributes.GetEnumerator();
  373.             while (en.MoveNext()) {
  374.                 Output.Write("[");
  375.                 Output.Write("assembly: ");
  376.                 CodeAttributeDeclaration current = (CodeAttributeDeclaration)en.Current;
  377.                 Output.Write(GetBaseTypeOutput(current.Name));
  378.                 Output.Write("(");
  379.                 bool firstArg = true;
  380.                 foreach (CodeAttributeArgument arg in current.Arguments) {
  381.                     if (firstArg) {
  382.                         firstArg = false;
  383.                     }
  384.                     else {
  385.                         Output.Write(", ");
  386.                     }
  387.                     OutputAttributeArgument(arg);
  388.                 }
  389.                 Output.Write(")");
  390.                 Output.Write("]");
  391.                 Output.WriteLine();
  392.             }
  393.         }
  394.        
  395.         // Generates code for the specified CodeDom based assignment statement representation.
  396.         // 'e' indicates the statement to generate code for.
  397.         protected override void GenerateAssignStatement(CodeAssignStatement e)
  398.         {
  399.             GenerateExpression(e.Left);
  400.             Output.Write(" = ");
  401.             GenerateExpression(e.Right);
  402.             if (!forLoopHack) {
  403.                 Output.WriteLine(";");
  404.             }
  405.         }
  406.        
  407.         protected override void GenerateAttachEventStatement(CodeAttachEventStatement e)
  408.         {
  409.             GenerateExpression(e.Event.TargetObject);
  410.             Output.Write(".add_");
  411.             Output.Write(e.Event.EventName);
  412.             Output.Write("(");
  413.             GenerateExpression(e.Listener);
  414.             Output.WriteLine(");");
  415.         }
  416.        
  417.         // Generates code for the specified CodeDom based attribute block end representation.
  418.         // 'attributes' indicates the attribute block end to generate code for.
  419.         protected override void GenerateAttributeDeclarationsEnd(CodeAttributeDeclarationCollection attributes)
  420.         {
  421.         }
  422.        
  423.         // Generates code for the specified CodeDom based attribute block start representation.
  424.         // 'attributes' indicates the attribute block to generate code for.
  425.         protected override void GenerateAttributeDeclarationsStart(CodeAttributeDeclarationCollection attributes)
  426.         {
  427.         }
  428.        
  429.         // Generates code for the specified CodeDom based base reference expression
  430.         // representation.
  431.         // 'e' indicates the expression to generate code for.
  432.         protected override void GenerateBaseReferenceExpression(CodeBaseReferenceExpression e)
  433.         {
  434.             Output.Write("super");
  435.         }
  436.        
  437.         // Used to output the T part of new T[...]
  438.         private string GetBaseTypeOutput(string baseType)
  439.         {
  440.             if (baseType.Length == 0) {
  441.                 return "void";
  442.             }
  443.             else if (string.Compare(baseType, "System.Byte", StringComparison.Ordinal) == 0) {
  444.                 return "byte";
  445.             }
  446.             else if (string.Compare(baseType, "System.Int16", StringComparison.Ordinal) == 0) {
  447.                 return "short";
  448.             }
  449.             else if (string.Compare(baseType, "System.Int32", StringComparison.Ordinal) == 0) {
  450.                 return "int";
  451.             }
  452.             else if (string.Compare(baseType, "System.Int64", StringComparison.Ordinal) == 0) {
  453.                 return "long";
  454.             }
  455.             else if (string.Compare(baseType, "System.SByte", StringComparison.Ordinal) == 0) {
  456.                 return "sbyte";
  457.             }
  458.             else if (string.Compare(baseType, "System.UInt16", StringComparison.Ordinal) == 0) {
  459.                 return "ushort";
  460.             }
  461.             else if (string.Compare(baseType, "System.UInt32", StringComparison.Ordinal) == 0) {
  462.                 return "uint";
  463.             }
  464.             else if (string.Compare(baseType, "System.UInt64", StringComparison.Ordinal) == 0) {
  465.                 return "ulong";
  466.             }
  467.             else if (string.Compare(baseType, "System.Decimal", StringComparison.Ordinal) == 0) {
  468.                 return "decimal";
  469.             }
  470.             else if (string.Compare(baseType, "System.Single", StringComparison.Ordinal) == 0) {
  471.                 return "float";
  472.             }
  473.             else if (string.Compare(baseType, "System.Double", StringComparison.Ordinal) == 0) {
  474.                 return "double";
  475.             }
  476.             else if (string.Compare(baseType, "System.Boolean", StringComparison.Ordinal) == 0) {
  477.                 return "boolean";
  478.             }
  479.             else if (string.Compare(baseType, "System.Char", StringComparison.Ordinal) == 0) {
  480.                 return "char";
  481.             }
  482.             else {
  483.                 // replace + with . for nested classes.
  484.                 baseType = baseType.Replace('+', '.');
  485.                 return CreateEscapedIdentifier(baseType);
  486.             }
  487.         }
  488.        
  489.         // Generates code for the specified CodeDom based cast expression representation.
  490.         // 'e' indicates the expression to generate code for.
  491.         protected override void GenerateCastExpression(CodeCastExpression e)
  492.         {
  493.             OutputType(e.TargetType);
  494.             Output.Write("(");
  495.             GenerateExpression(e.Expression);
  496.             Output.Write(")");
  497.         }
  498.        
  499.         protected override void GenerateComment(CodeComment e)
  500.         {
  501.             string commentText = e.Text;
  502.             StringBuilder b = new StringBuilder(commentText.Length * 2);
  503.             string commentPrefix = e.DocComment ? "///" : "//";
  504.             // escape the comment text
  505.             b.Append(commentPrefix);
  506.             for (int i = 0; i < commentText.Length; i++) {
  507.                 switch (commentText[i]) {
  508.                     case '@':
  509.                         // suppress '@' to prevent compiler directives in comments
  510.                         break;
  511.                     case '\r':
  512.                         if (i < commentText.Length - 1 && commentText[i + 1] == '\n') {
  513.                             b.Append("\r\n" + commentPrefix);
  514.                             i++;
  515.                         }
  516.                         else {
  517.                             b.Append("\r" + commentPrefix);
  518.                         }
  519.                         break;
  520.                     case '\n':
  521.                         b.Append("\n" + commentPrefix);
  522.                         break;
  523.                     case '
':
  524.                         b.Append("
" + commentPrefix);
  525.                         break;
  526.                     case '
':
  527.                         b.Append("
" + commentPrefix);
  528.                         break;
  529.                     default:
  530.                         b.Append(commentText[i]);
  531.                         break;
  532.                 }
  533.             }
  534.             Output.WriteLine(b.ToString());
  535.         }
  536.        
  537.         protected override void GenerateCompileUnitStart(CodeCompileUnit e)
  538.         {
  539.             Output.WriteLine("//------------------------------------------------------------------------------");
  540.             Output.WriteLine("/// <autogenerated>");
  541.             Output.WriteLine("/// This code was generated by a tool.");
  542.             Output.WriteLine("/// Runtime Version: " + System.Environment.Version.ToString());
  543.             Output.WriteLine("///");
  544.             Output.WriteLine("/// Changes to this file may cause incorrect behavior and will be lost if ");
  545.             Output.WriteLine("/// the code is regenerated.");
  546.             Output.WriteLine("/// </autogenerated>");
  547.             Output.WriteLine("//------------------------------------------------------------------------------");
  548.             Output.WriteLine("");
  549.            
  550.             // Assembly attributes must be placed at the top level.
  551.             if (e.AssemblyCustomAttributes.Count > 0) {
  552.                 GenerateAssemblyAttributes(e.AssemblyCustomAttributes);
  553.                 Output.WriteLine("");
  554.             }
  555.         }
  556.        
  557.         // Generates code for the specified CodeDom based if statement representation.
  558.         // 'e' indicates the statement to generate code for.
  559.         protected override void GenerateConditionStatement(CodeConditionStatement e)
  560.         {
  561.             Output.Write("if (");
  562.             // Indent within the condition, in case they need to go on multiple lines.
  563.             Indent += 2;
  564.             GenerateExpression(e.Condition);
  565.             Indent -= 2;
  566.             Output.Write(")");
  567.             OutputStartingBrace();
  568.             Indent++;
  569.             GenerateStatements(e.TrueStatements);
  570.             Indent--;
  571.            
  572.             if (e.FalseStatements.Count > 0) {
  573.                 Output.Write("}");
  574.                 if (Options.ElseOnClosing) {
  575.                     Output.Write(" ");
  576.                 }
  577.                 else {
  578.                     Output.WriteLine("");
  579.                 }
  580.                 Output.Write("else");
  581.                 OutputStartingBrace();
  582.                 Indent++;
  583.                 GenerateStatements(e.FalseStatements);
  584.                 Indent--;
  585.             }
  586.             Output.WriteLine("}");
  587.         }
  588.        
  589.        
  590.         // Generates code for the specified CodeDom based constructor representation.
  591.         // 'e' indicates the constructor to generate code for.
  592.         protected override void GenerateConstructor(CodeConstructor e, CodeTypeDeclaration c)
  593.         {
  594.             if (!(IsCurrentClass || IsCurrentStruct))
  595.                 return;
  596.            
  597.             OutputMemberAccessModifier(e.Attributes);
  598.             if (e.CustomAttributes.Count > 0) {
  599.                 OutputAttributeDeclarations(e.CustomAttributes);
  600.             }
  601.             Output.Write("function ");
  602.             OutputIdentifier(CurrentTypeName);
  603.             Output.Write("(");
  604.             OutputParameters(e.Parameters);
  605.             Output.Write(")");
  606.            
  607.             CodeExpressionCollection baseArgs = e.BaseConstructorArgs;
  608.             CodeExpressionCollection thisArgs = e.ChainedConstructorArgs;
  609.            
  610.             OutputStartingBrace();
  611.             Indent++;
  612.             if (baseArgs.Count > 0) {
  613.                 Output.Write("super(");
  614.                 OutputExpressionList(baseArgs);
  615.                 Output.WriteLine(");");
  616.             }
  617.            
  618.             if (thisArgs.Count > 0) {
  619.                 Output.Write("this(");
  620.                 OutputExpressionList(thisArgs);
  621.                 Output.WriteLine(");");
  622.             }
  623.            
  624.             GenerateStatements(e.Statements);
  625.             Output.WriteLine();
  626.             Indent--;
  627.             Output.WriteLine("}");
  628.         }
  629.        
  630.         // Generates code for the specified CodeDom based delegate creation expression representation.
  631.         // 'e' indicates the delegate creation expression to generate code for.
  632.         protected override void GenerateDelegateCreateExpression(CodeDelegateCreateExpression e)
  633.         {
  634.             bool castToDelegate = (e.DelegateType != null);
  635.             if (castToDelegate) {
  636.                 OutputType(e.DelegateType);
  637.                 Output.Write("(");
  638.             }
  639.             GenerateExpression(e.TargetObject);
  640.             Output.Write(".");
  641.             OutputIdentifier(e.MethodName);
  642.             if (castToDelegate)
  643.                 Output.Write(")");
  644.         }
  645.        
  646.         // Generates code for the specified CodeDom based delegate invoke expression representation.
  647.         // 'e' indicates the expression to generate code for.
  648.         protected override void GenerateDelegateInvokeExpression(CodeDelegateInvokeExpression e)
  649.         {
  650.             if (e.TargetObject != null) {
  651.                 GenerateExpression(e.TargetObject);
  652.             }
  653.             Output.Write("(");
  654.             OutputExpressionList(e.Parameters);
  655.             Output.Write(")");
  656.         }
  657.        
  658.         protected override void GenerateEntryPointMethod(CodeEntryPointMethod e, CodeTypeDeclaration c)
  659.         {
  660.             Output.Write("public static ");
  661.             if (e.CustomAttributes.Count > 0) {
  662.                 OutputAttributeDeclarations(e.CustomAttributes);
  663.             }
  664.             Output.Write("function Main()");
  665.             OutputStartingBrace();
  666.             Indent++;
  667.             GenerateStatements(e.Statements);
  668.             Indent--;
  669.             Output.WriteLine("}");
  670.             mainClassName = CurrentTypeName;
  671.             mainMethodName = "Main";
  672.         }
  673.        
  674.         protected override void GenerateEvent(CodeMemberEvent e, CodeTypeDeclaration c)
  675.         {
  676.             throw new Exception(JScriptException.Localize("No event declarations", CultureInfo.CurrentUICulture));
  677.         }
  678.        
  679.         protected override void GenerateEventReferenceExpression(CodeEventReferenceExpression e)
  680.         {
  681.             // JScript does not allow ob.foo where foo is an event name. (This should never get
  682.             // called, but we'll put an exception here just in case.)
  683.             throw new Exception(JScriptException.Localize("No event references", CultureInfo.CurrentUICulture));
  684.         }
  685.        
  686.         // Generates code for the specified CodeDom based method invoke statement representation.
  687.         // 'e' indicates the statement to generate code for.
  688.         protected override void GenerateExpressionStatement(CodeExpressionStatement e)
  689.         {
  690.             GenerateExpression(e.Expression);
  691.             if (!forLoopHack) {
  692.                 Output.WriteLine(";");
  693.             }
  694.         }
  695.        
  696.        
  697.         // Generates code for the specified CodeDom based member field representation.
  698.         // 'e' indicates the field to generate code for.
  699.         protected override void GenerateField(CodeMemberField e)
  700.         {
  701.             if (IsCurrentDelegate || IsCurrentInterface)
  702.                 throw new Exception(JScriptException.Localize("Only methods on interfaces", CultureInfo.CurrentUICulture));
  703.            
  704.             if (IsCurrentEnum) {
  705.                 OutputIdentifier(e.Name);
  706.                 if (e.InitExpression != null) {
  707.                     Output.Write(" = ");
  708.                     GenerateExpression(e.InitExpression);
  709.                 }
  710.                 Output.WriteLine(",");
  711.             }
  712.             else {
  713.                 OutputMemberAccessModifier(e.Attributes);
  714.                 if ((e.Attributes & MemberAttributes.ScopeMask) == MemberAttributes.Static)
  715.                     Output.Write("static ");
  716.                 if (e.CustomAttributes.Count > 0) {
  717.                     OutputAttributeDeclarations(e.CustomAttributes);
  718.                     Output.WriteLine("");
  719.                 }
  720.                 if ((e.Attributes & MemberAttributes.Const) == MemberAttributes.Const) {
  721.                     if ((e.Attributes & MemberAttributes.ScopeMask) != MemberAttributes.Static)
  722.                         Output.Write("static ");
  723.                     Output.Write("const ");
  724.                 }
  725.                 else
  726.                     Output.Write("var ");
  727.                 OutputTypeNamePair(e.Type, e.Name);
  728.                 if (e.InitExpression != null) {
  729.                     Output.Write(" = ");
  730.                     GenerateExpression(e.InitExpression);
  731.                 }
  732.                 Output.WriteLine(";");
  733.             }
  734.         }
  735.        
  736.         // Generates code for the specified CodeDom based field reference expression representation.
  737.         // 'e' indicates the expression to generate code for.
  738.         protected override void GenerateFieldReferenceExpression(CodeFieldReferenceExpression e)
  739.         {
  740.             if (e.TargetObject != null) {
  741.                 GenerateExpression(e.TargetObject);
  742.                 Output.Write(".");
  743.             }
  744.             OutputIdentifier(e.FieldName);
  745.         }
  746.        
  747.         protected override void GenerateGotoStatement(CodeGotoStatement e)
  748.         {
  749.             throw new Exception(JScriptException.Localize("No goto statements", CultureInfo.CurrentUICulture));
  750.         }
  751.        
  752.         // Generates code for the specified CodeDom based indexer expression representation.
  753.         // 'e' indicates the expression to generate code for.
  754.         protected override void GenerateIndexerExpression(CodeIndexerExpression e)
  755.         {
  756.             GenerateExpression(e.TargetObject);
  757.             Output.Write("[");
  758.             bool first = true;
  759.             foreach (CodeExpression exp in e.Indices) {
  760.                 if (first) {
  761.                     first = false;
  762.                 }
  763.                 else {
  764.                     Output.Write(", ");
  765.                 }
  766.                 GenerateExpression(exp);
  767.             }
  768.             Output.Write("]");
  769.         }
  770.        
  771.         // Generates code for the specified CodeDom based for loop statement representation.
  772.         // 'e' indicates the statement to generate code for.
  773.         protected override void GenerateIterationStatement(CodeIterationStatement e)
  774.         {
  775.             forLoopHack = true;
  776.             Output.Write("for (");
  777.             GenerateStatement(e.InitStatement);
  778.             Output.Write("; ");
  779.             GenerateExpression(e.TestExpression);
  780.             Output.Write("; ");
  781.             GenerateStatement(e.IncrementStatement);
  782.             Output.Write(")");
  783.             OutputStartingBrace();
  784.             forLoopHack = false;
  785.             Indent++;
  786.             GenerateStatements(e.Statements);
  787.             Indent--;
  788.             Output.WriteLine("}");
  789.         }
  790.        
  791.         protected override void GenerateLabeledStatement(CodeLabeledStatement e)
  792.         {
  793.             throw new Exception(JScriptException.Localize("No goto statements", CultureInfo.CurrentUICulture));
  794.         }
  795.        
  796.         // Generates code for the specified CodeDom based line pragma start representation.
  797.         // 'e' indicates the start position to generate code for.
  798.         protected override void GenerateLinePragmaStart(CodeLinePragma e)
  799.         {
  800.             Output.WriteLine("");
  801.             Output.WriteLine("//@cc_on");
  802.             Output.Write("//@set @position(file=\"");
  803.            
  804.             // we need to escape "\" to become "\\", however regex requires the
  805.             // _pattern_ to be escaped, therefore the replacement is "\\" --> "\\"...
  806.             // since C# requires \ to be escaped we get the apparently meaningless
  807.             // expression below...
  808.             //
  809.             Output.Write(Regex.Replace(e.FileName, "\\\\", "\\\\"));
  810.            
  811.             Output.Write("\";line=");
  812.             Output.Write(e.LineNumber.ToString(CultureInfo.InvariantCulture));
  813.             Output.WriteLine(")");
  814.         }
  815.        
  816.         // Generates code for the specified CodeDom based line pragma end representation.
  817.         // 'e' indicates the end position to generate code for.
  818.         protected override void GenerateLinePragmaEnd(CodeLinePragma e)
  819.         {
  820.             Output.WriteLine("");
  821.             Output.WriteLine("//@set @position(end)");
  822.         }
  823.        
  824.         // Generates code for the specified CodeDom based member method representation.
  825.         // 'e' indicates the method to generate code for.
  826.         protected override void GenerateMethod(CodeMemberMethod e, CodeTypeDeclaration c)
  827.         {
  828.             if (!IsCurrentInterface) {
  829.                 if (e.PrivateImplementationType == null) {
  830.                     OutputMemberAccessModifier(e.Attributes);
  831.                     OutputMemberVTableModifier(e.Attributes);
  832.                     OutputMemberScopeModifier(e.Attributes);
  833.                 }
  834.             }
  835.             else {
  836.                 OutputMemberVTableModifier(e.Attributes);
  837.             }
  838.             if (e.CustomAttributes.Count > 0) {
  839.                 OutputAttributeDeclarations(e.CustomAttributes);
  840.             }
  841.             Output.Write("function ");
  842.             if (e.PrivateImplementationType != null && !IsCurrentInterface) {
  843.                 Output.Write(e.PrivateImplementationType.BaseType);
  844.                 Output.Write(".");
  845.             }
  846.             OutputIdentifier(e.Name);
  847.             Output.Write("(");
  848.             // disable use of '&' in front of ref and out parameters (JScript doesn't allow them to be declared, only used)
  849.             this.isArgumentList = false;
  850.             try {
  851.                 OutputParameters(e.Parameters);
  852.             }
  853.             finally {
  854.                 this.isArgumentList = true;
  855.             }
  856.             Output.Write(")");
  857.             if (e.ReturnType.BaseType.Length > 0 && string.Compare(e.ReturnType.BaseType, typeof(void).FullName, StringComparison.Ordinal) != 0) {
  858.                 Output.Write(" : ");
  859.                 OutputType(e.ReturnType);
  860.             }
  861.             if (!IsCurrentInterface && (e.Attributes & MemberAttributes.ScopeMask) != MemberAttributes.Abstract) {
  862.                 OutputStartingBrace();
  863.                 Indent++;
  864.                 GenerateStatements(e.Statements);
  865.                 Indent--;
  866.                 Output.WriteLine("}");
  867.             }
  868.             else {
  869.                 Output.WriteLine(";");
  870.             }
  871.         }
  872.        
  873.         // Generates code for the specified CodeDom based method invoke expression representation.
  874.         // 'e' indicates the expression to generate code for.
  875.         protected override void GenerateMethodInvokeExpression(CodeMethodInvokeExpression e)
  876.         {
  877.             GenerateMethodReferenceExpression(e.Method);
  878.             Output.Write("(");
  879.             OutputExpressionList(e.Parameters);
  880.             Output.Write(")");
  881.         }
  882.        
  883.         protected override void GenerateMethodReferenceExpression(CodeMethodReferenceExpression e)
  884.         {
  885.             if (e.TargetObject != null) {
  886.                 if (e.TargetObject is CodeBinaryOperatorExpression) {
  887.                     Output.Write("(");
  888.                     GenerateExpression(e.TargetObject);
  889.                     Output.Write(")");
  890.                 }
  891.                 else {
  892.                     GenerateExpression(e.TargetObject);
  893.                 }
  894.                 Output.Write(".");
  895.             }
  896.             OutputIdentifier(e.MethodName);
  897.         }
  898.        
  899.         // Generates code for the specified CodeDom based method return statement representation.
  900.         // 'e' indicates the statement to generate code for.
  901.         protected override void GenerateMethodReturnStatement(CodeMethodReturnStatement e)
  902.         {
  903.             Output.Write("return");
  904.             if (e.Expression != null) {
  905.                 Output.Write(" ");
  906.                 GenerateExpression(e.Expression);
  907.             }
  908.             Output.WriteLine(";");
  909.         }
  910.        
  911.         // Generates code for the specified CodeDom based namespace representation.
  912.         // 'e' indicates the namespace to generate code for.
  913.         protected override void GenerateNamespace(CodeNamespace e)
  914.         {
  915.             Output.WriteLine("//@cc_on");
  916.             Output.WriteLine("//@set @debug(off)");
  917.             Output.WriteLine("");
  918.            
  919.             GenerateNamespaceImports(e);
  920.             Output.WriteLine("");
  921.            
  922.             GenerateCommentStatements(e.Comments);
  923.             GenerateNamespaceStart(e);
  924.             GenerateTypes(e);
  925.             GenerateNamespaceEnd(e);
  926.         }
  927.        
  928.         // Generates code for the specified CodeDom based namespace end representation.
  929.         // 'e' indicates the namespace end to generate code for.
  930.         protected override void GenerateNamespaceEnd(CodeNamespace e)
  931.         {
  932.             if (e.Name != null && e.Name.Length > 0) {
  933.                 Indent--;
  934.                 Output.WriteLine("}");
  935.             }
  936.            
  937.             if (mainClassName != null) {
  938.                 if (e.Name != null) {
  939.                     OutputIdentifier(e.Name);
  940.                     Output.Write(".");
  941.                 }
  942.                 OutputIdentifier(mainClassName);
  943.                 Output.Write(".");
  944.                 OutputIdentifier(mainMethodName);
  945.                 Output.WriteLine("();");
  946.                 mainClassName = null;
  947.             }
  948.         }
  949.        
  950.         // Generates code for the specified CodeDom based namespace import representation.
  951.         // 'e' indicates the namespace import to generate code for.
  952.         protected override void GenerateNamespaceImport(CodeNamespaceImport e)
  953.         {
  954.             Output.Write("import ");
  955.             OutputIdentifier(e.Namespace);
  956.             Output.WriteLine(";");
  957.         }
  958.        
  959.         // Generates code for the specified CodeDom based namespace start representation.
  960.         // 'e' indicates the namespace start to generate code for.
  961.         protected override void GenerateNamespaceStart(CodeNamespace e)
  962.         {
  963.             if (e.Name != null && e.Name.Length > 0) {
  964.                 Output.Write("package ");
  965.                 OutputIdentifier(e.Name);
  966.                 OutputStartingBrace();
  967.                 Indent++;
  968.             }
  969.         }
  970.        
  971.         // Generates code for the specified CodeDom based object creation expression representation.
  972.         // 'e' indicates the expression to generate code for.
  973.         protected override void GenerateObjectCreateExpression(CodeObjectCreateExpression e)
  974.         {
  975.             Output.Write("new ");
  976.             OutputType(e.CreateType);
  977.             Output.Write("(");
  978.             OutputExpressionList(e.Parameters);
  979.             Output.Write(")");
  980.         }
  981.        
  982.         protected override void GenerateParameterDeclarationExpression(CodeParameterDeclarationExpression e)
  983.         {
  984.             if (e.CustomAttributes.Count > 0) {
  985.                 CodeAttributeDeclaration attr = e.CustomAttributes[0];
  986.                 if (attr.Name == "ParamArrayAttribute")
  987.                     Output.Write("... ");
  988.                 else {
  989.                     throw new Exception(JScriptException.Localize("No parameter attributes", CultureInfo.CurrentUICulture));
  990.                     // Output.Write("[");
  991.                     // OutputAttributeDeclarations(current.CustomAttributes);
  992.                     // Output.Write("]");
  993.                 }
  994.             }
  995.             OutputDirection(e.Direction);
  996.             OutputTypeNamePair(e.Type, e.Name);
  997.         }
  998.        
  999.         // Generates code for the specified CodeDom based member property representation.
  1000.         // 'e' indicates the member property to generate code for.
  1001.         protected override void GenerateProperty(CodeMemberProperty e, CodeTypeDeclaration c)
  1002.         {
  1003.             if (!(IsCurrentClass || IsCurrentStruct || IsCurrentInterface))
  1004.                 return;
  1005.            
  1006.             if (e.HasGet) {
  1007.                 if (!IsCurrentInterface) {
  1008.                     if (e.PrivateImplementationType == null) {
  1009.                         OutputMemberAccessModifier(e.Attributes);
  1010.                         OutputMemberVTableModifier(e.Attributes);
  1011.                         OutputMemberScopeModifier(e.Attributes);
  1012.                     }
  1013.                 }
  1014.                 else {
  1015.                     OutputMemberVTableModifier(e.Attributes);
  1016.                 }
  1017.                 if (e.CustomAttributes.Count > 0) {
  1018.                     if (IsCurrentInterface)
  1019.                         Output.Write("public ");
  1020.                     OutputAttributeDeclarations(e.CustomAttributes);
  1021.                     Output.WriteLine("");
  1022.                 }
  1023.                 Output.Write("function get ");
  1024.                 if (e.PrivateImplementationType != null && !IsCurrentInterface) {
  1025.                     Output.Write(e.PrivateImplementationType.BaseType);
  1026.                     Output.Write(".");
  1027.                 }
  1028.                 OutputIdentifier(e.Name);
  1029.                 if (e.Parameters.Count > 0)
  1030.                     throw new Exception(JScriptException.Localize("No indexer declarations", CultureInfo.CurrentUICulture));
  1031.                 Output.Write("() : ");
  1032.                 OutputType(e.Type);
  1033.                 if (IsCurrentInterface || (e.Attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract) {
  1034.                     Output.WriteLine(";");
  1035.                 }
  1036.                 else {
  1037.                     OutputStartingBrace();
  1038.                     Indent++;
  1039.                     GenerateStatements(e.GetStatements);
  1040.                     Indent--;
  1041.                     Output.WriteLine("}");
  1042.                 }
  1043.             }
  1044.             if (e.HasSet) {
  1045.                 if (!IsCurrentInterface) {
  1046.                     if (e.PrivateImplementationType == null) {
  1047.                         OutputMemberAccessModifier(e.Attributes);
  1048.                         OutputMemberVTableModifier(e.Attributes);
  1049.                         OutputMemberScopeModifier(e.Attributes);
  1050.                     }
  1051.                 }
  1052.                 else {
  1053.                     OutputMemberVTableModifier(e.Attributes);
  1054.                 }
  1055.                 if (e.CustomAttributes.Count > 0 && !e.HasGet) {
  1056.                     if (IsCurrentInterface)
  1057.                         Output.Write("public ");
  1058.                     OutputAttributeDeclarations(e.CustomAttributes);
  1059.                     Output.WriteLine("");
  1060.                 }
  1061.                 Output.Write("function set ");
  1062.                 if (e.PrivateImplementationType != null && !IsCurrentInterface) {
  1063.                     Output.Write(e.PrivateImplementationType.BaseType);
  1064.                     Output.Write(".");
  1065.                 }
  1066.                 OutputIdentifier(e.Name);
  1067.                 Output.Write("(");
  1068.                 OutputTypeNamePair(e.Type, "value");
  1069.                 if (e.Parameters.Count > 0)
  1070.                     throw new Exception(JScriptException.Localize("No indexer declarations", CultureInfo.CurrentUICulture));
  1071.                 Output.Write(")");
  1072.                 if (IsCurrentInterface || (e.Attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract) {
  1073.                     Output.WriteLine(";");
  1074.                 }
  1075.                 else {
  1076.                     OutputStartingBrace();
  1077.                     Indent++;
  1078.                     GenerateStatements(e.SetStatements);
  1079.                     Indent--;
  1080.                     Output.WriteLine("}");
  1081.                 }
  1082.             }
  1083.         }
  1084.        
  1085.         // Generates code for the specified CodeDom based property reference expression representation.
  1086.         // 'e' indicates the expression to generate code for.
  1087.         protected override void GeneratePropertyReferenceExpression(CodePropertyReferenceExpression e)
  1088.         {
  1089.             if (e.TargetObject != null) {
  1090.                 GenerateExpression(e.TargetObject);
  1091.                 Output.Write(".");
  1092.             }
  1093.             OutputIdentifier(e.PropertyName);
  1094.         }
  1095.        
  1096.         protected override void GeneratePropertySetValueReferenceExpression(CodePropertySetValueReferenceExpression e)
  1097.         {
  1098.             Output.Write("value");
  1099.         }
  1100.        
  1101.         protected override void GenerateRemoveEventStatement(CodeRemoveEventStatement e)
  1102.         {
  1103.             GenerateExpression(e.Event.TargetObject);
  1104.             Output.Write(".remove_");
  1105.             Output.Write(e.Event.EventName);
  1106.             Output.Write("(");
  1107.             GenerateExpression(e.Listener);
  1108.             Output.WriteLine(");");
  1109.         }
  1110.        
  1111.         protected override void GenerateSingleFloatValue(float s)
  1112.         {
  1113.             Output.Write("float(");
  1114.             Output.Write(s.ToString(CultureInfo.InvariantCulture));
  1115.             Output.Write(")");
  1116.         }
  1117.        
  1118.         // Generates code for the specified CodeDom based snippet expression representation.
  1119.         // 'e' indicates the expression to generate code for.
  1120.         protected override void GenerateSnippetExpression(CodeSnippetExpression e)
  1121.         {
  1122.             Output.Write(e.Value);
  1123.         }
  1124.        
  1125.         // Generates code for the specified CodeDom based snippet class member representation.
  1126.         // 'e' indicates the expression to generate code for.
  1127.         protected override void GenerateSnippetMember(CodeSnippetTypeMember e)
  1128.         {
  1129.             Output.Write(e.Text);
  1130.         }
  1131.        
  1132.         protected override void GenerateSnippetStatement(CodeSnippetStatement e)
  1133.         {
  1134.             Output.WriteLine(e.Value);
  1135.         }
  1136.        
  1137.         // Generates code for the specified CodeDom based this reference expression representation.
  1138.         // 'e' indicates the expression to generate code for.
  1139.         protected override void GenerateThisReferenceExpression(CodeThisReferenceExpression e)
  1140.         {
  1141.             Output.Write("this");
  1142.         }
  1143.        
  1144.         // Generates code for the specified CodeDom based throw exception statement representation.
  1145.         // 'e' indicates the statement to generate code for.
  1146.         protected override void GenerateThrowExceptionStatement(CodeThrowExceptionStatement e)
  1147.         {
  1148.             Output.Write("throw");
  1149.             if (e.ToThrow != null) {
  1150.                 Output.Write(" ");
  1151.                 GenerateExpression(e.ToThrow);
  1152.             }
  1153.             Output.WriteLine(";");
  1154.         }
  1155.        
  1156.         protected override void GenerateTryCatchFinallyStatement(CodeTryCatchFinallyStatement e)
  1157.         {
  1158.             Output.Write("try");
  1159.             OutputStartingBrace();
  1160.             Indent++;
  1161.             GenerateStatements(e.TryStatements);
  1162.             Indent--;
  1163.             CodeCatchClauseCollection catches = e.CatchClauses;
  1164.             if (catches.Count > 0) {
  1165.                 IEnumerator en = catches.GetEnumerator();
  1166.                 while (en.MoveNext()) {
  1167.                     Output.Write("}");
  1168.                     if (Options.ElseOnClosing) {
  1169.                         Output.Write(" ");
  1170.                     }
  1171.                     else {
  1172.                         Output.WriteLine("");
  1173.                     }
  1174.                     CodeCatchClause current = (CodeCatchClause)en.Current;
  1175.                     Output.Write("catch (");
  1176.                     OutputIdentifier(current.LocalName);
  1177.                     Output.Write(" : ");
  1178.                     OutputType(current.CatchExceptionType);
  1179.                     Output.Write(")");
  1180.                     OutputStartingBrace();
  1181.                     Indent++;
  1182.                     GenerateStatements(current.Statements);
  1183.                     Indent--;
  1184.                 }
  1185.             }
  1186.            
  1187.             CodeStatementCollection finallyStatements = e.FinallyStatements;
  1188.             if (finallyStatements.Count > 0) {
  1189.                 Output.Write("}");
  1190.                 if (Options.ElseOnClosing) {
  1191.                     Output.Write(" ");
  1192.                 }
  1193.                 else {
  1194.                     Output.WriteLine("");
  1195.                 }
  1196.                 Output.Write("finally");
  1197.                 OutputStartingBrace();
  1198.                 Indent++;
  1199.                 GenerateStatements(finallyStatements);
  1200.                 Indent--;
  1201.             }
  1202.             Output.WriteLine("}");
  1203.         }
  1204.        
  1205.         // Generates code for the specified CodeDom based class constructor representation.
  1206.         // 'e' indicates the constructor to generate code for.
  1207.         protected override void GenerateTypeConstructor(CodeTypeConstructor e)
  1208.         {
  1209.             if (!(IsCurrentClass || IsCurrentStruct))
  1210.                 return;
  1211.            
  1212.             Output.Write("static ");
  1213.             OutputIdentifier(CurrentTypeName);
  1214.             OutputStartingBrace();
  1215.             Indent++;
  1216.             GenerateStatements(e.Statements);
  1217.             Indent--;
  1218.             Output.WriteLine("}");
  1219.         }
  1220.        
  1221.         // Generates code for the specified CodeDom based class end representation.
  1222.         // 'e' indicates the end of the class.
  1223.         protected override void GenerateTypeEnd(CodeTypeDeclaration e)
  1224.         {
  1225.             if (!IsCurrentDelegate) {
  1226.                 Indent--;
  1227.                 Output.WriteLine("}");
  1228.             }
  1229.         }
  1230.        
  1231.         // Generates code for the specified CodeDom based type of expression
  1232.         // representation.
  1233.         protected override void GenerateTypeOfExpression(CodeTypeOfExpression e)
  1234.         {
  1235.             OutputType(e.Type);
  1236.         }
  1237.        
  1238.         protected override string GetTypeOutput(CodeTypeReference typeRef)
  1239.         {
  1240.             string s;
  1241.             if (typeRef.ArrayElementType != null) {
  1242.                 // Recurse up
  1243.                 s = GetTypeOutput(typeRef.ArrayElementType);
  1244.             }
  1245.             else {
  1246.                 s = GetBaseTypeOutput(typeRef.BaseType);
  1247.             }
  1248.             // Now spit out the array postfix
  1249.             if (typeRef.ArrayRank > 0) {
  1250.                 char[] results = new char[typeRef.ArrayRank + 1];
  1251.                 results[0] = '[';
  1252.                 results[typeRef.ArrayRank] = ']';
  1253.                 for (int i = 1; i < typeRef.ArrayRank; i++) {
  1254.                     results[i] = ',';
  1255.                 }
  1256.                 s += new string(results);
  1257.             }
  1258.             return s;
  1259.         }
  1260.        
  1261.         // Generates code for the specified CodeDom based class start representation.
  1262.         // 'e' indicates the start of the class.
  1263.         protected override void GenerateTypeStart(CodeTypeDeclaration e)
  1264.         {
  1265.             if (IsCurrentDelegate)
  1266.                 throw new Exception(JScriptException.Localize("No delegate declarations", CultureInfo.CurrentUICulture));
  1267.            
  1268.             OutputTypeVisibility(e.TypeAttributes);
  1269.             if (e.CustomAttributes.Count > 0) {
  1270.                 OutputAttributeDeclarations(e.CustomAttributes);
  1271.                 Output.WriteLine("");
  1272.             }
  1273.             OutputTypeAttributes(e.TypeAttributes, IsCurrentStruct, IsCurrentEnum);
  1274.             OutputIdentifier(e.Name);
  1275.            
  1276.             if (IsCurrentEnum) {
  1277.                 if (e.BaseTypes.Count > 1)
  1278.                     throw new Exception(JScriptException.Localize("Too many base types", CultureInfo.CurrentUICulture));
  1279.                 if (e.BaseTypes.Count == 1) {
  1280.                     Output.Write(" : ");
  1281.                     OutputType(e.BaseTypes[0]);
  1282.                 }
  1283.             }
  1284.             else {
  1285.                 bool first = true;
  1286.                 bool second = false;
  1287.                 foreach (CodeTypeReference typeRef in e.BaseTypes) {
  1288.                     if (first) {
  1289.                         Output.Write(" extends ");
  1290.                         first = false;
  1291.                         second = true;
  1292.                     }
  1293.                     else if (second) {
  1294.                         Output.Write(" implements ");
  1295.                         second = false;
  1296.                     }
  1297.                     else {
  1298.                         Output.Write(", ");
  1299.                     }
  1300.                     OutputType(typeRef);
  1301.                 }
  1302.             }
  1303.             OutputStartingBrace();
  1304.             Indent++;
  1305.         }
  1306.        
  1307.         // Generates code for the specified CodeDom based variable declaration statement representation.
  1308.         // 'e' indicates the statement to generate code for.
  1309.         protected override void GenerateVariableDeclarationStatement(CodeVariableDeclarationStatement e)
  1310.         {
  1311.             Output.Write("var ");
  1312.             OutputTypeNamePair(e.Type, e.Name);
  1313.             if (e.InitExpression != null) {
  1314.                 Output.Write(" = ");
  1315.                 GenerateExpression(e.InitExpression);
  1316.             }
  1317.             Output.WriteLine(";");
  1318.         }
  1319.        
  1320.         protected override void GenerateVariableReferenceExpression(CodeVariableReferenceExpression e)
  1321.         {
  1322.             OutputIdentifier(e.VariableName);
  1323.         }
  1324.        
  1325.         bool IsKeyword(string value)
  1326.         {
  1327.             return keywords.ContainsKey(value);
  1328.         }
  1329.        
  1330.        
  1331.         // Gets whether the specified value is a valid identifier.
  1332.         // 'value' is the string to test for validity as an identifier.
  1333.         protected override bool IsValidIdentifier(string value)
  1334.         {
  1335.             // identifiers must be 1 char or longer
  1336.             if (value == null || value.Length == 0) {
  1337.                 return false;
  1338.             }
  1339.            
  1340.             VsaEngine engine = VsaEngine.CreateEngine();
  1341.             return engine.IsValidIdentifier(value);
  1342.         }
  1343.        
  1344.         // Gets the token used to represent 'null'.
  1345.         protected override string NullToken {
  1346.             get { return "null"; }
  1347.         }
  1348.        
  1349.         // Generates code for the specified System.CodeDom.CodeAttributeBlock.
  1350.         protected override void OutputAttributeDeclarations(CodeAttributeDeclarationCollection attributes)
  1351.         {
  1352.             if (attributes.Count == 0)
  1353.                 return;
  1354.             GenerateAttributeDeclarationsStart(attributes);
  1355.             IEnumerator en = attributes.GetEnumerator();
  1356.             while (en.MoveNext()) {
  1357.                 CodeAttributeDeclaration current = (CodeAttributeDeclaration)en.Current;
  1358.                 Output.Write(GetBaseTypeOutput(current.Name));
  1359.                 Output.Write("(");
  1360.                
  1361.                 bool firstArg = true;
  1362.                 foreach (CodeAttributeArgument arg in current.Arguments) {
  1363.                     if (firstArg) {
  1364.                         firstArg = false;
  1365.                     }
  1366.                     else {
  1367.                         Output.Write(", ");
  1368.                     }
  1369.                     OutputAttributeArgument(arg);
  1370.                 }
  1371.                 Output.Write(") ");
  1372.             }
  1373.             GenerateAttributeDeclarationsEnd(attributes);
  1374.         }
  1375.        
  1376.         protected override void OutputDirection(FieldDirection dir)
  1377.         {
  1378.             switch (dir) {
  1379.                 case FieldDirection.In:
  1380.                     break;
  1381.                 case FieldDirection.Out:
  1382.                 case FieldDirection.Ref:
  1383.                     if (!this.isArgumentList)
  1384.                         throw new Exception(JScriptException.Localize("No parameter direction", CultureInfo.CurrentUICulture));
  1385.                     else
  1386.                         Output.Write("&");
  1387.                     break;
  1388.             }
  1389.         }
  1390.        
  1391.         protected override void OutputIdentifier(string ident)
  1392.         {
  1393.             Output.Write(CreateEscapedIdentifier(ident));
  1394.         }
  1395.        
  1396.         // Generates code for the specified CodeDom based member access modifier representation.
  1397.         // 'attributes' indicates the access modifier to generate code for.
  1398.         protected override void OutputMemberAccessModifier(MemberAttributes attributes)
  1399.         {
  1400.             switch (attributes & MemberAttributes.AccessMask) {
  1401.                 case MemberAttributes.Assembly:
  1402.                     Output.Write("internal ");
  1403.                     break;
  1404.                 case MemberAttributes.FamilyAndAssembly:
  1405.                     Output.Write("internal ");
  1406.                     break;
  1407.                 case MemberAttributes.Family:
  1408.                     Output.Write("protected ");
  1409.                     break;
  1410.                 case MemberAttributes.FamilyOrAssembly:
  1411.                     Output.Write("protected internal ");
  1412.                     break;
  1413.                 case MemberAttributes.Public:
  1414.                     Output.Write("public ");
  1415.                     break;
  1416.                 default:
  1417.                     Output.Write("private ");
  1418.                     break;
  1419.             }
  1420.         }
  1421.        
  1422.         // Generates code for the specified CodeDom based member scope modifier representation.
  1423.         // 'attributes' indicates the scope modifier to generate code for.</para>
  1424.         protected override void OutputMemberScopeModifier(MemberAttributes attributes)
  1425.         {
  1426.             switch (attributes & MemberAttributes.ScopeMask) {
  1427.                 case MemberAttributes.Abstract:
  1428.                     Output.Write("abstract ");
  1429.                     break;
  1430.                 case MemberAttributes.Final:
  1431.                     Output.Write("final ");
  1432.                     break;
  1433.                 case MemberAttributes.Static:
  1434.                     Output.Write("static ");
  1435.                     break;
  1436.                 case MemberAttributes.Override:
  1437.                     Output.Write("override ");
  1438.                     break;
  1439.                 default:
  1440.                     break;
  1441.             }
  1442.         }
  1443.        
  1444.         private void OutputMemberVTableModifier(MemberAttributes attributes)
  1445.         {
  1446.             switch (attributes & MemberAttributes.VTableMask) {
  1447.                 case MemberAttributes.New:
  1448.                     Output.Write("hide ");
  1449.                     break;
  1450.             }
  1451.         }
  1452.        
  1453.         // Generates code for the specified CodeDom based parameter declaration expression representation.
  1454.         // 'parameters' indicates the parameter declaration expressions to generate code for.
  1455.         protected override void OutputParameters(CodeParameterDeclarationExpressionCollection parameters)
  1456.         {
  1457.             bool first = true;
  1458.             IEnumerator en = parameters.GetEnumerator();
  1459.             while (en.MoveNext()) {
  1460.                 CodeParameterDeclarationExpression current = (CodeParameterDeclarationExpression)en.Current;
  1461.                 if (first) {
  1462.                     first = false;
  1463.                 }
  1464.                 else {
  1465.                     Output.Write(", ");
  1466.                 }
  1467.                 GenerateExpression(current);
  1468.             }
  1469.         }
  1470.        
  1471.         private void OutputStartingBrace()
  1472.         {
  1473.             if (Options.BracingStyle == "C") {
  1474.                 Output.WriteLine("");
  1475.                 Output.WriteLine("{");
  1476.             }
  1477.             else {
  1478.                 Output.WriteLine(" {");
  1479.             }
  1480.         }
  1481.        
  1482.         // Generates code for the specified CodeDom based return type representation.
  1483.         // 'typeRef' indicates the return type to generate code for.
  1484.         protected override void OutputType(CodeTypeReference typeRef)
  1485.         {
  1486.             Output.Write(GetTypeOutput(typeRef));
  1487.         }
  1488.        
  1489.         protected override void OutputTypeAttributes(TypeAttributes attributes, bool isStruct, bool isEnum)
  1490.         {
  1491.             if (isEnum) {
  1492.                 Output.Write("enum ");
  1493.             }
  1494.             else {
  1495.                 switch (attributes & TypeAttributes.ClassSemanticsMask) {
  1496.                     case TypeAttributes.Class:
  1497.                         if ((attributes & TypeAttributes.Sealed) == TypeAttributes.Sealed)
  1498.                             Output.Write("final ");
  1499.                         if ((attributes & TypeAttributes.Abstract) == TypeAttributes.Abstract)
  1500.                             Output.Write("abstract ");
  1501.                         Output.Write("class ");
  1502.                         break;
  1503.                     case TypeAttributes.Interface:
  1504.                         Output.Write("interface ");
  1505.                         break;
  1506.                 }
  1507.             }
  1508.         }
  1509.        
  1510.         // Generates code for the specified CodeDom based type name pair representation.
  1511.         // 'typeRef' indicates the type to generate code for.
  1512.         // 'name' name to generate code for.
  1513.         //
  1514.         // remarks: This is commonly used for variable declarations.
  1515.         protected override void OutputTypeNamePair(CodeTypeReference typeRef, string name)
  1516.         {
  1517.             OutputIdentifier(name);
  1518.             Output.Write(" : ");
  1519.             OutputType(typeRef);
  1520.         }
  1521.        
  1522.         private void OutputTypeVisibility(TypeAttributes attributes)
  1523.         {
  1524.             switch (attributes & TypeAttributes.VisibilityMask) {
  1525.                 case TypeAttributes.NestedAssembly:
  1526.                 case TypeAttributes.NestedFamANDAssem:
  1527.                     Output.Write("internal static ");
  1528.                     break;
  1529.                 case TypeAttributes.NestedFamily:
  1530.                     Output.Write("protected static ");
  1531.                     break;
  1532.                 case TypeAttributes.NestedFamORAssem:
  1533.                     Output.Write("protected internal static ");
  1534.                     break;
  1535.                 case TypeAttributes.NotPublic:
  1536.                     Output.Write("internal ");
  1537.                     break;
  1538.                 case TypeAttributes.NestedPrivate:
  1539.                     Output.Write("private static ");
  1540.                     break;
  1541.                 case TypeAttributes.NestedPublic:
  1542.                     Output.Write("public static ");
  1543.                     break;
  1544.                 default:
  1545.                     Output.Write("public ");
  1546.                     break;
  1547.             }
  1548.         }
  1549.        
  1550.         protected override void ProcessCompilerOutputLine(CompilerResults results, string line)
  1551.         {
  1552.             Match m = outputReg.Match(line);
  1553.             if (m.Success) {
  1554.                 CompilerError ce = new CompilerError();
  1555.                 // The location is optional since the error can not always be traced to a file.
  1556.                 if (m.Groups[1].Success) {
  1557.                     ce.FileName = m.Groups[2].Value;
  1558.                     ce.Line = int.Parse(m.Groups[4].Value, CultureInfo.InvariantCulture);
  1559.                     ce.Column = int.Parse(m.Groups[5].Value, CultureInfo.InvariantCulture);
  1560.                 }
  1561.                 if (string.Compare(m.Groups[7].Value, "warning", StringComparison.OrdinalIgnoreCase) == 0) {
  1562.                     ce.IsWarning = true;
  1563.                 }
  1564.                 ce.ErrorNumber = m.Groups[8].Value;
  1565.                 ce.ErrorText = m.Groups[9].Value;
  1566.                
  1567.                 results.Errors.Add(ce);
  1568.             }
  1569.         }
  1570.        
  1571.         protected override string QuoteSnippetString(string value)
  1572.         {
  1573.             return QuoteSnippetStringCStyle(value);
  1574.         }
  1575.        
  1576.         // Provides conversion to C-style formatting with escape codes.
  1577.         private string QuoteSnippetStringCStyle(string value)
  1578.         {
  1579.             char[] chars = value.ToCharArray();
  1580.             StringBuilder b = new StringBuilder(value.Length + 5);
  1581.            
  1582.             b.Append("\"");
  1583.            
  1584.             int nextBreak = MaxLineLength;
  1585.             for (int i = 0; i < chars.Length; i++) {
  1586.                 switch (chars[i]) {
  1587.                     case '\r':
  1588.                         b.Append("\\r");
  1589.                         break;
  1590.                     case '\t':
  1591.                         b.Append("\\t");
  1592.                         break;
  1593.                     case '"':
  1594.                         b.Append("\\\"");
  1595.                         break;
  1596.                     case '\'':
  1597.                         b.Append("\\'");
  1598.                         break;
  1599.                     case '\\':
  1600.                         b.Append("\\\\");
  1601.                         break;
  1602.                     case '\0':
  1603.                         b.Append("\\0");
  1604.                         break;
  1605.                     case '\n':
  1606.                         b.Append("\\n");
  1607.                         break;
  1608.                     case '
':
  1609.                         b.Append("\\u2028");
  1610.                         break;
  1611.                     case '
':
  1612.                         b.Append("\\u2029");
  1613.                         break;
  1614.                     default:
  1615.                         b.Append(chars[i]);
  1616.                         break;
  1617.                 }
  1618.                
  1619.                 // Insert a newline but only if we've reached max line, there are more characters,
  1620.                 // length, and we're not in the middle of a surrogate pair.
  1621.                 if (i >= nextBreak && i + 1 < chars.Length && (!IsSurrogateStart(chars[i]) || !IsSurrogateEnd(chars[i + 1]))) {
  1622.                     nextBreak = i + MaxLineLength;
  1623.                     b.Append("\" + \r\n\"");
  1624.                 }
  1625.             }
  1626.            
  1627.             b.Append("\"");
  1628.            
  1629.             return b.ToString();
  1630.         }
  1631.        
  1632.         private bool IsSurrogateStart(char c)
  1633.         {
  1634.             return 55296 <= c && c <= 56319;
  1635.             // Is code point the start (high surrogate) of a surrogate pair?
  1636.         }
  1637.        
  1638.         private bool IsSurrogateEnd(char c)
  1639.         {
  1640.             return 56320 <= c && c <= 57343;
  1641.             // Is code point the end (i.e. low surrogate) of a surrogate pair?
  1642.         }
  1643.        
  1644.         protected override void GeneratePrimitiveExpression(CodePrimitiveExpression e)
  1645.         {
  1646.             if (null == e.Value) {
  1647.                 Output.Write("undefined");
  1648.             }
  1649.             else if (e.Value is System.DBNull) {
  1650.                 Output.Write("null");
  1651.             }
  1652.             else if (e.Value is char) {
  1653.                 GeneratePrimitiveChar((char)e.Value);
  1654.             }
  1655.             else {
  1656.                 base.GeneratePrimitiveExpression(e);
  1657.             }
  1658.         }
  1659.        
  1660.         private void GeneratePrimitiveChar(char c)
  1661.         {
  1662.             Output.Write('\'');
  1663.             switch (c) {
  1664.                 case '\r':
  1665.                     Output.Write("\\r");
  1666.                     break;
  1667.                 case '\t':
  1668.                     Output.Write("\\t");
  1669.                     break;
  1670.                 case '"':
  1671.                     Output.Write("\\\"");
  1672.                     break;
  1673.                 case '\'':
  1674.                     Output.Write("\\'");
  1675.                     break;
  1676.                 case '\\':
  1677.                     Output.Write("\\\\");
  1678.                     break;
  1679.                 case '\0':
  1680.                     Output.Write("\\0");
  1681.                     break;
  1682.                 case '\n':
  1683.                     Output.Write("\\n");
  1684.                     break;
  1685.                 case '
':
  1686.                     Output.Write("\\u2028");
  1687.                     break;
  1688.                 case '
':
  1689.                     Output.Write("\\u2029");
  1690.                     break;
  1691.                 default:
  1692.                     Output.Write(c);
  1693.                     break;
  1694.             }
  1695.             Output.Write('\'');
  1696.         }
  1697.        
  1698.        
  1699.         protected override bool Supports(GeneratorSupport support)
  1700.         {
  1701.             return ((support & LanguageSupport) == support);
  1702.         }
  1703.     }
  1704. }

Developer Fusion