2 // driver.cs: The compiler command line driver.
4 // Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)
5 // Based on mcs by : Miguel de Icaza (miguel@gnu.org)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2002, 2003, 2004 Rafael Teixeira
16 namespace Mono.Languages {
19 using System.Collections;
22 using System.Globalization;
23 using System.Reflection;
24 using System.Reflection.Emit;
27 using Mono.GetOptions.Useful;
30 CompilerOptions options;
32 private void InitializeRootContextAndOthersFromOptions()
34 Report.Stacktrace = options.Stacktrace;
35 Report.WarningsAreErrors = options.WarningsAreErrors;
36 // TODO: change Report to receive the whole array
37 for(int i = 0; i < options.WarningsToIgnore.Length; i++)
38 Report.SetIgnoreWarning(options.WarningsToIgnore[i]);
39 Report.Fatal = options.MakeErrorsFatal;
41 RootContext.WarningLevel = options.WarningLevel;
42 RootContext.Checked = options.CheckedContext;
43 RootContext.MainClass = options.MainClassName;
44 RootContext.StdLib = !options.NoStandardLibraries;
45 RootContext.Unsafe = options.AllowUnsafeCode;
46 if (options.RootNamespace != null)
47 RootContext.RootNamespace = options.RootNamespace;
49 // TODO: semantics are different and should be adjusted
50 GenericParser.yacc_verbose_flag = options.Verbose ? 1 : 0;
52 Mono.MonoBASIC.Parser.InitialOptionExplicit = options.OptionExplicit;
53 Mono.MonoBASIC.Parser.InitialOptionStrict = options.OptionStrict;
54 Mono.MonoBASIC.Parser.InitialOptionCompareBinary = options.OptionCompareBinary;
55 Mono.MonoBASIC.Parser.ImportsList = options.Imports;
58 bool ParseAllSourceFiles()
60 options.StartTime("Parsing Source Files");
61 foreach(FileToCompile file in options.SourceFilesToCompile)
62 GenericParser.Parse(file.Filename, file.Encoding);
63 options.ShowTime(" Done");
64 return (Report.Errors == 0);
67 private bool InitializeDebuggingSupport()
69 string[] debug_args = new string [options.DebugListOfArguments.Count];
70 options.DebugListOfArguments.CopyTo(debug_args);
71 CodeGen.Init(options.OutputFileName, options.OutputFileName, options.WantDebuggingSupport, debug_args);
72 TypeManager.AddModule(CodeGen.ModuleBuilder);
76 private bool LoadReferencedAssemblies()
78 return options.LoadReferencedAssemblies(TypeManager.AddAssembly);
81 private bool AdjustCodegenWhenTargetIsNetModule()
83 options.AdjustCodegenWhenTargetIsNetModule(CodeGen.AssemblyBuilder);
87 private bool LoadAddedNetModules()
89 return options.LoadAddedNetModules(CodeGen.AssemblyBuilder, TypeManager.AddModule);
92 private bool InitializeCoreTypes()
95 // Before emitting, we need to get the core
96 // types emitted from the user defined types
97 // or from the system ones.
99 options.StartTime("Initializing Core Types");
101 if (!RootContext.StdLib)
102 RootContext.ResolveCore ();
103 if (Report.Errors > 0)
106 TypeManager.InitCoreTypes();
108 options.ShowTime("Core Types Done");
109 return Report.Errors == 0;
112 private bool ResolveTree()
114 options.StartTime("Resolving tree");
115 RootContext.ResolveTree (); // The second pass of the compiler
116 options.ShowTime("Tree resolved");
117 return Report.Errors == 0;
120 private bool PopulateCoreTypes()
122 if (!RootContext.StdLib) {
123 options.StartTime("Populate core types");
124 RootContext.BootCorlib_PopulateCoreTypes();
125 options.ShowTime(" Done");
127 return Report.Errors == 0;
130 private bool PopulateTypes()
132 options.StartTime("Populate types");
133 RootContext.PopulateTypes();
134 options.ShowTime(" Done");
135 return Report.Errors == 0;
138 private bool InitCodeHelpers()
140 options.StartTime("Initialize code helpers");
141 TypeManager.InitCodeHelpers();
142 options.ShowTime(" Done");
143 return Report.Errors == 0;
146 string GetFQMainClass()
148 if (RootContext.RootNamespace != "")
149 return RootContext.RootNamespace + "." + RootContext.MainClass;
151 return RootContext.MainClass;
156 string mainclass = GetFQMainClass();
158 if (mainclass != null) {
159 foreach (string r in options.AssembliesToReference) {
160 if (r.IndexOf ("System.Windows.Forms") >= 0) {
161 Type t = TypeManager.LookupType(mainclass);
163 return t.IsSubclassOf (TypeManager.LookupType("System.Windows.Forms.Form"));
173 if (options.TargetFileType == TargetType.Exe || options.TargetFileType == TargetType.WinExe) {
174 MethodInfo ep = RootContext.EntryPoint;
177 // If we don't have a valid entry point yet
178 // AND if System.Windows.Forms is included
179 // among the dependencies, we have to build
180 // a new entry point on-the-fly. Otherwise we
181 // won't be able to compile SWF code out of the box.
184 Type t = TypeManager.LookupType(GetFQMainClass());
187 TypeBuilder tb = t as TypeBuilder;
188 MethodBuilder mb = tb.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
189 typeof(void), new Type[0]);
191 Type SWFA = TypeManager.LookupType("System.Windows.Forms.Application");
192 Type SWFF = TypeManager.LookupType("System.Windows.Forms.Form");
193 Type[] args = new Type[1];
195 MethodInfo mi = SWFA.GetMethod("Run", args);
196 ILGenerator ig = mb.GetILGenerator();
197 ConstructorInfo ci = TypeManager.GetConstructor (TypeManager.LookupType(t.FullName), new Type[0]);
199 ig.Emit (OpCodes.Newobj, ci);
200 ig.Emit (OpCodes.Call, mi);
201 ig.Emit (OpCodes.Ret);
203 RootContext.EntryPoint = mb as MethodInfo;
210 private bool EmitCode()
212 options.StartTime("Emitting code");
213 RootContext.EmitCode();
215 options.ShowTime(" Done");
216 return Report.Errors == 0;
219 private bool CloseTypes()
221 options.StartTime("Closing types");
222 RootContext.CloseTypes ();
223 options.ShowTime(" Done");
224 return Report.Errors == 0;
227 private bool SetEntryPoint()
229 if (options.TargetFileType == TargetType.Exe || options.TargetFileType == TargetType.WinExe) {
230 options.StartTime("Setting entry point");
231 MethodInfo ep = RootContext.EntryPoint;
234 Report.Error (30737, "Program " + options.OutputFileName + " does not have an entry point defined");
238 CodeGen.AssemblyBuilder.SetEntryPoint (ep,
239 (options.TargetFileType == TargetType.Exe)?PEFileKinds.ConsoleApplication:PEFileKinds.WindowApplication);
240 options.ShowTime(" Done");
242 return Report.Errors == 0;
245 private bool EmbedResources()
247 options.StartTime("Embedding resources");
248 options.EmbedResources(CodeGen.AssemblyBuilder);
249 options.ShowTime(" Done");
250 return Report.Errors == 0;
253 private bool SaveOutput()
255 options.StartTime("Saving Output");
256 CodeGen.Save(options.OutputFileName);
257 options.ShowTime(" Done");
258 return Report.Errors == 0;
262 private bool SaveDebugSymbols()
264 if (options.WantDebuggingSupport) {
265 options.StartTime("Saving Debug Symbols");
266 CodeGen.SaveSymbols ();
267 options.ShowTime (" Done");
272 delegate bool CompilerStep();
274 private CompilerStep[] Steps {
276 return new CompilerStep[] {
278 InitializeDebuggingSupport,
279 LoadReferencedAssemblies,
280 AdjustCodegenWhenTargetIsNetModule,
296 /// Parses the arguments, and calls the compilation process.
298 int MainDriver(string [] args)
300 options = new CompilerOptions(args, Report.Error);
301 if (options.NothingToCompile)
304 InitializeRootContextAndOthersFromOptions();
306 foreach(CompilerStep step in Steps)
310 } catch (Exception ex) {
311 Report.Error(0, "Exception: " + ex.ToString());
313 return Report.ProcessResults(options.BeQuiet);
316 public static int Main (string[] args)
318 Driver Exec = new Driver();
320 return Exec.MainDriver(args);