using System; using System.Collections; using System.IO; #if SUPPORT_DYNAMIC_LOADING_OF_VISITORS using System.Reflection; #endif public class Compiler { public MessageWriter Msg; Imports imports; VisitorDelegateList visitors = new VisitorDelegateList(); ArrayList visitorArgs = new ArrayList(); public void AddLibraryPath(string path) { checkArg(path, "path"); imports.Add(path); } public bool AddReference(string file) { checkArg(file, "file"); return imports.Load(file); } public bool AddVisitor(VisitorDelegate visitor) { return AddVisitor(visitor, new string[0]); } public bool AddVisitor(VisitorDelegate visitor, string[] args) { visitors.Add(visitor); visitorArgs.Add(args.Clone()); return true; } #if SUPPORT_DYNAMIC_LOADING_OF_VISITORS public bool AddVisitor(System.Type type) { return AddVisitor(type, new string[0]); } public bool AddVisitor(System.Type type, string[] args) { checkArg(type, "classname"); checkArg(args, "args"); MethodInfo m = type.GetMethod("visit", new System.Type[] { typeof(compilation), typeof(TextWriter), typeof(string[]), typeof(MessageWriter) }); if (m != null && m.IsStatic && m.IsPublic && m.ReturnType == typeof(compilation)) { VisitorDelegate visitor = (VisitorDelegate)VisitorDelegate.CreateDelegate(typeof(VisitorDelegate), m); return AddVisitor(visitor, args); } Console.WriteLine("Couldn't find visit method on {0}", type); return false; } #endif void checkArg(object arg, string name) { if (arg == null) throw new ArgumentNullException(name); } void compile(string[] inputs, compilation_unitList asts) { foreach (string f in inputs) try { TextReader r = new StreamReader(f); long time = Debug.Clock; object ast = Parser.parse(f, r); if (ast != null) asts.Add((compilation_unit)ast); else Msg.Count++; r.Close(); } catch (Exception e) { Msg.Error("can't read \"{0}\": {1}", f, e.Message); } } public int Compile(string[] inputs, string[] argv) { checkArg(inputs, "inputs"); compilation_unitList asts = new compilation_unitList(); compile(inputs, asts); if (Msg.Count == 0 && asts.Count > 0) visit(argv, asts, Console.Out); return Msg.Count; } public int Compile(string[] inputs, string output, string[] argv) { checkArg(inputs, "inputs"); checkArg(output, "output"); compilation_unitList asts = new compilation_unitList(); compile(inputs, asts); if (Msg.Count == 0 && asts.Count > 0) { TextWriter w; try { w = new StreamWriter(output); } catch (Exception e) { Msg.Error("can't write \"{0}\": {1}", output, e.Message); return Msg.Count; } visit(argv, asts, w); w.Close(); } return Msg.Count; } public int Compile(TextReader input, TextWriter output, string[] argv) { checkArg(input, "input"); long time = Debug.Clock; object ast = Parser.parse("", input); if (ast == null) Msg.Count++; if (Msg.Count == 0 && ast != null) visit(argv, compilation_unitList.New((compilation_unit)ast), output); return Msg.Count; } public Compiler() : this(new NullReader(), Console.Error) {} public Compiler(IImportReader reader) : this(reader, Console.Error) { } public Compiler(IImportReader reader, TextWriter errors) { Msg = new MessageWriter(errors); imports = new Imports(reader, Msg); imports.Add("."); } #if SUPPORT_DYNAMIC_LOADING_OF_VISITORS public bool LoadVisitor(string classname) { return LoadVisitor(classname, null, new string[0]); } public bool LoadVisitor(string classname, string filename) { checkArg(filename, "filename"); return LoadVisitor(classname, filename, new string[0]); } public bool LoadVisitor(string classname, string filename, string[] args) { checkArg(classname, "classname"); checkArg(args, "args"); Assembly asm; try { if (filename != null) asm = Assembly.LoadFrom(filename); else asm = Assembly.Load(classname); } catch { return false; } System.Type t; if (asm == null || (t = asm.GetType(classname)) == null) return false; return AddVisitor(t, args); } #endif void visit(string[] argv, compilation_unitList asts, TextWriter w) { compilation ast = new compilation(argv, asts, imports.global); ast.link(null); for (int i = 0; i < visitors.Count && ast != null; i++) { VisitorDelegate visitor = visitors[i]; string[] args = (string[])visitorArgs[i]; ast = visitor(ast, w, args, Msg); } } }