ecore.cs : Added support for Implicit numeric conversions
[mono.git] / mcs / mbas / driver.cs
1 //
2 // driver.cs: The compiler command line driver.
3 //
4 // Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)
5 // Based on mcs by : Miguel de Icaza (miguel@gnu.org)
6 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // (C) 2002, 2003, 2004 Rafael Teixeira
10 //
11
12 namespace Mono.Languages {
13
14         using System;
15         using System.Collections;
16         using System.Diagnostics;
17         using System.IO;
18         using System.Globalization;
19         using System.Reflection;
20         using System.Reflection.Emit;
21
22         using Mono.MonoBASIC;
23         using Mono.GetOptions;
24
25         enum Target {
26                 Library, Exe, Module, WinExe
27         };
28         
29         enum OptionCompare {
30                 Binary, Text
31         };
32         
33         /// <summary>
34         ///    The compiler driver.
35         /// </summary>
36         public class Driver : Options {
37                 // Temporary options
38                 //------------------------------------------------------------------
39                 [Option("[Mono] Only parses the source file (for debugging the tokenizer)", "parse")]
40                 public bool parse_only = false;
41
42                 [Option("[Mono] Only tokenizes source files")]
43                 public bool tokenize = false;
44
45                 [Option("[Mono] Shows stack trace at Error location")]
46                 public bool stacktrace { set { Report.Stacktrace = value; } }
47
48                 [Option("[Mono] Displays time stamps of various compiler events")]
49                 public bool timestamp {
50                         set
51                         {
52                                 timestamps = true;
53                                 last_time = DateTime.Now;
54                                 debug_arglist.Add("timestamp");
55                         }
56                 }
57
58                 // Mono-specific options
59                 //------------------------------------------------------------------
60                 [Option("About the MonoBASIC compiler", "about")]
61                 public override WhatToDoNext DoAbout()
62                 {
63                         return base.DoAbout();
64                 }
65
66                 [Option(-1, "[Mono] References packages listed. {packagelist}=package,...", "pkg")]
67                 public WhatToDoNext ReferenceSomePackage(string packageName)
68                 {
69                         return ReferencePackage(packageName)?WhatToDoNext.GoAhead:WhatToDoNext.AbandonProgram;
70                 }
71
72                 [Option("[Mono] Don\'t assume the standard library", "nostdlib")]
73                 public bool NoStandardLibraries { set { RootContext.StdLib = !value; } }
74
75                 [Option("[Mono] Disables implicit references to assemblies", "noconfig")]
76                 public bool NoConfig { set { load_default_config = !value; } }
77
78                 [Option("[Mono] Allows unsafe code", "unsafe")]
79                 public bool AllowUnsafeCode { set { RootContext.Unsafe = value; } }
80
81                 [Option("[Mono] Debugger {arguments}", "debug-args")]
82                 public WhatToDoNext SetDebugArgs(string args)
83                 {
84                         debug_arglist.AddRange (args.Split(','));
85                         return WhatToDoNext.GoAhead;
86                 }
87
88                 [Option("[Mono] Ignores warning number {XXXX}", "ignorewarn")]
89                 public WhatToDoNext SetIgnoreWarning(int warn)
90                 {
91                         Report.SetIgnoreWarning(warn);
92                         return WhatToDoNext.GoAhead;
93                 }       
94
95                 [Option("[Mono] Sets warning {level} (the highest is 4, the default)", "wlevel")]
96                 public int WarningLevel { set { RootContext.WarningLevel = value; } }
97
98                 [Option("[Mono] Makes errors fatal", "fatal")]
99                 public bool Fatal { set { Report.Fatal = value; } }
100
101                 // Output file options
102                 //------------------------------------------------------------------
103                 [Option("Specifies the output {file} name", 'o', "out")]
104                 public string OutputFileName = null;
105
106                 [Option("Specifies the target {type} for the output file (exe [default], winexe, library, module)", 't', "target")]
107                 public WhatToDoNext SetTarget(string type)
108                 {
109                         switch (type.ToLower()) {
110                                 case "library":
111                                         target = Target.Library;
112                                         target_ext = ".dll";
113                                         break;
114                                                         
115                                 case "exe":
116                                         target = Target.Exe;
117                                         target_ext = ".exe";
118                                         break;
119                                                         
120                                 case "winexe":
121                                         target = Target.WinExe;
122                                         target_ext = ".exe";
123                                         break;
124                                                         
125                                 case "module":
126                                         target = Target.Module;
127                                         target_ext = ".netmodule";
128                                         break;
129                         }
130                         return WhatToDoNext.GoAhead;
131                 }
132
133                 // input file options
134                 //------------------------------------------------------------------
135                 public ArrayList AddedModules = new ArrayList();
136
137                 [Option(-1, "References metadata from specified {module}", "addmodule")]
138                 public string AddedModule { set { AddedModules.Add(value); } }
139
140 //              [Option("[NOT IMPLEMENTED YET]Include all files in the current directory and subdirectories according to the {wildcard}", "recurse")]
141                 public WhatToDoNext Recurse(string wildcard)
142                 {
143                         //AddFiles (DirName, true); // TODO wrong semantics
144                         return WhatToDoNext.GoAhead;
145                 }
146
147                 [Option(-1, "References metadata from the specified {assembly}", 'r', "reference")]
148                 public string AddedReference { set { references.Add(value); } }
149                 
150                 // support for the Compact Framework
151                 //------------------------------------------------------------------
152 //              [Option("[NOT IMPLEMENTED YET]Sets the compiler to target the Compact Framework","netcf")]
153                 public bool CompileForCompactFramework = false;
154                 
155 //              [Option("[NOT IMPLEMENTED YET]Specifies the {path} to the location of mscorlib.dll and microsoft.visualbasic.dll", "sdkpath")]
156                 public string SDKPath = null;
157
158                 // resource options
159                 //------------------------------------------------------------------
160                 public ArrayList EmbeddedResources = new ArrayList();
161                 
162                 [Option(-1, "Adds the specified {file} as an embedded assembly resource", "resource", "res")]
163                 public string AddedResource { set { EmbeddedResources.Add(value); } }
164
165                 public ArrayList LinkedResources = new ArrayList();
166                 
167 //              [Option(-1, "[NOT IMPLEMENTED YET]Adds the specified {file} as a linked assembly resource", "linkresource", "linkres")]
168                 public string AddedLinkresource { set { LinkedResources.Add(value); } }
169
170                 public ArrayList Win32Resources = new ArrayList();
171                 
172 //              [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 resource {file} (.res)", "win32resource")]
173                 public string AddedWin32resource { set { Win32Resources.Add(value); } }
174
175                 public ArrayList Win32Icons = new ArrayList();
176                 
177 //              [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 icon {file} (.ico) for the default Win32 resources", "win32icon")]
178                 public string AddedWin32icon { set { Win32Icons.Add(value); } }
179
180                 // code generation options
181                 //------------------------------------------------------------------
182 //              [Option("[NOT IMPLEMENTED YET]Enable optimizations", "optimize")]
183                 public bool optimize = false;
184
185                 // TODO: handle VB.NET [+|-] boolean syntax
186                 [Option("Remove integer checks. Default off.")]
187                 public bool removeintchecks { set { RootContext.Checked = !value; } }
188
189                 // TODO: handle VB.NET [+|-] boolean syntax
190                 [Option("Emit debugging information", 'g', "debug")]
191                 public bool want_debugging_support = false;
192
193                 [Option("Emit full debugging information (default)", "debug:full")]
194                 public bool fullDebugging = false;
195
196                 [Option("[IGNORED] Emit PDB file only", "debug:pdbonly")]
197                 public bool pdbOnly = false;
198
199                 // errors and warnings options
200                 //------------------------------------------------------------------
201                 [Option("Treat warnings as errors", "warnaserror")]
202                 public bool WarningsAreErrors { set { Report.WarningsAreErrors = value; } }
203
204                 [Option("Disable warnings", "nowarn")]
205                 public bool NoWarnings { set { if (value) RootContext.WarningLevel = 0; } }
206
207
208                 // language options
209                 //------------------------------------------------------------------
210                 public Hashtable Defines = new Hashtable();
211                 
212                 [Option(-1, "Declares global conditional compilation symbol(s). {symbol-list}:name=value,...", 'd', "define")]
213                 public string define { 
214                         set 
215                         {
216                                 foreach(string item in value.Split(','))  {
217                                         string[] dados = item.Split('=');
218                                         try {
219                                                 if (dados.Length > 1)
220                                                         Defines.Add(dados[0], dados[1]); 
221                                                 else
222                                                         Defines.Add(dados[0], string.Empty);
223                                         }
224                                         catch  {
225                                                 Error ("Could not define symbol" + dados[0]);
226                                         }
227                                 }
228                         } 
229                 }
230                 
231                 [Option(-1, "Declare global Imports for namespaces in referenced metadata files. {import-list}:namespace,...", "imports")]
232                 public WhatToDoNext imports(string import)
233                 {
234                         Mono.MonoBASIC.Parser.ImportsList.Add(import);
235                         return WhatToDoNext.GoAhead;
236                 }
237
238                 // TODO: handle VB.NET [+|-] boolean syntax
239 //              [Option("[NOT IMPLEMENTED YET]Require explicit declaration of variables")]
240                 public bool optionexplicit { set { Mono.MonoBASIC.Parser.InitialOptionExplicit = value; } }
241
242                 // TODO: handle VB.NET [+|-] boolean syntax
243 //              [Option("[NOT IMPLEMENTED YET]Enforce strict language semantics")]
244                 public bool optionstrict { set { Mono.MonoBASIC.Parser.InitialOptionStrict = value; } }
245                 
246 //              [Option("[NOT IMPLEMENTED YET]Specifies binary-style string comparisons. This is the default", "optioncompare:binary")]
247                 public bool optioncomparebinary { set { Mono.MonoBASIC.Parser.InitialOptionCompareBinary = true; } }
248
249 //              [Option("[NOT IMPLEMENTED YET]Specifies text-style string comparisons.", "optioncompare:text")]
250                 public bool optioncomparetext { set { Mono.MonoBASIC.Parser.InitialOptionCompareBinary = false; } }
251
252                 [Option("Specifies de root {namespace} for all type declarations")]
253                 public string rootnamespace { set { RootContext.RootNamespace = value; } }
254                 
255                 // Miscellaneous options        
256                 //------------------------------------------------------------------
257                 
258                 [Option("[IGNORED] Do not display compiler copyright banner")]
259                 public bool nologo = false;
260                 
261                 [Option("[Mono] Quiet output mode", 'q')]
262                 public bool quiet = false;
263                 
264                 // TODO: semantics are different and should be adjusted
265                 [Option("Display verbose messages", 'v')] 
266                 public bool verbose     { set { GenericParser.yacc_verbose_flag = value ? 1 : 0; } }
267
268                 // Advanced options     
269                 //------------------------------------------------------------------
270                 // TODO: force option to accept number in hex format
271 //              [Option("[NOT IMPLEMENTED YET]The base {address} for a library or module (hex)")]
272                 public int baseaddress;
273                 
274 //              [Option("[NOT IMPLEMENTED YET]Create bug report {file}")]
275                 public string bugreport;
276                 
277                 // TODO: handle VB.NET [+|-] boolean syntax
278 //              [Option("[NOT IMPLEMENTED YET]Delay-sign the assembly using only the public portion of the strong name key")]
279                 public bool delaysign;
280                 
281 //              [Option("[NOT IMPLEMENTED YET]Specifies a strong name key {container}")]
282                 public string keycontainer;
283                 
284 //              [Option("[NOT IMPLEMENTED YET]Specifies a strong name key {file}")]
285                 public string keyfile;
286
287                 public string[] libpath = null;
288                 
289                 [Option("List of directories to search for metadata references {path-list}:path;...", "libpath")]
290                 public WhatToDoNext setlibpath(string pathlist)
291                 {
292                         libpath = pathlist.Split(';');
293                         return WhatToDoNext.GoAhead;
294                 }
295
296                 [Option("Specifies the {name} of the Class or Module that contains Sub Main or inherits from System.Windows.Forms.Form.",
297                         'm', "main")]
298                 public string main { set { RootContext.MainClass = value; } }
299
300                 // TODO: handle VB.NET [+|-] boolean syntax
301                 [Option("[IGNORED] Emit compiler output in UTF8 character encoding")]
302                 public bool utf8output;
303
304                 ArrayList defines = new ArrayList();
305                 ArrayList references = new ArrayList();
306                 ArrayList soft_references = new ArrayList();
307                 
308                 string firstSourceFile = null;
309                 Target target = Target.Exe;
310                 string target_ext = ".exe";
311                 ArrayList debug_arglist = new ArrayList ();
312                 bool timestamps = false;
313                 Hashtable source_files = new Hashtable ();
314                 bool load_default_config = true;
315
316                 //
317                 // Last time we took the time
318                 //
319                 DateTime last_time;
320                 void ShowTime (string msg)
321                 {
322                         DateTime now = DateTime.Now;
323                         TimeSpan span = now - last_time;
324                         last_time = now;
325
326                         Console.WriteLine (
327                                 "[{0:00}:{1:000}] {2}",
328                                 (int) span.TotalSeconds, span.Milliseconds, msg);
329                 }
330                         
331                 public int LoadAssembly (string assembly, bool soft)
332                 {
333                         Assembly a;
334                         string total_log = "";
335
336                         try  {
337                                 char[] path_chars = { '/', '\\' };
338
339                                 if (assembly.IndexOfAny (path_chars) != -1)
340                                         a = Assembly.LoadFrom(assembly);
341                                 else {
342                                         string ass = assembly;
343                                         if (ass.EndsWith (".dll"))
344                                                 ass = assembly.Substring (0, assembly.Length - 4);
345                                         a = Assembly.Load (ass);
346                                 }
347                                 TypeManager.AddAssembly (a);
348                                 return 0;
349                         }
350                         catch (FileNotFoundException) {
351                                 if (libpath != null) {
352                                         foreach (string dir in libpath) {
353                                                 string full_path = dir + "/" + assembly + ".dll";
354
355                                                 try  {
356                                                         a = Assembly.LoadFrom (full_path);
357                                                         TypeManager.AddAssembly (a);
358                                                         return 0;
359                                                 } 
360                                                 catch (FileNotFoundException ff)  {
361                                                         total_log += ff.FusionLog;
362                                                         continue;
363                                                 }
364                                         }
365                                 }
366                                 if (soft)
367                                         return 0;
368                         }
369                         catch (BadImageFormatException f)  {
370                                 Error ("// Bad file format while loading assembly");
371                                 Error ("Log: " + f.FusionLog);
372                                 return 1;
373                         } catch (FileLoadException f){
374                                 Error ("File Load Exception: " + assembly);
375                                 Error ("Log: " + f.FusionLog);
376                                 return 1;
377                         } catch (ArgumentNullException){
378                                 Error ("// Argument Null exception ");
379                                 return 1;
380                         }
381                         
382                         Report.Error (6, "Can not find assembly `" + assembly + "'" );
383                         Console.WriteLine ("Log: \n" + total_log);
384
385                         return 0;
386                 }
387
388                 public bool ReferencePackage(string packageName)
389                 {
390                         if (packageName == ""){
391                                 DoAbout ();
392                                 return false;
393                         }
394                                 
395                         ProcessStartInfo pi = new ProcessStartInfo ();
396                         pi.FileName = "pkg-config";
397                         pi.RedirectStandardOutput = true;
398                         pi.UseShellExecute = false;
399                         pi.Arguments = "--libs " + packageName;
400                         Process p = null;
401                         try {
402                                 p = Process.Start (pi);
403                         } catch (Exception e) {
404                                 Report.Error (-27, "Couldn't run pkg-config: " + e.Message);
405                                 return false;
406                         }
407
408                         if (p.StandardOutput == null){
409                                 Report.Warning (-27, "Specified package did not return any information");
410                         }
411                         string pkgout = p.StandardOutput.ReadToEnd ();
412                         p.WaitForExit ();
413                         if (p.ExitCode != 0) {
414                                 Report.Error (-27, "Error running pkg-config. Check the above output.");
415                                 return false;
416                         }
417                         p.Close ();
418                         
419                         if (pkgout != null) {
420                                 string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}).
421                                         Split (new Char [] { ' ', '\t'});
422                                 foreach(string arg in xargs) {
423                                         string[] zargs = arg.Split(':', '=');
424                                         try {
425                                                 if (zargs.Length > 1)
426                                                         AddedReference = zargs[1];
427                                                 else
428                                                         AddedReference = arg;
429                                         } catch (Exception e) {
430                                                 Report.Error (-27, "Something wrong with argument (" + arg + ") in 'pkg-config --libs' output: " + e.Message);
431                                                 return false;
432                                         }
433                                 }
434                         }
435
436                         return true;
437                 }
438
439                 public void LoadModule (MethodInfo adder_method, string module)
440                 {
441                         System.Reflection.Module m;
442                         string total_log = "";
443
444                         try {
445                                 try {
446                                         m = (System.Reflection.Module)adder_method.Invoke (CodeGen.AssemblyBuilder, new object [] { module });
447                                 }
448                                 catch (TargetInvocationException ex) {
449                                         throw ex.InnerException;
450                                 }
451                                 TypeManager.AddModule (m);
452
453                         } 
454                         catch (FileNotFoundException) {
455                                 foreach (string dir in libpath) {
456                                         string full_path = Path.Combine (dir, module);
457                                         if (!module.EndsWith (".netmodule"))
458                                                 full_path += ".netmodule";
459
460                                         try {
461                                                 try {
462                                                         m = (System.Reflection.Module) adder_method.Invoke (CodeGen.AssemblyBuilder, new object [] { full_path });
463                                                 }
464                                                 catch (TargetInvocationException ex) {
465                                                         throw ex.InnerException;
466                                                 }
467                                                 TypeManager.AddModule (m);
468                                                 return;
469                                         }
470                                         catch (FileNotFoundException ff) {
471                                                 total_log += ff.FusionLog;
472                                                 continue;
473                                         }
474                                 }
475                                 Report.Error (6, "Cannot find module `" + module + "'" );
476                                 Console.WriteLine ("Log: \n" + total_log);
477                         }
478                         catch (BadImageFormatException f) {
479                                 Report.Error(6, "Cannot load module (bad file format)" + f.FusionLog);
480                         }
481                         catch (FileLoadException f)     {
482                                 Report.Error(6, "Cannot load module " + f.FusionLog);
483                         }
484                         catch (ArgumentNullException) {
485                                 Report.Error(6, "Cannot load module (null argument)");
486                         }
487                 }
488
489                 void Error(string message)
490                 {
491                         Console.WriteLine(message);
492                 }
493
494                 /// <summary>
495                 ///   Loads all assemblies referenced on the command line
496                 /// </summary>
497                 public int LoadReferences ()
498                 {
499                         int errors = 0;
500
501                         foreach (string r in references)
502                                 errors += LoadAssembly (r, false);
503
504                         foreach (string r in soft_references)
505                                 errors += LoadAssembly (r, true);
506                         
507                         return errors;
508                 }
509
510                 void SetupDefaultDefines ()
511                 {
512                         defines = new ArrayList ();
513                         defines.Add ("__MonoBASIC__");
514                 }
515                 
516                 void SetupDefaultImports()
517                 {
518                         Mono.MonoBASIC.Parser.ImportsList = new ArrayList();
519                         Mono.MonoBASIC.Parser.ImportsList.Add("Microsoft.VisualBasic");
520                 }
521
522                 //
523                 // Given a path specification, splits the path from the file/pattern
524                 //
525                 void SplitPathAndPattern (string spec, out string path, out string pattern)
526                 {
527                         int p = spec.LastIndexOf ("/");
528                         if (p != -1){
529                                 //
530                                 // Windows does not like /file.cs, switch that to:
531                                 // "\", "file.cs"
532                                 //
533                                 if (p == 0){
534                                         path = "\\";
535                                         pattern = spec.Substring (1);
536                                 } else {
537                                         path = spec.Substring (0, p);
538                                         pattern = spec.Substring (p + 1);
539                                 }
540                                 return;
541                         }
542
543                         p = spec.LastIndexOf ("\\");
544                         if (p != -1){
545                                 path = spec.Substring (0, p);
546                                 pattern = spec.Substring (p + 1);
547                                 return;
548                         }
549
550                         path = ".";
551                         pattern = spec;
552                 }
553
554                 bool AddFiles (string spec, bool recurse)
555                 {
556                         string path, pattern;
557
558                         SplitPathAndPattern(spec, out path, out pattern);
559                         if (pattern.IndexOf("*") == -1) {
560                                 AddFile(spec);
561                                 return true;
562                         }
563
564                         string [] files = null;
565                         try {
566                                 files = Directory.GetFiles(path, pattern);
567                         } catch (System.IO.DirectoryNotFoundException) {
568                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
569                                 return false;
570                         } catch (System.IO.IOException){
571                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
572                                 return false;
573                         }
574                         foreach (string f in files)
575                                 AddFile (f);
576
577                         if (!recurse)
578                                 return true;
579                         
580                         string [] dirs = null;
581
582                         try {
583                                 dirs = Directory.GetDirectories(path);
584                         } catch {
585                         }
586                         
587                         foreach (string d in dirs) {
588                                         
589                                 // Don't include path in this string, as each
590                                 // directory entry already does
591                                 AddFiles (d + "/" + pattern, true);
592                         }
593
594                         return true;
595                 }
596
597                 void DefineDefaultConfig ()
598                 {
599                         //
600                         // For now the "default config" is harcoded into the compiler
601                         // we can move this outside later
602                         //
603                         string [] default_config = 
604                         {
605                                 "System",
606                                 "System.Data",
607                                 "System.Xml",
608                                 "Microsoft.VisualBasic" , 
609 #if EXTRA_DEFAULT_REFS
610                                 //
611                                 // Is it worth pre-loading all this stuff?
612                                 //
613                                 "Accessibility",
614                                 "System.Configuration.Install",
615                                 "System.Design",
616                                 "System.DirectoryServices",
617                                 "System.Drawing.Design",
618                                 "System.Drawing",
619                                 "System.EnterpriseServices",
620                                 "System.Management",
621                                 "System.Messaging",
622                                 "System.Runtime.Remoting",
623                                 "System.Runtime.Serialization.Formatters.Soap",
624                                 "System.Security",
625                                 "System.ServiceProcess",
626                                 "System.Web",
627                                 "System.Web.RegularExpressions",
628                                 "System.Web.Services" ,
629                                 "System.Windows.Forms"
630 #endif
631                         };
632                         
633                         foreach (string def in default_config)
634                                 if (!(references.Contains(def) || references.Contains (def + ".dll")))
635                                         soft_references.Add(def);
636                 }
637
638                 [ArgumentProcessor]
639                 public void AddFile(string fileName)
640                 {
641                         string f = fileName;
642                         if (firstSourceFile == null)
643                                 firstSourceFile = f;
644
645                         if (source_files.Contains(f))
646                                 Report.Error(1516, "Source file '" + f + "' specified multiple times");
647                         else
648                                 source_files.Add(f, f);
649                 }
650
651                 void ProcessSourceFile(string filename)
652                 {
653                         if (tokenize)
654                                 GenericParser.Tokenize(filename);
655                         else
656                                 GenericParser.Parse(filename);
657                 }
658
659                 string outputFile_Name = null;
660
661                 string outputFileName {
662                         get 
663                         {
664                                 if (outputFile_Name == null) {
665                                         if (OutputFileName == null) {
666                                                 int pos = firstSourceFile.LastIndexOf(".");
667
668                                                 if (pos > 0)
669                                                         OutputFileName = firstSourceFile.Substring(0, pos);
670                                                 else
671                                                         OutputFileName = firstSourceFile;
672                                         }
673                                         string bname = CodeGen.Basename(OutputFileName);
674                                         if (bname.IndexOf(".") == -1)
675                                                 OutputFileName +=  target_ext;
676                                         outputFile_Name = OutputFileName;
677                                 }
678                                 return outputFile_Name;
679                         }
680                 }
681
682                 bool ParseAll() // Phase 1
683                 {
684                         if (firstSourceFile == null) {
685                                 Report.Error(2008, "No files to compile were specified");
686                                 return false;
687                         }
688
689                         foreach(string filename in source_files.Values)
690                                 ProcessSourceFile(filename);
691
692                         if (tokenize || parse_only || (Report.Errors > 0))
693                                 return false;           
694
695                         return true; // everything went well go ahead
696                 }
697
698                 void InitializeDebuggingSupport()
699                 {
700                         string[] debug_args = new string [debug_arglist.Count];
701                         debug_arglist.CopyTo(debug_args);
702                         CodeGen.Init(outputFileName, outputFileName, want_debugging_support, debug_args);
703                         TypeManager.AddModule(CodeGen.ModuleBuilder);
704                 }
705
706                 public bool ResolveAllTypes() // Phase 2
707                 {
708                         // Load Core Library for default compilation
709                         if (RootContext.StdLib)
710                                 references.Insert(0, "mscorlib");
711
712                         if (load_default_config)
713                                 DefineDefaultConfig();
714
715                         if (timestamps)
716                                 ShowTime("Loading references");
717
718                         // Load assemblies required
719                         if (LoadReferences() > 0) {
720                                 Error ("Could not load one or more assemblies");
721                                 return false;
722                         }
723
724                         if (timestamps)
725                                 ShowTime("References loaded");
726
727                         InitializeDebuggingSupport();
728
729                         // target is Module 
730                         if (target == Target.Module) {
731                                 PropertyInfo module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
732                                 if (module_only == null) {
733                                         Report.Error (0, new Location (-1, -1), "Cannot use /target:module on this runtime: try the Mono runtime instead.");
734                                         Environment.Exit (1);
735                                 }
736
737                                 MethodInfo set_method = module_only.GetSetMethod (true);
738                                 set_method.Invoke (CodeGen.AssemblyBuilder, BindingFlags.Default, null, new object[]{true}, null);
739
740                                 TypeManager.AddModule (CodeGen.ModuleBuilder);
741                         }
742
743                         if (AddedModules.Count > 0) {
744                                 MethodInfo adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.NonPublic);
745                                 if (adder_method == null) {
746                                         Report.Error (0, new Location (-1, -1), "Cannot use /addmodule on this runtime: Try the Mono runtime instead.");
747                                         Environment.Exit (1);
748                                 }
749
750                                 foreach (string module in AddedModules)
751                                         LoadModule (adder_method, module);
752                         }
753
754
755                         //
756                         // Before emitting, we need to get the core
757                         // types emitted from the user defined types
758                         // or from the system ones.
759                         //
760                         if (timestamps)
761                                 ShowTime ("Initializing Core Types");
762
763                         if (!RootContext.StdLib)
764                                 RootContext.ResolveCore ();
765                         if (Report.Errors > 0)
766                                 return false;
767                         
768                         TypeManager.InitCoreTypes();
769                         if (Report.Errors > 0)
770                                 return false;
771
772                         if (timestamps)
773                                 ShowTime ("   Core Types done");
774
775                         if (timestamps)
776                                 ShowTime ("Resolving tree");
777
778                         // The second pass of the compiler
779                         RootContext.ResolveTree ();
780                         if (Report.Errors > 0)
781                                 return false;
782                         
783                         if (timestamps)
784                                 ShowTime ("Populate tree");
785
786                         if (!RootContext.StdLib)
787                                 RootContext.BootCorlib_PopulateCoreTypes();
788                         if (Report.Errors > 0)
789                                 return false;
790
791                         RootContext.PopulateTypes();
792                         if (Report.Errors > 0)
793                                 return false;
794                         
795                         TypeManager.InitCodeHelpers();
796                         if (Report.Errors > 0)
797                                 return false;
798
799                         return true;
800                 }
801                 
802                 bool IsSWFApp()
803                 {
804                         string mainclass = GetFQMainClass();
805                         
806                         if (mainclass != null) {
807                                 foreach (string r in references) {
808                                         if (r.IndexOf ("System.Windows.Forms") >= 0) {
809                                                 Type t = TypeManager.LookupType(mainclass);
810                                                 if (t != null) 
811                                                         return t.IsSubclassOf (TypeManager.LookupType("System.Windows.Forms.Form"));
812                                                 break;  
813                                         }       
814                                 }
815                         }
816                         return false;
817                 }
818                 
819                 string GetFQMainClass()
820                 {       
821                         if (RootContext.RootNamespace != "")
822                                 return RootContext.RootNamespace + "." + RootContext.MainClass;
823                         else
824                                 return RootContext.MainClass;                   
825                 }
826                 
827                 void FixEntryPoint()
828                 {
829                         if (target == Target.Exe || target == Target.WinExe) {
830                                 MethodInfo ep = RootContext.EntryPoint;
831                         
832                                 if (ep == null) {
833                                         // If we don't have a valid entry point yet
834                                         // AND if System.Windows.Forms is included
835                                         // among the dependencies, we have to build
836                                         // a new entry point on-the-fly. Otherwise we
837                                         // won't be able to compile SWF code out of the box.
838
839                                         if (IsSWFApp())  {
840                                                 Type t = TypeManager.LookupType(GetFQMainClass());
841                                                 if (t != null) 
842                                                 {                                                       
843                                                         TypeBuilder tb = t as TypeBuilder;
844                                                         MethodBuilder mb = tb.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, 
845                                                                 typeof(void), new Type[0]);
846
847                                                         Type SWFA = TypeManager.LookupType("System.Windows.Forms.Application");
848                                                         Type SWFF = TypeManager.LookupType("System.Windows.Forms.Form");
849                                                         Type[] args = new Type[1];
850                                                         args[0] = SWFF;
851                                                         MethodInfo mi = SWFA.GetMethod("Run", args);
852                                                         ILGenerator ig = mb.GetILGenerator();
853                                                         ConstructorInfo ci = TypeManager.GetConstructor (TypeManager.LookupType(t.FullName), new Type[0]);
854                                                         
855                                                         ig.Emit (OpCodes.Newobj, ci);
856                                                         ig.Emit (OpCodes.Call, mi);
857                                                         ig.Emit (OpCodes.Ret);
858
859                                                         RootContext.EntryPoint = mb as MethodInfo;
860                                                 }
861                                         }
862                                 }
863                         }
864                 }
865
866                 bool GenerateAssembly()
867                 {
868                         //
869                         // The code generator
870                         //
871                         if (timestamps)
872                                 ShowTime ("Emitting code");
873                         
874                         
875
876                         RootContext.EmitCode();
877                         FixEntryPoint();
878                         if (Report.Errors > 0)
879                                 return false;
880
881                         if (timestamps)
882                                 ShowTime ("   done");
883
884
885                         if (timestamps)
886                                 ShowTime ("Closing types");
887
888                         RootContext.CloseTypes ();
889                         if (Report.Errors > 0)
890                                 return false;
891
892                         if (timestamps)
893                                 ShowTime ("   done");
894
895                         PEFileKinds k = PEFileKinds.ConsoleApplication;
896                                                         
897                         if (target == Target.Library || target == Target.Module)
898                                 k = PEFileKinds.Dll;
899                         else if (target == Target.Exe)
900                                 k = PEFileKinds.ConsoleApplication;
901                         else if (target == Target.WinExe)
902                                 k = PEFileKinds.WindowApplication;
903                         
904                         if (target == Target.Exe || target == Target.WinExe) {
905                                 MethodInfo ep = RootContext.EntryPoint;
906                         
907                                 if (ep == null) {
908                                         Report.Error (30737, "Program " + outputFileName +
909                                                 " does not have an entry point defined");
910                                         return false;
911                                 }
912                                                         
913                                 CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
914                         }
915
916                         // Add the resources
917                         if (EmbeddedResources != null)
918                                 foreach (string file in EmbeddedResources)
919                                         CodeGen.AssemblyBuilder.AddResourceFile (file, file);
920                         
921                         CodeGen.Save(outputFileName);
922
923                         if (timestamps)
924                                 ShowTime ("Saved output");
925
926                         
927                         if (want_debugging_support)  {
928                                 CodeGen.SaveSymbols ();
929                                 if (timestamps)
930                                         ShowTime ("Saved symbols");
931                         }
932
933                         return true;
934                 }
935
936                 public void CompileAll()
937                 {
938                         try {
939 /* 
940                     VB.NET expects the default namespace to be "" (empty string)                
941                     
942                     if (RootContext.RootNamespace == "") {
943                       RootContext.RootNamespace = System.IO.Path.GetFileNameWithoutExtension(outputFileName);
944                     }
945 */
946                                 if (!ParseAll()) // Phase 1
947                                         return;
948
949                                 if (!ResolveAllTypes()) // Phase 2
950                                         return;
951
952                                 GenerateAssembly(); // Phase 3 
953                                 
954                         } catch (Exception ex) {
955                                 Error("Exception: " + ex.ToString());
956                         }
957                 }
958                 
959                 private void ThisIsAlphaAlert()
960                 {
961                         if (!quiet) {
962                                 Console.WriteLine ("--------");
963                                 Console.WriteLine ("MonoBASIC: THIS IS AN ALPHA SOFTWARE.");
964                                 Console.WriteLine ("--------");
965                         }               
966                 }
967                 
968                 protected void SetupDefaults()
969                 {
970                         SetupDefaultDefines();  
971                         SetupDefaultImports();
972                         Report.Stacktrace = false;
973                         RootContext.Checked = true;
974                 }               
975
976                 /// <summary>
977                 ///    Parses the arguments, and calls the compilation process.
978                 /// </summary>
979                 int MainDriver(string [] args)
980                 {
981                         SetupDefaults();
982                         ProcessArgs(args);
983                         
984                         ThisIsAlphaAlert(); // remove this call when the compiler has matured enough
985                         
986                         if (firstSourceFile == null) {
987                                 if (!quiet) 
988                                         DoHelp();
989                                 return 2;
990                         }
991
992                         CompileAll();
993                         return Report.ProcessResults(quiet);
994                 }
995
996                 public static int Main (string[] args)
997                 {
998                         Driver Exec = new Driver();
999                         
1000                         return Exec.MainDriver(args);
1001                 }
1002
1003         }
1004 }