package scotch.runner; import static java.lang.System.out; import static java.util.stream.Collectors.toList; import static scotch.compiler.ClassLoaderResolver.resolver; import static scotch.compiler.Compiler.compiler; import static scotch.symbol.Symbol.getPackagePath; import static scotch.symbol.Symbol.toJavaName; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.stream.Stream; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import scotch.compiler.Compiler; import scotch.compiler.output.GeneratedClass; import scotch.compiler.error.CompileException; import scotch.compiler.ClassLoaderResolver; import scotch.runtime.Callable; @SuppressWarnings("unused") public class Runner { public static void main(String[] args) throws Exception { new Runner(args).printHelpOr(runner -> { ClassLoaderResolver resolver = resolver(runner.getOutputPath()); Path path = Paths.get(getPackagePath(runner.getModule()) + ".scotch"); try (Stream<String> stream = Files.lines(path.toAbsolutePath())) { List<String> lines = stream.collect(toList()); Compiler compiler = compiler(resolver, lines.toArray(new String[lines.size()])); List<GeneratedClass> generatedClasses = compiler.generateBytecode(); resolver.defineAll(generatedClasses); out.println("main = " + ((Callable) resolver .loadClass(toJavaName(runner.getModule()) + ".$$Module") .getMethod("main") .invoke(null)).call()); } catch (CompileException exception) { exception.printErrors(); } }); } private final JCommander commander; private final String[] args; @Parameter(names = { "-m", "--module" }, description = "[required] The name of the module to run") private String module; @Parameter(names = { "-o", "--output" }, description = "[optional] The compiled class output path, for debugging purposes") private String outputPath; @Parameter(names = { "-h", "--help" }, description = "[optional] Displays this help") private boolean help; public Runner(String[] args) { this.args = Arrays.copyOf(args, args.length); this.commander = new JCommander(); } public String getModule() { return module; } public Optional<File> getOutputPath() { return Optional.ofNullable(outputPath).map(outputPath -> new File(outputPath).getAbsoluteFile()); } public void printHelpOr(ThrowingRunnable runnable) throws Exception { parseArgs(); if (isHelp()) { printHelp(); } else { runnable.run(this); } } private boolean isHelp() { return help || module == null; } private void parseArgs() { commander.addObject(this); commander.parse(args); } private void printHelp() { out.println("Scotch Runner"); commander.getParameters().forEach( action -> out.printf("\t%-15.30s %-10s%n", action.getNames(), action.getDescription()) ); } @FunctionalInterface private interface ThrowingRunnable { void run(Runner runner) throws Exception; } }