package org.shedlang.compiler.cli; import net.sourceforge.argparse4j.ArgumentParsers; import net.sourceforge.argparse4j.ext.java7.PathArgumentType; import net.sourceforge.argparse4j.inf.ArgumentParserException; import net.sourceforge.argparse4j.inf.Namespace; import org.shedlang.compiler.ShedCompiler; import org.shedlang.compiler.backends.Backends; import org.shedlang.compiler.backends.targets.ShedTarget; import org.shedlang.compiler.errors.CompilerError; import org.shedlang.compiler.sources.NullSource; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; public class ShedCli { public static void main(String[] rawArgs) throws IOException, InterruptedException { var args = parseArgs(rawArgs); try { compile(args); } catch (CompilerError error) { if (!(error.source() instanceof NullSource)) { System.err.println(error.source().describe()); } System.err.println(error.getMessage()); System.exit(2); } } private static void compile(Namespace args) throws IOException, InterruptedException { var sourcePath = args.get("source"); var compiler = new ShedCompiler(); switch (args.get("command")) { case COMPILE -> { var target = ShedTarget.fromString(args.getString("target")).orElseThrow(); var backend = Optional.ofNullable(args.getString("backend")) .map( backendName -> Backends .backendFactory(backendName) // In principle, this should be prevented by the arg parsing. .orElseThrow(() -> new UnsupportedOperationException("Unrecognised backend: " + backendName)) .backendForTarget(target) .orElseThrow(() -> new UnsupportedTargetError(backendName, target)) ) .orElseGet(() -> Backends.backendForTarget(target)); var profile = Optional.ofNullable(args.getString("profile")); compiler.compile(sourcePath, backend, profile); } } } private static Namespace parseArgs(String[] args) { var parser = ArgumentParsers.newFor("shed").build() .defaultHelp(true); var subparsers = parser.addSubparsers(); var compileSubParser = subparsers.addParser("compile"); compileSubParser.setDefault("command", Command.COMPILE); compileSubParser .addArgument("source") .type(new PathArgumentType()) .required(true); compileSubParser.addArgument("--backend").choices(Backends.backendNames()).required(false); compileSubParser.addArgument("--target").choices(ShedTarget.targetNames()).required(true); compileSubParser.addArgument("--profile").required(false); try { return parser.parseArgs(args); } catch (ArgumentParserException e) { parser.handleError(e); System.exit(1); throw new RuntimeException(e); } } private enum Command { COMPILE, } }