singrdk/base/Windows/csic/Compiler/Compiler.cs

152 lines
5.5 KiB
C#

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("<stream>", 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);
}
}
}