2003-10-17 Rafael Teixeira <rafaelteixeirabr@hotmail.com>
[mono.git] / mcs / class / System / Microsoft.VisualBasic / VBCodeGenerator.cs
1 //
2 // Microsoft.VisualBasic.VBCodeGenerator.cs
3 //
4 // Author:
5 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
6 //   (partially based on CSharpCodeGenerator)
7 //
8 // (C) 2003 Andreas Nahr
9 //
10
11 using System;
12 using System.Text;
13 using System.Text.RegularExpressions;
14 using System.CodeDom;
15 using System.CodeDom.Compiler;
16 using System.IO;
17 using System.Reflection;
18 using System.Collections;
19
20 namespace Microsoft.VisualBasic
21 {
22         internal class VBCodeGenerator : CodeGenerator
23         {
24                 private string[] Keywords = new string[] {
25                         "AddHandler", "AddressOf", "Alias", "And",
26                         "AndAlso", "Ansi", "As", "Assembly",
27                         "Auto", "Boolean", "ByRef", "Byte", 
28                         "ByVal", "Call", "Case", "Catch", 
29                         "CBool", "CByte", "CChar", "CDate", 
30                         "CDec", "CDbl", "Char", "CInt", 
31                         "Class", "CLng", "CObj", "Const", 
32                         "CShort", "CSng", "CStr", "CType", 
33                         "Date", "Decimal", "Declare", "Default", 
34                         "Delegate", "Dim", "DirectCast", "Do", 
35                         "Double", "Each", "Else", "ElseIf", 
36                         "End", "Enum", "Erase", "Error", 
37                         "Event", "Exit", "False", "Finally", 
38                         "For", "Friend", "Function", "Get", 
39                         "GetType", "GoSub", "GoTo", "Handles", 
40                         "If", "Implements", "Imports", "In", 
41                         "Inherits", "Integer", "Interface", "Is", 
42                         "Let", "Lib", "Like", "Long", 
43                         "Loop", "Me", "Mod", "Module", 
44                         "MustInherit", "MustOverride", "MyBase", "MyClass", 
45                         "Namespace", "New", "Next", "Not", 
46                         "Nothing", "NotInheritable", "NotOverridable", "Object", 
47                         "On", "Option", "Optional", "Or", 
48                         "OrElse", "Overloads", "Overridable", "Overrides", 
49                         "ParamArray", "Preserve", "Private", "Property", 
50                         "Protected", "Public", "RaiseEvent", "ReadOnly", 
51                         "ReDim", "REM", "RemoveHandler", "Resume", 
52                         "Return", "Select", "Set", "Shadows", 
53                         "Shared", "Short", "Single", "Static", 
54                         "Step", "Stop", "String", "Structure", 
55                         "Sub", "SyncLock", "Then", "Throw", 
56                         "To", "True", "Try", "TypeOf", 
57                         "Unicode", "Until", "Variant", "When", 
58                         "While", "With", "WithEvents", "WriteOnly", 
59                         "Xor" 
60                 };
61
62                 public VBCodeGenerator()
63                 {
64                 }
65
66                 protected override string NullToken {
67                         get {
68                                 return "Nothing";
69                         }
70                 }
71
72                 protected override void GenerateArrayCreateExpression (CodeArrayCreateExpression expression)
73                 {
74                         TextWriter output = Output;
75
76                         output.Write ("New ");
77
78                         CodeExpressionCollection initializers = expression.Initializers;
79                         CodeTypeReference createType = expression.CreateType;
80
81                         if (initializers.Count > 0) {
82
83                                 OutputType (createType);
84                                 
85                                 output.WriteLine (" {");
86                                 ++Indent;
87                                 OutputExpressionList (initializers, true);
88                                 --Indent;
89                                 output.Write ("}");
90
91                         } 
92                         else {
93                                 CodeTypeReference arrayType = createType.ArrayElementType;
94                                 while (arrayType != null) 
95                                 {
96                                         createType = arrayType;
97                                         arrayType = arrayType.ArrayElementType;
98                                 }
99
100                                 OutputType (createType);
101
102                                 output.Write ('(');
103
104                                 CodeExpression size = expression.SizeExpression;
105                                 if (size != null)
106                                         GenerateExpression (size);
107                                 else
108                                         output.Write (expression.Size);
109
110                                 output.Write (')');
111                         }
112                 }
113
114                 protected override void GenerateBaseReferenceExpression (CodeBaseReferenceExpression expression)
115                 {
116                         Output.Write ("MyBase");
117                 }
118
119                 protected override void GenerateCastExpression (CodeCastExpression expression)
120                 {
121                         TextWriter output = Output;
122                         // ENHANCE: Use a DirectCast if it is known that expression.Expression is no Value-Type
123                         output.Write ("CType(");
124                         GenerateExpression (expression.Expression);
125                         output.Write (", ");
126                         OutputType (expression.TargetType);
127                         output.Write (")");
128                 }
129
130                 protected override void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
131                 {
132                         GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
133                         GenerateComment (new CodeComment (" <autogenerated>"));
134                         GenerateComment (new CodeComment ("     This code was generated by a tool."));
135                         GenerateComment (new CodeComment ("     Mono Runtime Version: " + System.Environment.Version));
136                         GenerateComment (new CodeComment (""));
137                         GenerateComment (new CodeComment ("     Changes to this file may cause incorrect behavior and will be lost if "));
138                         GenerateComment (new CodeComment ("     the code is regenerated."));
139                         GenerateComment (new CodeComment (" </autogenerated>"));
140                         GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
141                         Output.WriteLine ();
142                 }
143
144                 protected override void GenerateDelegateCreateExpression (CodeDelegateCreateExpression expression)
145                 {
146                         TextWriter output = Output;
147
148                         output.Write ("AddressOf ");
149
150                         CodeExpression targetObject = expression.TargetObject;
151                         if (targetObject != null) {
152                                 GenerateExpression (targetObject);
153                                 Output.Write ('.');
154                         }
155                         output.Write (expression.MethodName);
156                 }
157
158                 protected override void GenerateFieldReferenceExpression (CodeFieldReferenceExpression expression)
159                 {
160                         CodeExpression targetObject = expression.TargetObject;
161                         if (targetObject != null) {
162                                 GenerateExpression (targetObject);
163                                 Output.Write ('.');
164                         }
165                         Output.Write (expression.FieldName);
166                 }
167                 
168                 protected override void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression expression)
169                 {
170                         Output.Write (expression.ParameterName);
171                 }
172
173                 protected override void GenerateVariableReferenceExpression (CodeVariableReferenceExpression expression)
174                 {
175                         Output.Write (expression.VariableName);
176                 }
177                 
178                 protected override void GenerateIndexerExpression (CodeIndexerExpression expression)
179                 {
180                         TextWriter output = Output;
181
182                         GenerateExpression (expression.TargetObject);
183                         output.Write ('(');
184                         OutputExpressionList (expression.Indices);
185                         output.Write (')');
186                 }
187                 
188                 protected override void GenerateArrayIndexerExpression (CodeArrayIndexerExpression expression)
189                 {
190                         TextWriter output = Output;
191
192                         GenerateExpression (expression.TargetObject);
193                         output.Write (".Item(");
194                         OutputExpressionList (expression.Indices);
195                         output.Write (')');
196                 }
197                 
198                 protected override void GenerateSnippetExpression (CodeSnippetExpression expression)
199                 {
200                         Output.Write (expression.Value);
201                 }
202                 
203                 protected override void GenerateMethodInvokeExpression (CodeMethodInvokeExpression expression)
204                 {
205                         TextWriter output = Output;
206
207                         GenerateMethodReferenceExpression (expression.Method);
208
209                         output.Write ('(');
210                         OutputExpressionList (expression.Parameters);
211                         output.Write (')');
212                 }
213
214                 protected override void GenerateMethodReferenceExpression (CodeMethodReferenceExpression expression)
215                 {
216                         GenerateExpression (expression.TargetObject);
217                         Output.Write ('.');
218                         Output.Write (expression.MethodName);
219                 }
220
221                 protected override void GenerateEventReferenceExpression (CodeEventReferenceExpression expression)
222                 {
223                         GenerateExpression (expression.TargetObject);
224                         Output.Write ('.');
225                         Output.Write (expression.EventName);
226                 }
227
228                 protected override void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression expression)
229                 {
230                         Output.Write ("RaiseEvent ");
231                         GenerateExpression (expression.TargetObject);
232                         Output.Write ('(');
233                         OutputExpressionList (expression.Parameters);
234                         Output.WriteLine (')');
235                 }
236                 
237                 protected override void GenerateObjectCreateExpression (CodeObjectCreateExpression expression)
238                 {
239                         Output.Write( "New " );
240                         OutputType (expression.CreateType);
241                         Output.Write ('(');
242                         OutputExpressionList (expression.Parameters);
243                         Output.Write (')');
244                 }
245
246                 protected override void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
247                 {
248                         if (e.CustomAttributes != null && e.CustomAttributes.Count > 0)
249                                 OutputAttributeDeclarations (e.CustomAttributes);
250                         OutputDirection (e.Direction);
251                         OutputTypeNamePair (e.Type, e.Name);
252                 }
253
254                 protected override void GeneratePrimitiveExpression (CodePrimitiveExpression e)
255                 {
256                         TextWriter output = Output;
257
258                         if (e.Value == null) {
259                                 output.Write (NullToken);
260                                 return;
261                         }
262
263                         Type type = e.Value.GetType ();
264                         if (type == typeof (bool)) {
265                                 if ((bool)e.Value)
266                                         output.Write ("True");
267                                 else
268                                         output.Write ("False");
269                         } 
270                         else if (type == typeof (char)) {
271                                 output.Write ("\"" + e.Value.ToString () + "\"c");
272                         } 
273                         else if (type == typeof (string)) {
274                                 output.Write (QuoteSnippetString ((string) e.Value));
275                         } 
276                         else if (type == typeof (byte) || type == typeof (sbyte) || type == typeof (short) ||
277                                 type == typeof (int) || type == typeof (long) || type == typeof (float) ||
278                                 type == typeof (double) || type == typeof (decimal)) {
279                                 output.Write (e.Value.ToString ());
280                         } 
281                         else {
282                                 throw new ArgumentException ("Value type (" + type + ") is not a primitive type");
283                         }
284                 }
285
286                 protected override void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression expression)
287                 {
288                         GenerateMemberReferenceExpression (expression.TargetObject, expression.PropertyName);
289                 }
290
291                 protected override void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression expression)
292                 {
293                         Output.Write ("Value"); 
294                 }
295
296                 protected override void GenerateThisReferenceExpression (CodeThisReferenceExpression expression)
297                 {
298                         Output.Write ("Me");
299                 }
300
301                 protected override void GenerateExpressionStatement (CodeExpressionStatement statement)
302                 {
303                         GenerateExpression (statement.Expression);
304                         Output.WriteLine (); //start new line
305                 }
306
307                 protected override void GenerateIterationStatement (CodeIterationStatement statement)
308                 {
309                         TextWriter output = Output;
310
311                         GenerateStatement (statement.InitStatement);
312                         output.Write ("Do While ");
313                         GenerateExpression (statement.TestExpression);
314                         output.WriteLine ();
315                         GenerateStatements (statement.Statements);
316                         GenerateStatement (statement.IncrementStatement);
317                         output.WriteLine ("Loop");
318                 }
319
320                 protected override void GenerateThrowExceptionStatement (CodeThrowExceptionStatement statement)
321                 {
322                         Output.Write ("Throw ");
323                         GenerateExpression (statement.ToThrow);
324                 }
325
326                 protected override void GenerateComment (CodeComment comment)
327                 {
328                         TextWriter output = Output;
329
330                         if (comment.DocComment)
331                                 output.Write ("''' ");
332                         else
333                                 output.Write ("' ");
334
335                         output.WriteLine (comment.Text);
336                 }
337
338                 protected override void GenerateMethodReturnStatement (CodeMethodReturnStatement statement)
339                 {
340                         TextWriter output = Output;
341
342                         output.Write ("Return ");
343                         GenerateExpression (statement.Expression);
344                         output.WriteLine ();
345                 }
346
347                 protected override void GenerateConditionStatement (CodeConditionStatement statement)
348                 {
349                         TextWriter output = Output;
350                         output.Write ("If (");
351
352                         GenerateExpression (statement.Condition);
353
354                         output.WriteLine (") Then");
355                         ++Indent;
356                         GenerateStatements (statement.TrueStatements);
357                         --Indent;
358
359                         CodeStatementCollection falses = statement.FalseStatements;
360                         if (falses.Count > 0) {
361                                 output.WriteLine ("Else");
362                                 ++Indent;
363                                 GenerateStatements (falses);
364                                 --Indent;
365                         }
366                         else {
367                                 if (Options.ElseOnClosing)
368                                         output.WriteLine ("Else");
369                         }
370                         output.WriteLine ("End If");
371                 }
372
373                 protected override void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement statement)
374                 {
375                         TextWriter output = Output;
376                         CodeGeneratorOptions options = Options;
377
378                         output.WriteLine ("Try");
379                         ++Indent;
380                         GenerateStatements (statement.TryStatements);
381                         --Indent;
382                         output.WriteLine ();
383                         
384                         foreach (CodeCatchClause clause in statement.CatchClauses) {
385                                 output.Write ("Catch ");
386                                 OutputTypeNamePair (clause.CatchExceptionType, clause.LocalName);
387                                 output.WriteLine ();
388                                 ++Indent;
389                                 GenerateStatements (clause.Statements);
390                                 --Indent;
391                                 output.WriteLine ();
392                         }
393
394                         CodeStatementCollection finallies = statement.FinallyStatements;
395                         if (finallies.Count > 0) {
396
397                                 output.WriteLine ("Finally");
398                                 ++Indent;
399                                 GenerateStatements (finallies);
400                                 --Indent;
401                                 output.WriteLine ();
402                         }
403
404                         if (Options.ElseOnClosing) {
405                                 if (statement.CatchClauses.Count == 0)
406                                         output.WriteLine ("Catch");
407                                 if (statement.FinallyStatements.Count == 0)
408                                         output.WriteLine ("Finally");
409                         }
410
411                         output.WriteLine("End Try");
412                 }
413
414                 protected override void GenerateAssignStatement (CodeAssignStatement statement)
415                 {                       
416                         TextWriter output = Output;
417                         GenerateExpression (statement.Left);
418                         output.Write (" = ");
419                         GenerateExpression (statement.Right);
420                         output.WriteLine ();
421                 }
422
423                 protected override void GenerateAttachEventStatement (CodeAttachEventStatement statement)
424                 {
425                         TextWriter output = Output;
426
427                         Output.Write ("AddHandler ");
428                         GenerateEventReferenceExpression (statement.Event);
429                         Output.Write ( ", ");
430                         GenerateExpression (statement.Listener);
431                         output.WriteLine ();
432                 }
433
434                 protected override void GenerateRemoveEventStatement (CodeRemoveEventStatement statement)
435                 {
436                         TextWriter output = Output;
437
438                         Output.Write ("RemoveHandler ");
439                         GenerateEventReferenceExpression (statement.Event);
440                         Output.Write ( ", ");
441                         GenerateExpression (statement.Listener);
442                         output.WriteLine ();
443                 }
444
445                 protected override void GenerateGotoStatement (CodeGotoStatement statement)
446                 {
447                         TextWriter output = Output;
448
449                         output.Write ("Goto ");
450                         output.Write (statement.Label);
451                         output.WriteLine ();
452                 }
453                 
454                 protected override void GenerateLabeledStatement (CodeLabeledStatement statement)
455                 {
456                         TextWriter output = Output;
457
458                         output.Write (statement.Label + ":");
459                         GenerateStatement (statement.Statement);
460                 }
461
462                 protected override void GenerateTypeOfExpression (CodeTypeOfExpression e)
463                 {
464                         TextWriter output = Output;
465
466                         output.Write ("GetType(");
467                         OutputType (e.Type);
468                         output.Write (")");
469                 }
470
471                 protected override void GenerateVariableDeclarationStatement( CodeVariableDeclarationStatement statement )
472                 {
473                         TextWriter output = Output;
474
475                         output.Write ("Dim ");
476                         OutputTypeNamePair (statement.Type, statement.Name);
477
478                         CodeExpression initExpression = statement.InitExpression;
479                         if (initExpression != null) 
480                         {
481                                 output.Write (" = ");
482                                 GenerateExpression (initExpression);
483                         }
484
485                         output.WriteLine();
486                 }
487
488                 protected override void GenerateLinePragmaStart (CodeLinePragma linePragma)
489                 {
490                         Output.WriteLine ();
491                         Output.Write ("#ExternalSource(");
492                         Output.Write (linePragma.FileName);
493                         Output.Write (", ");
494                         Output.Write (linePragma.LineNumber);
495                         Output.WriteLine (")");
496                 }
497
498                 protected override void GenerateLinePragmaEnd (CodeLinePragma linePragma)
499                 {
500                         Output.WriteLine ("#End ExternalSource");
501                 }
502
503                 protected override void GenerateEvent (CodeMemberEvent eventRef, CodeTypeDeclaration declaration)
504                 {
505                         TextWriter output = Output;
506
507                         if (eventRef.CustomAttributes.Count > 0)
508                                 OutputAttributeDeclarations (eventRef.CustomAttributes);
509
510                         MemberAttributes attributes = eventRef.Attributes;
511
512                         OutputMemberAccessModifier (attributes);
513                         OutputMemberScopeModifier (attributes);
514
515                         output.Write ("Event ");
516                         OutputTypeNamePair (eventRef.Type, eventRef.Name);
517                         output.WriteLine ();
518                 }
519
520                 protected override void GenerateField (CodeMemberField field)
521                 {
522                         TextWriter output = Output;
523
524                         if (field.CustomAttributes.Count > 0)
525                                 OutputAttributeDeclarations (field.CustomAttributes);
526
527                         MemberAttributes attributes = field.Attributes;
528                         OutputMemberAccessModifier (attributes);
529                         OutputFieldScopeModifier (attributes);
530
531                         OutputTypeNamePair (field.Type, field.Name);
532
533                         CodeExpression initExpression = field.InitExpression;
534                         if (initExpression != null) {
535                                 output.Write (" = ");
536                                 GenerateExpression (initExpression);
537                         }
538
539                         output.WriteLine();
540                 }
541                 
542                 protected override void GenerateSnippetMember (CodeSnippetTypeMember member)
543                 {
544                         Output.Write (member.Text);
545                 }
546                 
547                 protected override void GenerateEntryPointMethod( CodeEntryPointMethod method, CodeTypeDeclaration declaration )
548                 {
549                         method.Name = "Main";
550                         GenerateMethod (method, declaration);
551                 }
552                 
553                 [MonoTODO ("partially implemented")]
554                 protected override void GenerateMethod (CodeMemberMethod method, CodeTypeDeclaration declaration)
555                 {
556                         bool isSub = method.ReturnType == null || method.ReturnType.ToString() == "System.Void";
557
558                         TextWriter output = Output;
559
560                         if (method.CustomAttributes.Count > 0)
561                                 OutputAttributeDeclarations (method.CustomAttributes);
562
563                         MemberAttributes attributes = method.Attributes;
564
565                         OutputMemberAccessModifier (attributes);
566                         OutputMemberScopeModifier (attributes);
567
568                         if (isSub)
569                                 output.Write ("Sub ");
570                         else
571                                 output.Write ("Function ");
572
573                         output.Write (method.Name);
574                         output.Write ('(');
575                         OutputParameters (method.Parameters);
576                         output.Write (')');
577
578                         if (!isSub) {
579                                 output.Write (" As ");
580                                 OutputType (method.ReturnType);
581                         }
582
583                         if (method.ImplementationTypes.Count > 0) {
584                                 output.Write (" Implements ");
585                                 foreach (CodeTypeReference type in method.ImplementationTypes)
586                                 {
587                                         OutputType (type);
588                                         output.Write ('.');
589                                         // TODO implementation incomplete
590
591                                 }
592                         }
593
594                         // TODO private implementations
595
596                         if ((attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract)
597                                 output.WriteLine ();
598                         else {
599                                 output.WriteLine ();
600                                 ++Indent;
601                                 GenerateStatements (method.Statements);
602                                 --Indent;
603                                 if (isSub)
604                                         output.WriteLine ("End Sub");
605                                 else
606                                         output.WriteLine ("End Function");
607                         }
608                 }
609
610                 protected override void GenerateProperty (CodeMemberProperty property, CodeTypeDeclaration declaration)
611                 {
612                         TextWriter output = Output;
613
614                         if (property.CustomAttributes.Count > 0)
615                                 OutputAttributeDeclarations (property.CustomAttributes);
616
617                         MemberAttributes attributes = property.Attributes;
618                         OutputMemberAccessModifier (attributes);
619                         OutputMemberScopeModifier (attributes);
620
621                         if (property.HasGet && (property.HasSet = false))
622                                 output.Write ("ReadOnly" );
623
624                         if (property.HasSet && (property.HasGet = false))
625                                 output.Write ("WriteOnly" );
626
627                         output.Write ("Property" );
628                         
629                         OutputTypeNamePair (property.Type, property.Name);
630                         output.WriteLine ();
631                         ++Indent;
632
633                         if (property.HasGet) {
634                                 output.WriteLine ("Get");
635                                 ++Indent;
636
637                                 GenerateStatements (property.GetStatements);
638
639                                 --Indent;
640                                 output.WriteLine ("End Get");
641                         }
642                         
643                         if (property.HasSet) {
644                                 output.WriteLine ("Set");
645                                 ++Indent;
646
647                                 GenerateStatements (property.SetStatements);
648
649                                 --Indent;
650                                 output.WriteLine ("End Set");
651                         }
652
653                         --Indent;
654                         output.WriteLine ("End Property");
655                 }
656
657                 [MonoTODO ("not implemented")]
658                 protected override void GenerateConstructor (CodeConstructor constructor, CodeTypeDeclaration declaration)
659                 {
660                         if (constructor.CustomAttributes.Count > 0)
661                                 OutputAttributeDeclarations (constructor.CustomAttributes);
662                         OutputMemberAccessModifier (constructor.Attributes);
663                         Output.Write ("Sub New(");
664                         OutputParameters (constructor.Parameters);
665                         Output.WriteLine (")");
666                         // Handle BaseConstructorArgs, ChainedConstructorArgs, ImplementationTypes
667                         Indent++;
668                         GenerateStatements (constructor.Statements);
669                         Indent--;
670                         Output.WriteLine ("End Sub");
671                 }
672                 
673                 protected override void GenerateTypeConstructor (CodeTypeConstructor constructor)
674                 {
675                         Output.WriteLine ("Shared Sub New()");
676                         Indent++;
677                         GenerateStatements (constructor.Statements);
678                         Indent--;
679                         Output.WriteLine ("End Sub");
680                 }
681
682                 [MonoTODO ("not implemented")]
683                 protected override void GenerateTypeStart (CodeTypeDeclaration declaration)
684                 {
685                         TextWriter output = Output;
686
687                         if (declaration.CustomAttributes.Count > 0)
688                                 OutputAttributeDeclarations (declaration.CustomAttributes);
689                         TypeAttributes attributes = declaration.TypeAttributes;
690                         OutputTypeAttributes (attributes,
691                                 declaration.IsStruct,
692                                 declaration.IsEnum);
693
694                         output.WriteLine (declaration.Name);
695
696                         ++Indent;
697                         
698                         IEnumerator enumerator = declaration.BaseTypes.GetEnumerator();
699                         if (enumerator.MoveNext()) 
700                         {
701                                 CodeTypeReference type = (CodeTypeReference)enumerator.Current;
702                         
703                                 if (type != null)
704                                 {
705                                         output.Write ("Inherits ");
706                                         OutputType (type);
707                                         output.WriteLine ();
708                                 }
709                                 
710                                 while (enumerator.MoveNext()) 
711                                 {
712                                         type = (CodeTypeReference)enumerator.Current;
713                                 
714                                         if (type != null)
715                                         {
716                                                 output.Write ("Implements ");
717                                                 OutputType (type);
718                                                 output.WriteLine ();
719                                         }
720                                 }
721                         }                       
722                 }
723
724                 protected override void GenerateTypeEnd (CodeTypeDeclaration declaration)
725                 {
726                         string output = string.Empty;
727
728                         --Indent;
729                         if (declaration.IsStruct)
730                                 output = "End Structure";
731                         if (declaration.IsInterface)
732                                 output = "End Interface";
733                         if (declaration.IsEnum)
734                                 output = "End Enum";
735                         if (declaration.IsClass)
736                                 output = "End Class";
737
738                         Output.WriteLine (output);
739                 }
740
741                 protected override void GenerateNamespaceStart (CodeNamespace ns)
742                 {
743                         TextWriter output = Output;
744                         
745                         string name = ns.Name;
746                         if (name != null && name != string.Empty) {
747                                 output.Write ("Namespace ");
748                                 output.WriteLine (name);
749                                 ++Indent;
750                         }
751                 }
752
753                 protected override void GenerateNamespaceEnd (CodeNamespace ns)
754                 {
755                         string name = ns.Name;
756                         if (name != null && name != string.Empty) {
757                                 --Indent;
758                                 Output.WriteLine ("End Namespace");
759                         }
760                 }
761
762                 protected override void GenerateNamespaceImport (CodeNamespaceImport import)
763                 {
764                         TextWriter output = Output;
765
766                         output.Write ("Imports ");
767                         output.Write (import.Namespace);
768                         output.WriteLine ();
769                 }
770                 
771                 protected override void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes)
772                 {
773                         Output.Write ('<');
774                 }
775                 
776                 protected override void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes)
777                 {
778                         Output.WriteLine ('>');
779                 }
780
781                 protected override void OutputDirection (FieldDirection direction)
782                 {
783                         switch (direction) {
784                         case FieldDirection.In:
785                                 //there is no "In"
786                                 break;
787                         case FieldDirection.Out:
788                                 Output.Write ("ByVal ");
789                                 break;
790                         case FieldDirection.Ref:
791                                 Output.Write ("ByRef ");
792                                 break;
793                         }
794                 }
795
796                 protected override void OutputFieldScopeModifier (MemberAttributes attributes)
797                 {
798                         if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
799                                 Output.Write ("New ");
800
801                         switch (attributes & MemberAttributes.ScopeMask) {
802                         case MemberAttributes.Static:
803                                 Output.Write ("Shared ");
804                                 break;
805                         case MemberAttributes.Const:
806                                 Output.Write ("Const ");
807                                 break;
808                         }
809                 }
810
811                 protected override void OutputMemberAccessModifier (MemberAttributes attributes)
812                 {
813                         switch (attributes & MemberAttributes.AccessMask) {
814                         case MemberAttributes.Assembly:
815                                 Output.Write ("Friend ");
816                                 break;
817                         case MemberAttributes.FamilyAndAssembly:
818                                 Output.Write ("Friend "); 
819                                 break;
820                         case MemberAttributes.Family:
821                                 Output.Write ("Protected ");
822                                 break;
823                         case MemberAttributes.FamilyOrAssembly:
824                                 Output.Write ("Protected Friend ");
825                                 break;
826                         case MemberAttributes.Private:
827                                 Output.Write ("Private ");
828                                 break;
829                         case MemberAttributes.Public:
830                                 Output.Write ("Public ");
831                                 break;
832                         }
833                 }
834
835                 protected override void OutputMemberScopeModifier (MemberAttributes attributes)
836                 {
837                         if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
838                                 Output.Write ("New ");
839
840                         switch (attributes & MemberAttributes.ScopeMask) {
841                         case MemberAttributes.Abstract:
842                                 Output.Write ("MustOverride ");
843                                 break;
844                         case MemberAttributes.Final:
845                                 Output.Write ("NotOverridable ");
846                                 break;
847                         case MemberAttributes.Static:
848                                 Output.Write ("Shared ");
849                                 break;
850                         case MemberAttributes.Override:
851                                 Output.Write ("Overrides ");
852                                 break;
853                         default:
854                                 //
855                                 // FUNNY! if the scope value is
856                                 // rubbish (0 or >Const), and access
857                                 // is public or protected, make it
858                                 // "virtual".
859                                 //
860                                 // i'm not sure whether this is 100%
861                                 // correct, but it seems to be MS
862                                 // behavior. 
863                                 //
864                                 MemberAttributes access = attributes & MemberAttributes.AccessMask;
865                                 if ( access == MemberAttributes.Public || 
866                                         access == MemberAttributes.Family )
867                                         Output.Write ("Overridable ");
868                                 break;
869                         }
870                 }
871
872                 protected override void OutputOperator (CodeBinaryOperatorType op)
873                 {
874                         switch (op) {
875                         case CodeBinaryOperatorType.Add:
876                                 Output.Write ("+");
877                                 break;
878                         case CodeBinaryOperatorType.Subtract:
879                                 Output.Write ("-");
880                                 break;
881                         case CodeBinaryOperatorType.Multiply:
882                                 Output.Write ("*");
883                                 break;
884                         case CodeBinaryOperatorType.Divide:
885                                 Output.Write ("/");
886                                 break;
887                         case CodeBinaryOperatorType.Modulus:
888                                 Output.Write ("Mod");
889                                 break;
890                         case CodeBinaryOperatorType.Assign:
891                                 Output.Write ("=");
892                                 break;
893                         case CodeBinaryOperatorType.IdentityInequality:
894                                 Output.Write ("<>");
895                                 break;
896                         case CodeBinaryOperatorType.IdentityEquality:
897                                 Output.Write ("Is");
898                                 break;
899                         case CodeBinaryOperatorType.ValueEquality:
900                                 Output.Write ("=");
901                                 break;
902                         case CodeBinaryOperatorType.BitwiseOr:
903                                 Output.Write ("Or");
904                                 break;
905                         case CodeBinaryOperatorType.BitwiseAnd:
906                                 Output.Write ("And");
907                                 break;
908                         case CodeBinaryOperatorType.BooleanOr:
909                                 Output.Write ("OrElse");
910                                 break;
911                         case CodeBinaryOperatorType.BooleanAnd:
912                                 Output.Write ("AndAlso");
913                                 break;
914                         case CodeBinaryOperatorType.LessThan:
915                                 Output.Write ("<");
916                                 break;
917                         case CodeBinaryOperatorType.LessThanOrEqual:
918                                 Output.Write ("<=");
919                                 break;
920                         case CodeBinaryOperatorType.GreaterThan:
921                                 Output.Write (">");
922                                 break;
923                         case CodeBinaryOperatorType.GreaterThanOrEqual:
924                                 Output.Write (">=");
925                                 break;
926                         }
927                 }
928
929                 protected override void OutputTypeAttributes (TypeAttributes attributes, bool isStruct, bool isEnum)
930                 {
931                         TextWriter output = Output;
932
933                         switch (attributes & TypeAttributes.VisibilityMask) {
934                         case TypeAttributes.NotPublic:
935                                 // Does this mean friend access?
936                                 output.Write ("Friend ");
937                                 break; 
938
939                         case TypeAttributes.Public:
940                         case TypeAttributes.NestedPublic:
941                                 output.Write ("Public ");
942                                 break;
943
944                         case TypeAttributes.NestedPrivate:
945                                 output.Write ("Private ");
946                                 break;
947                         case TypeAttributes.NestedAssembly:
948                                 output.Write ("Friend ");
949                                 break;
950                         case TypeAttributes.NestedFamily:
951                                 output.Write ("Protected ");
952                                 break;
953                         case TypeAttributes.NestedFamORAssem:
954                                 output.Write ("Protected Friend");
955                                 break;
956                         case TypeAttributes.NestedFamANDAssem:
957                                 output.Write ("Friend ");
958                                 break;
959                         }
960
961                         if (isStruct)
962                                 output.Write ("Structure ");
963
964                         else if (isEnum)
965                                 output.Write ("Enumeration ");
966
967                         else {
968                                 if ((attributes & TypeAttributes.Interface) != 0) 
969                                         output.Write ("Interface ");
970
971                                 else {
972                                         if ((attributes & TypeAttributes.Sealed) != 0)
973                                                 output.Write ("NotInheritable ");
974
975                                         if ((attributes & TypeAttributes.Abstract) != 0)
976                                                 output.Write ("MustInherit ");
977                                         
978                                         output.Write ("Class ");
979                                 }
980                         }
981                 }
982
983                 protected override void OutputTypeNamePair (CodeTypeReference typeRef, String name)
984                 {
985                         Output.Write (name + " As " + GetTypeOutput (typeRef));
986                 }
987
988                 protected override void OutputType (CodeTypeReference type)
989                 {
990                         Output.Write (GetTypeOutput (type));
991                 }
992
993                 [MonoTODO ("not implemented")]
994                 protected override string QuoteSnippetString (string value)
995                 {
996                         // FIXME: escape ASCII chars that are not code compatible (e.g. vbcrlf)
997                         return value;
998                 }
999
1000                 private void GenerateDeclaration (CodeTypeReference type, string name, CodeExpression initExpression)
1001                 {
1002                         TextWriter output = Output;
1003
1004                         OutputTypeNamePair (type, name);
1005
1006                         if (initExpression != null) {
1007                                 output.Write (" = ");
1008                                 GenerateExpression (initExpression);
1009                         }
1010
1011                         output.WriteLine ();
1012                 }
1013                 
1014                 private void GenerateMemberReferenceExpression (CodeExpression targetObject, string memberName)
1015                 {
1016                         GenerateExpression (targetObject);
1017                         Output.Write ('.');
1018                         Output.Write (memberName);
1019                 }
1020                         
1021                 /* 
1022                  * ICodeGenerator
1023                  */
1024
1025                 protected override string CreateEscapedIdentifier (string value)
1026                 {
1027                         for (int x = 0; x < Keywords.Length; x++)
1028                                 if (value.ToLower().Equals (Keywords[x].ToLower()))
1029                                         return "[" + value + "]";
1030                         return value;
1031                 }
1032
1033                 protected override string CreateValidIdentifier (string value)
1034                 {
1035                         for (int x = 0; x < Keywords.Length; x++)
1036                                 if (value.ToLower().Equals (Keywords[x].ToLower()))
1037                                         return "_" + value;
1038                         return value;
1039                 }
1040
1041                 protected override string GetTypeOutput (CodeTypeReference type)
1042                 {
1043                         string output;
1044                         CodeTypeReference arrayType;
1045
1046                         arrayType = type.ArrayElementType;
1047                         if (arrayType != null)
1048                                 output = GetTypeOutput (arrayType);
1049                         else { 
1050                                 switch (type.BaseType) {
1051
1052                                 case "System.Decimal":
1053                                         output = "Decimal";
1054                                         break;
1055                                 case "System.Double":
1056                                         output = "Double";
1057                                         break;
1058                                 case "System.Single":
1059                                         output = "Single";
1060                                         break;
1061                                 
1062                                 case "System.Byte":
1063                                         output = "Byte";
1064                                         break;
1065                                 case "System.SByte":
1066                                         output = "SByte";
1067                                         break;
1068                                 case "System.Int32":
1069                                         output = "Integer";
1070                                         break;
1071                                 case "System.UInt32":
1072                                         output = "UInt32";
1073                                         break;
1074                                 case "System.Int64":
1075                                         output = "Long";
1076                                         break;
1077                                 case "System.UInt64":
1078                                         output = "UInt64";
1079                                         break;
1080                                 case "System.Int16":
1081                                         output = "Short";
1082                                         break;
1083                                 case "System.UInt16":
1084                                         output = "UInt16";
1085                                         break;
1086
1087                                 case "System.Boolean":
1088                                         output = "Boolean";
1089                                         break;
1090                                 
1091                                 case "System.Char":
1092                                         output = "Char";
1093                                         break;
1094
1095                                 case "System.String":
1096                                         output = "String";
1097                                         break;
1098                                 case "System.Object":
1099                                         output = "Object";
1100                                         break;
1101
1102                                 case "System.Void":
1103                                         output = "Nothing";
1104                                         break;
1105
1106                                 default:
1107                                         output = type.BaseType;
1108                                         break;
1109                                 }
1110                         }
1111
1112                         int rank = type.ArrayRank;
1113                         if (rank > 0) {
1114                                 output += "(";
1115                                 for (--rank; rank > 0; --rank)
1116                                         output += ",";
1117                                 output += ")";
1118                         }
1119
1120                         return output;
1121                 }
1122
1123                 protected override bool IsValidIdentifier (string identifier)
1124                 {
1125                         for (int x = 0; x < Keywords.Length; x++)
1126                                 if (identifier.ToLower().Equals (Keywords[x].ToLower()))
1127                                         return false;
1128                         return true;
1129                 }
1130
1131                 protected override bool Supports (GeneratorSupport supports)
1132                 {
1133                         return true;
1134                 }
1135         }
1136 }