a2c815d0e621f4e5cf0c83bd1bc89772ca68b321
[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 : CodeCompiler
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 ('(');
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                         TextWriter output = Output;
557
558                         if (method.CustomAttributes.Count > 0)
559                                 OutputAttributeDeclarations (method.CustomAttributes);
560
561                         MemberAttributes attributes = method.Attributes;
562
563                         OutputMemberAccessModifier (attributes);
564                         OutputMemberScopeModifier (attributes);
565
566                         if (method.ReturnType == null)
567                                 output.Write ("Sub ");
568                         else
569                                 output.Write ("Function ");
570
571                         output.Write (method.Name);
572                         output.Write ('(');
573                         OutputParameters (method.Parameters);
574                         output.Write (')');
575
576                         if (method.ReturnType != null) {
577                                 output.Write (" As ");
578                                 OutputType (method.ReturnType);
579                         }
580
581                         if (method.ImplementationTypes.Count > 0) {
582                                 output.Write (" Implements ");
583                                 foreach (CodeTypeReference type in method.ImplementationTypes)
584                                 {
585                                         OutputType (type);
586                                         output.Write ('.');
587                                         // TODO implementation incomplete
588
589                                 }
590                         }
591
592                         // TODO private implementations
593
594                         if ((attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract)
595                                 output.WriteLine ();
596                         else {
597                                 output.WriteLine ();
598                                 ++Indent;
599                                 GenerateStatements (method.Statements);
600                                 --Indent;
601                                 if (method.ReturnType == null)
602                                         output.WriteLine ("End Sub");
603                                 else
604                                         output.WriteLine ("End Function");
605                         }
606                 }
607
608                 protected override void GenerateProperty (CodeMemberProperty property, CodeTypeDeclaration declaration)
609                 {
610                         TextWriter output = Output;
611
612                         if (property.CustomAttributes.Count > 0)
613                                 OutputAttributeDeclarations (property.CustomAttributes);
614
615                         MemberAttributes attributes = property.Attributes;
616                         OutputMemberAccessModifier (attributes);
617                         OutputMemberScopeModifier (attributes);
618
619                         if (property.HasGet && (property.HasSet = false))
620                                 output.Write ("ReadOnly" );
621
622                         if (property.HasSet && (property.HasGet = false))
623                                 output.Write ("WriteOnly" );
624
625                         output.Write ("Property" );
626                         
627                         OutputTypeNamePair (property.Type, property.Name);
628                         output.WriteLine ();
629                         ++Indent;
630
631                         if (property.HasGet) {
632                                 output.WriteLine ("Get");
633                                 ++Indent;
634
635                                 GenerateStatements (property.GetStatements);
636
637                                 --Indent;
638                                 output.WriteLine ("End Get");
639                         }
640                         
641                         if (property.HasSet) {
642                                 output.WriteLine ("Set");
643                                 ++Indent;
644
645                                 GenerateStatements (property.SetStatements);
646
647                                 --Indent;
648                                 output.WriteLine ("End Set");
649                         }
650
651                         --Indent;
652                         output.WriteLine ("End Property");
653                 }
654
655                 [MonoTODO ("not implemented")]
656                 protected override void GenerateConstructor (CodeConstructor constructor, CodeTypeDeclaration declaration)
657                 {
658                         if (constructor.CustomAttributes.Count > 0)
659                                 OutputAttributeDeclarations (constructor.CustomAttributes);
660                         OutputMemberAccessModifier (constructor.Attributes);
661                         Output.Write ("Sub New(");
662                         OutputParameters (constructor.Parameters);
663                         Output.WriteLine (")");
664                         // Handle BaseConstructorArgs, ChainedConstructorArgs, ImplementationTypes
665                         Indent++;
666                         GenerateStatements (constructor.Statements);
667                         Indent--;
668                         Output.WriteLine ("End Sub");
669                 }
670                 
671                 protected override void GenerateTypeConstructor (CodeTypeConstructor constructor)
672                 {
673                         Output.WriteLine ("Shared Sub New()");
674                         Indent++;
675                         GenerateStatements (constructor.Statements);
676                         Indent--;
677                         Output.WriteLine ("End Sub");
678                 }
679
680                 [MonoTODO ("not implemented")]
681                 protected override void GenerateTypeStart (CodeTypeDeclaration declaration)
682                 {
683                         TextWriter output = Output;
684
685                         if (declaration.CustomAttributes.Count > 0)
686                                 OutputAttributeDeclarations (declaration.CustomAttributes);
687                         TypeAttributes attributes = declaration.TypeAttributes;
688                         OutputTypeAttributes (attributes,
689                                 declaration.IsStruct,
690                                 declaration.IsEnum);
691
692                         output.WriteLine (declaration.Name);
693
694                         ++Indent;
695                         
696                         IEnumerator enumerator = declaration.BaseTypes.GetEnumerator();
697                         if (enumerator.MoveNext()) 
698                         {
699                                 CodeTypeReference type = (CodeTypeReference)enumerator.Current;
700                         
701                                 if (type != null)
702                                 {
703                                         output.Write ("Inherits ");
704                                         OutputType (type);
705                                         output.WriteLine ();
706                                 }
707                                 
708                                 while (enumerator.MoveNext()) 
709                                 {
710                                         type = (CodeTypeReference)enumerator.Current;
711                                 
712                                         if (type != null)
713                                         {
714                                                 output.Write ("Implements ");
715                                                 OutputType (type);
716                                                 output.WriteLine ();
717                                         }
718                                 }
719                         }                       
720                 }
721
722                 protected override void GenerateTypeEnd (CodeTypeDeclaration declaration)
723                 {
724                         string output = string.Empty;
725
726                         --Indent;
727                         if (declaration.IsStruct)
728                                 output = "End Structure";
729                         if (declaration.IsInterface)
730                                 output = "End Interface";
731                         if (declaration.IsEnum)
732                                 output = "End Enum";
733                         if (declaration.IsClass)
734                                 output = "End Class";
735
736                         Output.WriteLine (output);
737                 }
738
739                 protected override void GenerateNamespaceStart (CodeNamespace ns)
740                 {
741                         TextWriter output = Output;
742                         
743                         string name = ns.Name;
744                         if (name != null && name != string.Empty) {
745                                 output.Write ("Namespace ");
746                                 output.WriteLine (name);
747                                 ++Indent;
748                         }
749                 }
750
751                 protected override void GenerateNamespaceEnd (CodeNamespace ns)
752                 {
753                         string name = ns.Name;
754                         if (name != null && name != string.Empty) {
755                                 --Indent;
756                                 Output.WriteLine ("End Namespace");
757                         }
758                 }
759
760                 protected override void GenerateNamespaceImport (CodeNamespaceImport import)
761                 {
762                         TextWriter output = Output;
763
764                         output.Write ("Imports ");
765                         output.Write (import.Namespace);
766                         output.WriteLine ();
767                 }
768                 
769                 protected override void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes)
770                 {
771                         Output.Write ('<');
772                 }
773                 
774                 protected override void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes)
775                 {
776                         Output.WriteLine ('>');
777                 }
778
779                 protected override void OutputDirection (FieldDirection direction)
780                 {
781                         switch (direction) {
782                         case FieldDirection.In:
783                                 //there is no "In"
784                                 break;
785                         case FieldDirection.Out:
786                                 Output.Write ("ByVal ");
787                                 break;
788                         case FieldDirection.Ref:
789                                 Output.Write ("ByRef ");
790                                 break;
791                         }
792                 }
793
794                 protected override void OutputFieldScopeModifier (MemberAttributes attributes)
795                 {
796                         if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
797                                 Output.Write ("New ");
798
799                         switch (attributes & MemberAttributes.ScopeMask) {
800                         case MemberAttributes.Static:
801                                 Output.Write ("Shared ");
802                                 break;
803                         case MemberAttributes.Const:
804                                 Output.Write ("Const ");
805                                 break;
806                         }
807                 }
808
809                 protected override void OutputMemberAccessModifier (MemberAttributes attributes)
810                 {
811                         switch (attributes & MemberAttributes.AccessMask) {
812                         case MemberAttributes.Assembly:
813                                 Output.Write ("Friend ");
814                                 break;
815                         case MemberAttributes.FamilyAndAssembly:
816                                 Output.Write ("Friend "); 
817                                 break;
818                         case MemberAttributes.Family:
819                                 Output.Write ("Protected ");
820                                 break;
821                         case MemberAttributes.FamilyOrAssembly:
822                                 Output.Write ("Protected Friend ");
823                                 break;
824                         case MemberAttributes.Private:
825                                 Output.Write ("Private ");
826                                 break;
827                         case MemberAttributes.Public:
828                                 Output.Write ("Public ");
829                                 break;
830                         }
831                 }
832
833                 protected override void OutputMemberScopeModifier (MemberAttributes attributes)
834                 {
835                         if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
836                                 Output.Write ("New ");
837
838                         switch (attributes & MemberAttributes.ScopeMask) {
839                         case MemberAttributes.Abstract:
840                                 Output.Write ("MustOverride ");
841                                 break;
842                         case MemberAttributes.Final:
843                                 Output.Write ("NotOverridable ");
844                                 break;
845                         case MemberAttributes.Static:
846                                 Output.Write ("Shared ");
847                                 break;
848                         case MemberAttributes.Override:
849                                 Output.Write ("Overrides ");
850                                 break;
851                         default:
852                                 //
853                                 // FUNNY! if the scope value is
854                                 // rubbish (0 or >Const), and access
855                                 // is public or protected, make it
856                                 // "virtual".
857                                 //
858                                 // i'm not sure whether this is 100%
859                                 // correct, but it seems to be MS
860                                 // behavior. 
861                                 //
862                                 MemberAttributes access = attributes & MemberAttributes.AccessMask;
863                                 if ( access == MemberAttributes.Public || 
864                                         access == MemberAttributes.Family )
865                                         Output.Write ("Overridable ");
866                                 break;
867                         }
868                 }
869
870                 protected override void OutputOperator (CodeBinaryOperatorType op)
871                 {
872                         switch (op) {
873                         case CodeBinaryOperatorType.Add:
874                                 Output.Write ("+");
875                                 break;
876                         case CodeBinaryOperatorType.Subtract:
877                                 Output.Write ("-");
878                                 break;
879                         case CodeBinaryOperatorType.Multiply:
880                                 Output.Write ("*");
881                                 break;
882                         case CodeBinaryOperatorType.Divide:
883                                 Output.Write ("/");
884                                 break;
885                         case CodeBinaryOperatorType.Modulus:
886                                 Output.Write ("Mod");
887                                 break;
888                         case CodeBinaryOperatorType.Assign:
889                                 Output.Write ("=");
890                                 break;
891                         case CodeBinaryOperatorType.IdentityInequality:
892                                 Output.Write ("<>");
893                                 break;
894                         case CodeBinaryOperatorType.IdentityEquality:
895                                 Output.Write ("Is");
896                                 break;
897                         case CodeBinaryOperatorType.ValueEquality:
898                                 Output.Write ("=");
899                                 break;
900                         case CodeBinaryOperatorType.BitwiseOr:
901                                 Output.Write ("Or");
902                                 break;
903                         case CodeBinaryOperatorType.BitwiseAnd:
904                                 Output.Write ("And");
905                                 break;
906                         case CodeBinaryOperatorType.BooleanOr:
907                                 Output.Write ("OrElse");
908                                 break;
909                         case CodeBinaryOperatorType.BooleanAnd:
910                                 Output.Write ("AndAlso");
911                                 break;
912                         case CodeBinaryOperatorType.LessThan:
913                                 Output.Write ("<");
914                                 break;
915                         case CodeBinaryOperatorType.LessThanOrEqual:
916                                 Output.Write ("<=");
917                                 break;
918                         case CodeBinaryOperatorType.GreaterThan:
919                                 Output.Write (">");
920                                 break;
921                         case CodeBinaryOperatorType.GreaterThanOrEqual:
922                                 Output.Write (">=");
923                                 break;
924                         }
925                 }
926
927                 protected override void OutputTypeAttributes (TypeAttributes attributes, bool isStruct, bool isEnum)
928                 {
929                         TextWriter output = Output;
930
931                         switch (attributes & TypeAttributes.VisibilityMask) {
932                         case TypeAttributes.NotPublic:
933                                 // Does this mean friend access?
934                                 output.Write ("Friend ");
935                                 break; 
936
937                         case TypeAttributes.Public:
938                         case TypeAttributes.NestedPublic:
939                                 output.Write ("Public ");
940                                 break;
941
942                         case TypeAttributes.NestedPrivate:
943                                 output.Write ("Private ");
944                                 break;
945                         case TypeAttributes.NestedAssembly:
946                                 output.Write ("Friend ");
947                                 break;
948                         case TypeAttributes.NestedFamily:
949                                 output.Write ("Protected ");
950                                 break;
951                         case TypeAttributes.NestedFamORAssem:
952                                 output.Write ("Protected Friend");
953                                 break;
954                         case TypeAttributes.NestedFamANDAssem:
955                                 output.Write ("Friend ");
956                                 break;
957                         }
958
959                         if (isStruct)
960                                 output.Write ("Structure ");
961
962                         else if (isEnum)
963                                 output.Write ("Enumeration ");
964
965                         else {
966                                 if ((attributes & TypeAttributes.Interface) != 0) 
967                                         output.Write ("Interface ");
968
969                                 else {
970                                         if ((attributes & TypeAttributes.Sealed) != 0)
971                                                 output.Write ("NotInheritable ");
972
973                                         if ((attributes & TypeAttributes.Abstract) != 0)
974                                                 output.Write ("MustInherit ");
975                                         
976                                         output.Write ("Class ");
977                                 }
978                         }
979                 }
980
981                 protected override void OutputTypeNamePair (CodeTypeReference typeRef, String name)
982                 {
983                         Output.Write (name + " As " + GetTypeOutput (typeRef));
984                 }
985
986                 protected override void OutputType (CodeTypeReference type)
987                 {
988                         Output.Write (GetTypeOutput (type));
989                 }
990
991                 [MonoTODO ("not implemented")]
992                 protected override string QuoteSnippetString (string value)
993                 {
994                         // FIXME: escape ASCII chars that are not code compatible (e.g. vbcrlf)
995                         return value;
996                 }
997
998                 private void GenerateDeclaration (CodeTypeReference type, string name, CodeExpression initExpression)
999                 {
1000                         TextWriter output = Output;
1001
1002                         OutputTypeNamePair (type, name);
1003
1004                         if (initExpression != null) {
1005                                 output.Write (" = ");
1006                                 GenerateExpression (initExpression);
1007                         }
1008
1009                         output.WriteLine ();
1010                 }
1011                 
1012                 private void GenerateMemberReferenceExpression (CodeExpression targetObject, string memberName)
1013                 {
1014                         GenerateExpression (targetObject);
1015                         Output.Write ('.');
1016                         Output.Write (memberName);
1017                 }
1018                         
1019                 /* 
1020                  * ICodeGenerator
1021                  */
1022
1023                 protected override string CreateEscapedIdentifier (string value)
1024                 {
1025                         for (int x = 0; x < Keywords.Length; x++)
1026                                 if (value.ToLower().Equals (Keywords[x].ToLower()))
1027                                         return "[" + value + "]";
1028                         return value;
1029                 }
1030
1031                 protected override string CreateValidIdentifier (string value)
1032                 {
1033                         for (int x = 0; x < Keywords.Length; x++)
1034                                 if (value.ToLower().Equals (Keywords[x].ToLower()))
1035                                         return "_" + value;
1036                         return value;
1037                 }
1038
1039                 protected override string GetTypeOutput (CodeTypeReference type)
1040                 {
1041                         string output;
1042                         CodeTypeReference arrayType;
1043
1044                         arrayType = type.ArrayElementType;
1045                         if (arrayType != null)
1046                                 output = GetTypeOutput (arrayType);
1047                         else { 
1048                                 switch (type.BaseType) {
1049
1050                                 case "System.Decimal":
1051                                         output = "Decimal";
1052                                         break;
1053                                 case "System.Double":
1054                                         output = "Double";
1055                                         break;
1056                                 case "System.Single":
1057                                         output = "Single";
1058                                         break;
1059                                 
1060                                 case "System.Byte":
1061                                         output = "Byte";
1062                                         break;
1063                                 case "System.SByte":
1064                                         output = "SByte";
1065                                         break;
1066                                 case "System.Int32":
1067                                         output = "Integer";
1068                                         break;
1069                                 case "System.UInt32":
1070                                         output = "UInt32";
1071                                         break;
1072                                 case "System.Int64":
1073                                         output = "Long";
1074                                         break;
1075                                 case "System.UInt64":
1076                                         output = "UInt64";
1077                                         break;
1078                                 case "System.Int16":
1079                                         output = "Short";
1080                                         break;
1081                                 case "System.UInt16":
1082                                         output = "UInt16";
1083                                         break;
1084
1085                                 case "System.Boolean":
1086                                         output = "Boolean";
1087                                         break;
1088                                 
1089                                 case "System.Char":
1090                                         output = "Char";
1091                                         break;
1092
1093                                 case "System.String":
1094                                         output = "String";
1095                                         break;
1096                                 case "System.Object":
1097                                         output = "Object";
1098                                         break;
1099
1100                                 case "System.Void":
1101                                         output = "Nothing";
1102                                         break;
1103
1104                                 default:
1105                                         output = type.BaseType;
1106                                         break;
1107                                 }
1108                         }
1109
1110                         int rank = type.ArrayRank;
1111                         if (rank > 0) {
1112                                 output += "(";
1113                                 for (--rank; rank > 0; --rank)
1114                                         output += ",";
1115                                 output += ")";
1116                         }
1117
1118                         return output;
1119                 }
1120
1121                 protected override bool IsValidIdentifier (string identifier)
1122                 {
1123                         for (int x = 0; x < Keywords.Length; x++)
1124                                 if (identifier.ToLower().Equals (Keywords[x].ToLower()))
1125                                         return false;
1126                         return true;
1127                 }
1128
1129                 protected override bool Supports (GeneratorSupport supports)
1130                 {
1131                         return true;
1132                 }
1133
1134                 protected override string CompilerName {
1135                         get {
1136                                 return "mbas.exe";
1137                         }
1138                 }
1139
1140                 protected override string FileExtension {
1141                         get {
1142                                 return "vb";
1143                         }
1144                 }
1145
1146                 [MonoTODO ("check")]
1147                 protected override string CmdArgsFromParameters (CompilerParameters options)
1148                 {
1149                         //FIXME correct this agains mbas parameters if parameters are complete
1150                         StringBuilder args = new StringBuilder();
1151                         if (options.GenerateExecutable)
1152                                 args.Append ("/target:exe ");
1153                         else
1154                                 args.Append ("/target:library ");
1155
1156                         if (options.IncludeDebugInformation)
1157                                 args.Append ("/debug ");
1158
1159                         if (options.TreatWarningsAsErrors)
1160                                 args.Append ("/warnaserror ");
1161                         args.AppendFormat ("/warn:{0} ", options.WarningLevel);
1162                         if (options.OutputAssembly == null)
1163                                 options.OutputAssembly = Path.ChangeExtension (Path.GetTempFileName(), "dll");
1164
1165                         args.AppendFormat ("/out:'{0}' ", options.OutputAssembly);
1166
1167                         if (null != options.ReferencedAssemblies) {
1168                                 foreach (string import in options.ReferencedAssemblies)
1169                                         args.AppendFormat ("/r:'{0}' ", import);
1170                         }
1171
1172                         if (options.Win32Resource != null)
1173                                 args.AppendFormat ("/Win32Resource:{0} ", options.Win32Resource);
1174
1175                         foreach (string source in options.TempFiles)
1176                                 args.AppendFormat ("'{0}' ", source);
1177
1178                         return args.ToString();
1179                 }
1180
1181                 [MonoTODO ("check")]
1182                 protected override void ProcessCompilerOutputLine (CompilerResults results, string line)
1183                 {
1184                         CompilerError error = new CompilerError();
1185                         //FIXME check this Regex against mbas compiler if the output there is complete
1186                         Regex reg = new Regex (@"^(\s*(?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)\s+)*(?<level>\w+)\s*(?<number>.*):\s(?<message>.*)",
1187                                 RegexOptions.Compiled | RegexOptions.ExplicitCapture);
1188                         Match match = reg.Match (line);
1189                         if (!match.Success) {
1190                                 return;
1191                         }
1192                         if (String.Empty != match.Result ("${file}"))
1193                                 error.FileName = match.Result ("${file}");
1194                         if (String.Empty != match.Result ("${line}"))
1195                                 error.Line = Int32.Parse (match.Result ("${line}"));
1196                         if (String.Empty != match.Result ("${column}"))
1197                                 error.Column = Int32.Parse (match.Result ("${column}"));
1198                         if (match.Result ("${level}") == "warning")
1199                                 error.IsWarning=true;
1200                         error.ErrorNumber = match.Result ("${number}");
1201                         error.ErrorText = match.Result ("${message}");
1202
1203                         results.Errors.Add (error);
1204                         return;
1205                 }
1206         }
1207 }