Modifying the order of Named arguments
[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.IO;
17         using System.Text;
18         using System.Globalization;
19         using System.Reflection;
20         using System.Reflection.Emit;
21
22         using Mono.GetOptions;
23         using Mono.GetOptions.Useful;
24
25         using Mono.MonoBASIC;
26
27         public class Driver {
28                 CompilerOptions options;
29                 
30                 private void InitializeRootContextAndOthersFromOptions()
31                 {
32                         Report.Stacktrace = options.Stacktrace;
33                         Report.WarningsAreErrors = options.WarningsAreErrors;
34                         // TODO: change Report to receive the whole array
35                         for(int i = 0; i < options.WarningsToIgnore.Length; i++)
36                                 Report.SetIgnoreWarning(options.WarningsToIgnore[i]);
37                         Report.Fatal = options.MakeErrorsFatal;
38
39                         RootContext.WarningLevel = options.WarningLevel;
40                         RootContext.Checked = options.CheckedContext;
41                         RootContext.MainClass = options.MainClassName;
42                         RootContext.StdLib = !options.NoStandardLibraries;
43                         RootContext.Unsafe = options.AllowUnsafeCode;
44                         if (options.RootNamespace != null)
45                                 RootContext.RootNamespace = options.RootNamespace;
46                         
47                         // TODO: semantics are different and should be adjusted
48                         GenericParser.yacc_verbose_flag = options.Verbose ? 1 : 0;
49                         
50                         Mono.MonoBASIC.Parser.InitialOptionExplicit = options.OptionExplicit;
51                         Mono.MonoBASIC.Parser.InitialOptionStrict = options.OptionStrict;
52                     Mono.MonoBASIC.Parser.InitialOptionCompareBinary = options.OptionCompareBinary;
53                     Mono.MonoBASIC.Parser.ImportsList = options.Imports;
54                 }
55                 
56                 bool ParseAllSourceFiles()
57                 {
58                         options.StartTime("Parsing Source Files");
59                         foreach(FileToCompile file in options.SourceFilesToCompile)
60                                 GenericParser.Parse(file.Filename, file.Encoding);
61                         options.ShowTime("   Done");
62                         return (Report.Errors == 0);
63                 }
64                 
65                 private bool InitializeDebuggingSupport()
66                 {
67                         string[] debug_args = new string [options.DebugListOfArguments.Count];
68                         options.DebugListOfArguments.CopyTo(debug_args);
69                         CodeGen.Init(options.OutputFileName, options.OutputFileName, options.WantDebuggingSupport, debug_args);
70                         TypeManager.AddModule(CodeGen.ModuleBuilder);
71                         return true;
72                 }
73                 
74                 private bool LoadReferencedAssemblies()
75                 {
76                         return 
77                                 options.LoadReferencedAssemblies(
78                                         new Mono.GetOptions.Useful.AssemblyAdder(TypeManager.AddAssembly));
79                 }
80
81                 private bool AdjustCodegenWhenTargetIsNetModule()
82                 {
83                         options.AdjustCodegenWhenTargetIsNetModule(CodeGen.AssemblyBuilder);
84                         return true;
85                 }
86                 
87                 private bool LoadAddedNetModules()
88                 {
89                         return 
90                                 options.LoadAddedNetModules(
91                                         CodeGen.AssemblyBuilder, 
92                                         new Mono.GetOptions.Useful.ModuleAdder(TypeManager.AddModule));
93                 }
94                 
95                 private bool InitializeCoreTypes()
96                 {
97                         //
98                         // Before emitting, we need to get the core
99                         // types emitted from the user defined types
100                         // or from the system ones.
101                         //
102                         options.StartTime("Initializing Core Types");
103
104                         if (!RootContext.StdLib)
105                                 RootContext.ResolveCore ();
106                         if (Report.Errors > 0)
107                                 return false;
108                         
109                         TypeManager.InitCoreTypes();
110                                 
111                         options.ShowTime("Core Types Done");
112                         return Report.Errors == 0;
113                 }
114
115                 private bool ResolveTree()
116                 {
117                         options.StartTime("Resolving tree");
118                         RootContext.ResolveTree (); // The second pass of the compiler
119                         options.ShowTime("Tree resolved");
120                         return Report.Errors == 0;
121                 }
122                 
123                 private bool PopulateCoreTypes()
124                 {
125                         if (!RootContext.StdLib) {
126                                 options.StartTime("Populate core types");
127                                 RootContext.BootCorlib_PopulateCoreTypes();
128                                 options.ShowTime("   Done");
129                         }
130                         return Report.Errors == 0;
131                 }
132                                                 
133                 private bool PopulateTypes()
134                 {
135                         options.StartTime("Populate types");
136                         RootContext.PopulateTypes();
137                         options.ShowTime("   Done");
138                         return Report.Errors == 0;
139                 }
140                                                 
141                 private bool InitCodeHelpers()
142                 {
143                         options.StartTime("Initialize code helpers");
144                         TypeManager.InitCodeHelpers();
145                         options.ShowTime("   Done");
146                         return Report.Errors == 0;
147                 }
148                                                 
149                 void CookUpEntryPointForWinFormsApplication(Type t)
150                 {
151                         Type SystemWindowsFormsFormType = TypeManager.LookupType ("System.Windows.Forms.Form");
152                         if (SystemWindowsFormsFormType == null || !t.IsSubclassOf (SystemWindowsFormsFormType)) 
153                                 return;
154                                 
155                         TypeBuilder tb = t as TypeBuilder;
156                         MethodBuilder mb = tb.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, 
157                                 typeof(void), new Type[0]);
158
159                         Type SystemWindowsFormsApplicationType = TypeManager.LookupType ("System.Windows.Forms.Application");
160                         MethodInfo mi = SystemWindowsFormsApplicationType.GetMethod ("Run", new Type[] { SystemWindowsFormsFormType } );
161                         ILGenerator ig = mb.GetILGenerator();
162                         ConstructorInfo ci = TypeManager.GetConstructor (TypeManager.LookupType(t.FullName), new Type[0]);
163                                         
164                         ig.Emit (OpCodes.Newobj, ci);
165                         ig.Emit (OpCodes.Call, mi);
166                         ig.Emit (OpCodes.Ret);
167
168                         RootContext.EntryPoint = mb as MethodInfo;
169                 }
170                 
171                 void FixEntryPoint()
172                 {
173                         if (options.TargetFileType == TargetType.Exe || options.TargetFileType == TargetType.WinExe) {
174                                 if (RootContext.EntryPoint == null && RootContext.MainClass != null) {
175                                         // If we don't have a valid entry point yet AND if System.Windows.Forms is included
176                                         // among the dependencies, we have to build a new entry point on-the-fly for the specified
177                                         // main class.
178                                         // Otherwise we won't be able to compile SWF code out of the box.
179                                         Type t = TypeManager.LookupType(RootContext.MainClass);
180                                         if (t == null) 
181                                                 Report.Error(-1, string.Format("Specified main class {0} doesn't exist", RootContext.MainClass));                                       
182                                         else
183                                                 CookUpEntryPointForWinFormsApplication (t);
184                                 }
185                         }
186                 }
187                 
188                 private bool EmitCode()
189                 {
190                         options.StartTime("Emitting code");                     
191                         RootContext.EmitCode();
192                         FixEntryPoint();
193                         options.ShowTime("   Done");
194                         return Report.Errors == 0;
195                 }
196
197                 private bool CloseTypes()
198                 {
199                         options.StartTime("Closing types");                     
200                         RootContext.CloseTypes ();
201                         options.ShowTime("   Done");
202                         return Report.Errors == 0;
203                 }
204
205                 private bool SetEntryPoint()
206                 {
207                         if (options.TargetFileType == TargetType.Exe || options.TargetFileType == TargetType.WinExe) {
208                                 options.StartTime("Setting entry point");                       
209                                 MethodInfo ep = RootContext.EntryPoint;
210                         
211                                 if (ep == null) {
212                                         Report.Error (30737, "Program " + options.OutputFileName + " does not have an entry point defined");
213                                         return false;
214                                 }
215                                                         
216                                 CodeGen.AssemblyBuilder.SetEntryPoint (ep, 
217                                         (options.TargetFileType == TargetType.Exe)?PEFileKinds.ConsoleApplication:PEFileKinds.WindowApplication);
218                                 options.ShowTime("   Done");
219                         }
220                         return Report.Errors == 0;
221                 }
222
223                 private bool EmbedResources()
224                 {
225                         options.StartTime("Embedding resources");                       
226                         options.EmbedResources(CodeGen.AssemblyBuilder);
227                         options.ShowTime("   Done");
228                         return Report.Errors == 0;
229                 }
230
231                 private bool SaveOutput()
232                 {
233                         options.StartTime("Saving Output");                     
234                         CodeGen.Save(options.OutputFileName);
235                         options.ShowTime("   Done");
236                         return Report.Errors == 0;
237                 }
238
239
240                 private bool SaveDebugSymbols()
241                 {
242                         if (options.WantDebuggingSupport)  {
243                                 options.StartTime("Saving Debug Symbols");                      
244                                 CodeGen.SaveSymbols ();
245                                 options.ShowTime ("   Done");
246                         }
247                         return true;
248                 }
249
250                 delegate bool CompilerStep();
251                 
252                 private CompilerStep[] Steps {
253                         get {
254                                 return new CompilerStep[] {
255                                         new CompilerStep(ParseAllSourceFiles),
256                                         new CompilerStep(InitializeDebuggingSupport),
257                                         new CompilerStep(LoadReferencedAssemblies),
258                                         new CompilerStep(AdjustCodegenWhenTargetIsNetModule),
259                                         new CompilerStep(LoadAddedNetModules),
260                                         new CompilerStep(InitializeCoreTypes),
261                                         new CompilerStep(ResolveTree),
262                                         new CompilerStep(PopulateCoreTypes),
263                                         new CompilerStep(PopulateTypes),
264                                         new CompilerStep(InitCodeHelpers),
265                                         new CompilerStep(EmitCode),
266                                         new CompilerStep(CloseTypes),
267                                         new CompilerStep(SetEntryPoint),
268                                         new CompilerStep(SaveOutput),
269                                         new CompilerStep(SaveDebugSymbols) } ;
270                         }
271                 }
272
273                 /// <summary>
274                 ///    Parses the arguments, and calls the compilation process.
275                 /// </summary>
276                 int Execute(string [] args)
277                 {
278                         options = new CompilerOptions(args, new ErrorReporter(Report.Error));           
279                         if (options.NothingToCompile)
280                                 return 2;               
281                         try {
282                                 InitializeRootContextAndOthersFromOptions();
283                                 
284                                 foreach(CompilerStep step in Steps)
285                                         if (!step())
286                                                 break;
287                                                 
288                         } catch (Exception ex) {
289                                 Report.Error(0, "Exception: " + ex.ToString());
290                         }
291                         return Report.ProcessResults(options.BeQuiet);
292                 }
293
294                 public static int Main (string[] args)
295                 {
296                         Driver driver = new Driver();
297                         
298                         return driver.Execute(args);
299                 }
300
301         }
302 }