483 lines
18 KiB
Plaintext
483 lines
18 KiB
Plaintext
|
package slangc.sdk;
|
||
|
|
||
|
import slangc.streams.FileInput;
|
||
|
import slangc.streams.File;
|
||
|
import slangc.streams.LogWriter;
|
||
|
import slangc.streams.VFS;
|
||
|
import slangc.streams.SimpleVFS;
|
||
|
import slangc.api.BytecodeTarget;
|
||
|
import slangc.api.CompilerWorld;
|
||
|
import slangc.api.Reporter;
|
||
|
import slangc.api.TypeOption;
|
||
|
import slangc.parser.Annotation;
|
||
|
import slangc.parser.Branch;
|
||
|
import slangc.parser.CleopatraModeLanguage;
|
||
|
import slangc.parser.LegacyLanguage;
|
||
|
import slangc.parser.Node;
|
||
|
import slangc.parser.Token;
|
||
|
|
||
|
public class CompilerMain {
|
||
|
public static int a(int i) {
|
||
|
Log.line("" + i);
|
||
|
return i;
|
||
|
}
|
||
|
public static void b(int a, int b) {
|
||
|
Log.line(a + " " + b);
|
||
|
}
|
||
|
|
||
|
public static void usage(String[] args, int argi, String message) {
|
||
|
Log.line("USAGE:\n\tTODO...\n" + message);
|
||
|
if (message != null) {
|
||
|
throw new Error("TODO: Safe exit"); //System.exit(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void doAddSource(CompilerWorld world, File file, boolean isReference) throws Error {
|
||
|
recursiveAddSource(world, null, file, isReference);
|
||
|
}
|
||
|
|
||
|
private static byte[] getFileBytes(File f) throws Error {
|
||
|
FileInput in = f.openInput();
|
||
|
byte[] out = new byte[(int) f.size()];
|
||
|
in.readBuffer(out, 0, out.length);
|
||
|
in.close();
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
private static void recursiveAddSource(CompilerWorld world, String packagename, File file, boolean isReference) throws Error {
|
||
|
File[] subs = file.list();
|
||
|
if (subs == null) {
|
||
|
//Log.line(" > Processing " + (isReference ? "referenced" : "included") + " file " + file.path());
|
||
|
if (world.matchesIgnorePattern(file.name())) {
|
||
|
//Log.line("Ignoring '" + file.path() + "'...");
|
||
|
} else if (world.matchesDataPattern(file.name())) {
|
||
|
//Log.line("Adding data file '" + file.path() + "'...");
|
||
|
if (!isReference) world.addDataFile(packagename, file.name(), getFileBytes(file), null, null);
|
||
|
} else if (world.matchesSourcePattern(file.name())) {
|
||
|
//Log.line("Adding source file '" + file.path() + "'...");
|
||
|
world.addSource(/*new SimpleSource(file)*/ new UnicodeSource(file), isReference);
|
||
|
} else {
|
||
|
throw new Error("Unrecognised file extension for '" + file.path() + "'");
|
||
|
//Log.line("Ignoring " + file.path() + "...");
|
||
|
}
|
||
|
} else {
|
||
|
if (packagename == null) {
|
||
|
packagename = ""; // This should be used for default/outer directory
|
||
|
} else if (packagename.equals("")) {
|
||
|
packagename = file.name();
|
||
|
} else {
|
||
|
packagename = packagename + "." + file.name();
|
||
|
}
|
||
|
//Log.line("Scanning directory '" + file.path() + "' (as package " + packagename + ")...");
|
||
|
for (int i = 0; i < subs.length; i++) {
|
||
|
recursiveAddSource(world, packagename, subs[i], isReference);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void main(String[] args) {
|
||
|
Log.line("Zak's Burrito Compiler, build #13-ish");
|
||
|
//Log.line("Hello, ٣١٤١٥=" + ٣١٤١٥);
|
||
|
int i = 0;
|
||
|
|
||
|
VFS vfs = new SimpleVFS();
|
||
|
|
||
|
CompilerWorld world = new CompilerWorld();
|
||
|
world.addSourcePattern("*.sauce");
|
||
|
|
||
|
/*
|
||
|
world.addIgnorePattern("*.foo");
|
||
|
world.addDataPattern("bar");
|
||
|
*/
|
||
|
|
||
|
/*for (i = 0; i < args.length; i++) {
|
||
|
Log.line("Arg #" + i + " is '" + args[i] + "'");
|
||
|
}
|
||
|
i = 0;*/
|
||
|
|
||
|
boolean doingSomething = false;
|
||
|
Reporter reporter = null;
|
||
|
//Log.line("Doing args...");
|
||
|
//Log.startTracing();
|
||
|
try {
|
||
|
while (i < args.length) {
|
||
|
//Log.line("Handling Arg #" + i + " is '" + args[i] + "'");
|
||
|
/* If it's a "-b" flag, then we translate it into corresponding "-a" and "-r" flags. */
|
||
|
|
||
|
if (args[i].startsWith("-b")) {
|
||
|
if (args[i].intsLength() > 2) {
|
||
|
String path = args[i].sub(2);
|
||
|
args = ArgsLoader.remove(args, i);
|
||
|
args = ArgsLoader.insert(args, i, new String[] {"-a", path + "/compiler.wrap", "-r", path});
|
||
|
} else {
|
||
|
if (i + 1 >= args.length) {
|
||
|
usage(args, i + 1, "Expecting filename following -a flag");
|
||
|
return;
|
||
|
}
|
||
|
String path = args[i+1];
|
||
|
args = ArgsLoader.remove(args, i);
|
||
|
args = ArgsLoader.remove(args, i);
|
||
|
args = ArgsLoader.insert(args, i, new String[] {"-a", path + "/compiler.wrap", "-r", path});
|
||
|
}
|
||
|
/*for (int x = 0; x < args.length; x++) {
|
||
|
Log.line("Arg #" + x + " = '" + args[x] + "'");
|
||
|
}
|
||
|
System.exit(-1);*/
|
||
|
}
|
||
|
/* If it's a "-a" flag, then we want to load the arguments from a file, insert them in the array,
|
||
|
* then continue processing!
|
||
|
*/
|
||
|
if (args[i].startsWith("-a")) {
|
||
|
if (args[i].intsLength() > 2) {
|
||
|
Log.line("NOTE: Loading compiler arguments from " + args[i].sub(2));
|
||
|
String[] newArgs = ArgsLoader.loadArgs(new UnicodeSource(vfs.file(args[i].sub(2))));
|
||
|
args = ArgsLoader.remove(args, i);
|
||
|
args = ArgsLoader.insert(args, i, newArgs);
|
||
|
} else {
|
||
|
if (i + 1 >= args.length) {
|
||
|
usage(args, i + 1, "Expecting filename following -a flag");
|
||
|
return;
|
||
|
}
|
||
|
Log.line("NOTE: Loading compiler arguments from " + args[i+1]);
|
||
|
String[] newArgs = ArgsLoader.loadArgs(new UnicodeSource(vfs.file(args[i+1])));
|
||
|
args = ArgsLoader.remove(args, i);
|
||
|
args = ArgsLoader.remove(args, i);
|
||
|
args = ArgsLoader.insert(args, i, newArgs);
|
||
|
}
|
||
|
/*for (int x = 0; x < args.length; x++) {
|
||
|
Log.line("Arg #" + x + " = '" + args[x] + "'");
|
||
|
}
|
||
|
System.exit(-1);*/
|
||
|
}
|
||
|
|
||
|
//Log.line("Handling Arg #" + i + " is '" + args[i] + "'");
|
||
|
if (args[i].equals("--provides-version")) {
|
||
|
if (i + 2 >= args.length) {
|
||
|
usage(args, i, "Expected name and version following --provides-version");
|
||
|
return;
|
||
|
}
|
||
|
world.addProvidesVersion(args[i + 1], args[i + 2]);
|
||
|
i += 2;
|
||
|
} else if (args[i].equals("--depends-version")) {
|
||
|
if (i + 2 >= args.length) {
|
||
|
usage(args, i, "Expected name and version following --depends-version");
|
||
|
return;
|
||
|
}
|
||
|
world.addDependsVersion(args[i + 1], args[i + 2]);
|
||
|
i += 2;
|
||
|
} else if (args[i].equals("--source-pattern")) {
|
||
|
if (i + 1 >= args.length) {
|
||
|
usage(args, i, "Expected source pattern following --source-pattern (e.g. \"*.slang\" - probably with the quotes)");
|
||
|
return;
|
||
|
}
|
||
|
world.addSourcePattern(args[i + 1]);
|
||
|
i += 1;
|
||
|
} else if (args[i].equals("--ignore-pattern")) {
|
||
|
if (i + 1 >= args.length) {
|
||
|
usage(args, i, "Expected ignore pattern following --ignore-pattern (e.g. \"*.project\" - probably with the quotes)");
|
||
|
return;
|
||
|
}
|
||
|
world.addIgnorePattern(args[i + 1]);
|
||
|
i += 1;
|
||
|
} else if (args[i].equals("--data-pattern")) {
|
||
|
if (i + 1 >= args.length) {
|
||
|
usage(args, i, "Expected source pattern following --data-pattern (e.g. \"*.png\" - probably with the quotes)");
|
||
|
return;
|
||
|
}
|
||
|
world.addDataPattern(args[i + 1]);
|
||
|
i += 1;
|
||
|
} else if (args[i].equals("--global-import")) {
|
||
|
if (i + 1 >= args.length) {
|
||
|
usage(args, i, "Expected package name following --global-import");
|
||
|
return;
|
||
|
}
|
||
|
world.addGlobalImport(args[i + 1]);
|
||
|
i += 1;
|
||
|
} else if (args[i].equals("--alias-type")) {
|
||
|
if (i + 2 >= args.length) {
|
||
|
usage(args, i, "Expected alias and target type names following --alias-type");
|
||
|
return;
|
||
|
}
|
||
|
world.addAliasType(args[i + 1], args[i + 2]);
|
||
|
i += 2;
|
||
|
} else if (args[i].equals("--alias-package")) {
|
||
|
if (i + 2 >= args.length) {
|
||
|
usage(args, i, "Expected alias and target package names following --alias-package");
|
||
|
return;
|
||
|
}
|
||
|
world.addAliasPackage(args[i + 1], args[i + 2]);
|
||
|
i += 2;
|
||
|
} else if (args[i].equals("--main")) {
|
||
|
if (i + 1 >= args.length) {
|
||
|
usage(args, i, "Expected type name following --main");
|
||
|
return;
|
||
|
}
|
||
|
world.addMainType(args[i + 1]);
|
||
|
i += 1;
|
||
|
} else if (args[i].equals("--special-type-format")) {
|
||
|
if (i + 3 >= args.length) {
|
||
|
usage(args, i, "Expected kind name, type name and runtime-specific format string following --special-type-format");
|
||
|
return;
|
||
|
}
|
||
|
TypeOption.Kind k;
|
||
|
k = (TypeOption.Kind) TypeOption.Kind.lookup(TypeOption.Kind.class, args[i + 1]);
|
||
|
if (k == null) {
|
||
|
usage(args, i+1, "Invalid kind name");
|
||
|
return;
|
||
|
}
|
||
|
world.addSpecialType(k, args[i + 2], args[i + 3]);
|
||
|
i += 3;
|
||
|
} else if (args[i].equals("--special-type")) {
|
||
|
if (i + 2 >= args.length) {
|
||
|
usage(args, i, "Expected kind name and type name following --special-type");
|
||
|
return;
|
||
|
}
|
||
|
TypeOption.Kind k;
|
||
|
try {
|
||
|
k = (TypeOption.Kind) TypeOption.Kind.lookup(TypeOption.Kind.class, args[i + 1]);
|
||
|
} catch(Error e) {
|
||
|
e.log();
|
||
|
Log.line("Name of VOID is '" + TypeOption.Kind.VOID.name() + "'");
|
||
|
usage(args, i+1, "Invalid kind name");
|
||
|
return;
|
||
|
}
|
||
|
world.addSpecialType(k, args[i + 2], null);
|
||
|
i += 2;
|
||
|
} else if (args[i].equals("--builtin-type")) {
|
||
|
if (i + 2 >= args.length) {
|
||
|
usage(args, i, "Expected kind name and type name following --builtin-type");
|
||
|
return;
|
||
|
}
|
||
|
TypeOption.Kind k;
|
||
|
try {
|
||
|
k = (TypeOption.Kind) TypeOption.Kind.lookup(TypeOption.Kind.class, args[i + 1]);
|
||
|
} catch(Error e) {
|
||
|
usage(args, i+1, "Invalid kind name");
|
||
|
return;
|
||
|
}
|
||
|
world.addBuiltinType(k, args[i + 2], null);
|
||
|
i += 2;
|
||
|
} else if (args[i].equals("--meta")) {
|
||
|
if (i + 2 >= args.length) {
|
||
|
usage(args, i, "Expected key and typeName following --meta");
|
||
|
return;
|
||
|
}
|
||
|
world.addMeta(false, args[i + 1], args[i + 2]);
|
||
|
i += 2;
|
||
|
} else if (args[i].equals("--important-meta")) {
|
||
|
if (i + 2 >= args.length) {
|
||
|
usage(args, i, "Expected key and typeName following --important-meta");
|
||
|
return;
|
||
|
}
|
||
|
world.addMeta(true, args[i + 1], args[i + 2]);
|
||
|
i += 2;
|
||
|
} else if (args[i].startsWith("-r")) {
|
||
|
if (args[i].ints().length > 2) {
|
||
|
doAddSource(world, vfs.file(args[i].sub(2)), true);
|
||
|
doingSomething = true;
|
||
|
} else {
|
||
|
i++;
|
||
|
if (i >= args.length) {
|
||
|
usage(args, i, "Expecting filename following -r flag");
|
||
|
return;
|
||
|
}
|
||
|
doAddSource(world, vfs.file(args[i]), true);
|
||
|
doingSomething = true;
|
||
|
}
|
||
|
} else if (args[i].startsWith("-o")) {
|
||
|
if (args[i].ints().length > 2) {
|
||
|
world.setTarget(new BytecodeTarget(new SimpleBytecodeOutput(vfs.file(args[i].sub(2)).openOutput())));
|
||
|
//doingSomething = true;
|
||
|
} else {
|
||
|
i++;
|
||
|
if (i >= args.length) {
|
||
|
usage(args, i, "Expecting filename following -o flag");
|
||
|
return;
|
||
|
}
|
||
|
world.setTarget(new BytecodeTarget(new SimpleBytecodeOutput(vfs.file(args[i]).openOutput())));
|
||
|
//doingSomething = true;
|
||
|
}
|
||
|
} else if (args[i].equals("--compliments-to-the-chef") || args[i].equals("--gluten-free")) {
|
||
|
Log.line("**************************************************");
|
||
|
String start = "* Salt Sprinkling Mode ";
|
||
|
boolean merciless = args[i].equals("--gluten-free");
|
||
|
CleopatraModeLanguage herMajesty = new CleopatraModeLanguage(!merciless);
|
||
|
herMajesty.addMedu(CleopatraModeLanguage.Medu.NUBIAN);
|
||
|
herMajesty.addMedu(CleopatraModeLanguage.Medu.COPTIC);
|
||
|
world.setLanguage(herMajesty);
|
||
|
Log.line(start + (merciless ? " TURBO *" : "ACTIVATED *"));
|
||
|
Log.line("**************************************************");
|
||
|
//herMajesty.printTable(System.err);
|
||
|
//return;
|
||
|
} else if (args[i].equals("-ll0")) {
|
||
|
world.setLanguage(new LegacyLanguage(0));
|
||
|
} else if (args[i].equals("-ll1")) {
|
||
|
world.setLanguage(new LegacyLanguage(1));
|
||
|
} else if (args[i].equals("-ll2")) {
|
||
|
world.setLanguage(new LegacyLanguage(2));
|
||
|
} else if (args[i].equals("-ll3")) {
|
||
|
world.setLanguage(new LegacyLanguage(3));
|
||
|
} else if (args[i].equals("-ll4")) {
|
||
|
world.setLanguage(new LegacyLanguage(4));
|
||
|
} else if (args[i].equals("-ll5")) {
|
||
|
world.setLanguage(new LegacyLanguage(5));
|
||
|
} else if (args[i].equals("-ll6")) {
|
||
|
world.setLanguage(new LegacyLanguage(6));
|
||
|
} else if (args[i].equals("-ll7")) {
|
||
|
world.setLanguage(new LegacyLanguage(7));
|
||
|
} else if (args[i].equals("-ll8")) {
|
||
|
world.setLanguage(new LegacyLanguage(8));
|
||
|
} else if (args[i].equals("-ll9")) {
|
||
|
world.setLanguage(new LegacyLanguage(9));
|
||
|
} else if (args[i].equals("-ll10")) {
|
||
|
world.setLanguage(new LegacyLanguage(10));
|
||
|
} else if (args[i].equals("-ll11")) {
|
||
|
world.setLanguage(new LegacyLanguage(11));
|
||
|
} else if (args[i].equals("-ll12")) {
|
||
|
world.setLanguage(new LegacyLanguage(12));
|
||
|
} else if (args[i].equals("-ll13")) {
|
||
|
world.setLanguage(new LegacyLanguage(13));
|
||
|
} else if (args[i].equals("-ll14")) {
|
||
|
world.setLanguage(new LegacyLanguage(14));
|
||
|
} else if (args[i].equals("-ll15")) {
|
||
|
world.setLanguage(new LegacyLanguage(15));
|
||
|
} else if (args[i].equals("-ll16")) {
|
||
|
world.setLanguage(new LegacyLanguage(16));
|
||
|
} else if (args[i].equals("--language-forget")) {
|
||
|
if (i + 1 >= args.length) {
|
||
|
usage(args, i, "Expecting setting name following --language-forget");
|
||
|
return;
|
||
|
}
|
||
|
if (!world.getLanguage().applySetting(args[i+1], null, true, false)) {
|
||
|
usage(args, i+1, "Invalid setting");
|
||
|
return;
|
||
|
}
|
||
|
i += 1;
|
||
|
} /*else if (args[i].equals("--language-set")) {
|
||
|
if (i + 2 >= args.length) {
|
||
|
usage(args, i, "Expecting setting name and value following --language-set");
|
||
|
return;
|
||
|
}
|
||
|
if (!world.getLanguage().applySetting(args[i+1], args[i+2], false, false)) {
|
||
|
usage(args, i+2, "Invalid setting");
|
||
|
return;
|
||
|
}
|
||
|
i += 2;
|
||
|
}*/ else if (args[i].equals("--language-add")) {
|
||
|
if (i + 2 >= args.length) {
|
||
|
usage(args, i, "Expecting setting name and value following --language-append");
|
||
|
return;
|
||
|
}
|
||
|
if (!world.getLanguage().applySetting(args[i+1], args[i+2], false, true)) {
|
||
|
usage(args, i+2, "Invalid setting");
|
||
|
return;
|
||
|
}
|
||
|
i += 2;
|
||
|
} else if (args[i].equals("--array-length-name")) {
|
||
|
if (i + 1 >= args.length) {
|
||
|
usage(args, i, "Expecting setting name following --array-length-name");
|
||
|
return;
|
||
|
}
|
||
|
world.addArrayLengthName(args[i+1]);
|
||
|
i += 1;
|
||
|
} else if (args[i].equals("--errors-brief")) {
|
||
|
world.setErrorVerbosity(0);
|
||
|
} else if (args[i].equals("--errors-nice")) {
|
||
|
world.setErrorVerbosity(2);
|
||
|
} else if (args[i].equals("--errors-ast")) {
|
||
|
world.setErrorVerbosity(5);
|
||
|
} else if (args[i].equals("--errors-full-ast")) {
|
||
|
world.setErrorVerbosity(10);
|
||
|
} else if (args[i].equals("--cache-dir")) {
|
||
|
//Log.line("WTF...");
|
||
|
if (i + 1 >= args.length) {
|
||
|
usage(args, i, "Expecting directory path following --cache-dir");
|
||
|
return;
|
||
|
}
|
||
|
//Log.line("Trying to set cache manager...");
|
||
|
world.setCacheManager(new SimpleCacheManager(vfs.file(args[i+1])));
|
||
|
//Log.line("Done.");
|
||
|
i += 1;
|
||
|
} else {
|
||
|
Log.line("Adding regular sources '" + args[i] + "'");
|
||
|
doAddSource(world, vfs.file(args[i]), false);
|
||
|
doingSomething = true;
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
if (!doingSomething) {
|
||
|
usage(args, i, "Expecting something to do! Try listing some source files?");
|
||
|
}
|
||
|
|
||
|
if (reporter == null) {
|
||
|
reporter = new SimpleReporter();
|
||
|
}
|
||
|
world.setReporter(reporter);
|
||
|
if (world.build()) {
|
||
|
Log.line("Compilation completed.");
|
||
|
} else {
|
||
|
Log.line("Compilation terminated without finishing.");
|
||
|
}
|
||
|
} catch (Error e) {
|
||
|
e.log();
|
||
|
// TODO: Is more reporting needed here?
|
||
|
}
|
||
|
//SimpleSource src = new SimpleSource("package x.y\nimport z.*; import foo.bar.Baz;\npublic final enum X extends a.B, C{X,Y,private static Z,;} class Foo extends Bar {\nvoid x(int a){{}}\nint a = 1, b;\npublic Foo(int... nums){}}\n/* comment 1 */\n// comment 2\nclass Documented {\n/* look, an array of arrays: */\nint[][] arrz = null;\nDocumented(){if(true){return 1;}else{return;}int x = add(1,z().foo[1].mul(2,3)), y = (z).foo();n();x++; x *= 2; x = 1 + 2 * -3 + new fencom.Object;\nx = \"foo bar\";\n}\n}\n");//int add(int x, int y){\nreturn x + y;\n}
|
||
|
/*Scan scan = new Scan(new Language(), src);
|
||
|
int n = scan.scanPedantic();
|
||
|
Log.line("Scanned " + n + " tokens:");
|
||
|
for (int i = 0; i < scan.countTokens(); i++) {
|
||
|
Log.line(" > " + scan.getToken(i));
|
||
|
}
|
||
|
Parse p = new Parse();
|
||
|
Node u = p.parseUnit(scan);
|
||
|
Log.line("Finished parsing!");
|
||
|
// Was just for testing order of operations: b(a(1), a(2));
|
||
|
dump(System.out, u);
|
||
|
*/
|
||
|
}
|
||
|
@SuppressWarnings("unused")
|
||
|
private static void dump(LogWriter out, Node n) {
|
||
|
dump(out, n, "", " ");
|
||
|
}
|
||
|
|
||
|
private static void dump(LogWriter out, Node n, String curindent, String subindent) {
|
||
|
if (n instanceof Branch) {
|
||
|
dumpBranch(out, (Branch) n, curindent, subindent);
|
||
|
} else if (n instanceof Token) {
|
||
|
dumpToken(out, (Token) n, curindent, subindent);
|
||
|
} else if (n instanceof Annotation) {
|
||
|
dumpAnnotation(out, (Annotation) n, curindent, subindent);
|
||
|
} else if (n == null) {
|
||
|
out.println(curindent + "-! UH-OH !- null");
|
||
|
} else {
|
||
|
out.println(curindent + "-! TO-DO !- code to dump " + n);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void dumpAnnotations(LogWriter out, Node n, String curindent, String subindent) {
|
||
|
for (int i = 0; i < n.countAnnotations(); i++) {
|
||
|
dump(out, n.getAnnotation(i), curindent + subindent, subindent);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void dumpBranch(LogWriter out, Branch b, String curindent, String subindent) {
|
||
|
out.println(curindent + "-> " + b.getNodeType());
|
||
|
dumpAnnotations(out, b, curindent, subindent);
|
||
|
for (int i = 0; i < b.countSubnodes(); i++) {
|
||
|
dump(out, b.getSubnode(i), curindent + subindent, subindent);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void dumpToken(LogWriter out, Token t, String curindent, String subindent) {
|
||
|
out.println(curindent + "-. " + t);
|
||
|
dumpAnnotations(out, t, curindent, subindent);
|
||
|
}
|
||
|
|
||
|
private static void dumpAnnotation(LogWriter out, Annotation a, String curindent, String subindent) {
|
||
|
out.println(curindent + "-+ " + a);
|
||
|
dumpAnnotations(out, a, curindent, subindent);
|
||
|
}
|
||
|
}
|