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(new Mono.MonoBASIC.AssemblyAdder(TypeManager.AddAssembly));
81 private bool AdjustCodegenWhenTargetIsNetModule()
83 options.AdjustCodegenWhenTargetIsNetModule(CodeGen.AssemblyBuilder);
87 private bool LoadAddedNetModules()
89 return options.LoadAddedNetModules(CodeGen.AssemblyBuilder, new Mono.MonoBASIC.ModuleAdder(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[] {
277 new CompilerStep(ParseAllSourceFiles),
278 new CompilerStep(InitializeDebuggingSupport),
279 new CompilerStep(LoadReferencedAssemblies),
280 new CompilerStep(AdjustCodegenWhenTargetIsNetModule),
281 new CompilerStep(LoadAddedNetModules),
282 new CompilerStep(InitializeCoreTypes),
283 new CompilerStep(ResolveTree),
284 new CompilerStep(PopulateCoreTypes),
285 new CompilerStep(PopulateTypes),
286 new CompilerStep(InitCodeHelpers),
287 new CompilerStep(EmitCode),
288 new CompilerStep(CloseTypes),
289 new CompilerStep(SetEntryPoint),
290 new CompilerStep(SaveOutput),
291 new CompilerStep(SaveDebugSymbols) } ;
296 /// Parses the arguments, and calls the compilation process.
298 int MainDriver(string [] args)
300 options = new CompilerOptions(args, new ErrorReporter(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);