CLI & Debug runner (#124)

This commit is contained in:
Marcin Kostrzewa 2019-08-28 17:40:08 +02:00 committed by GitHub
parent 5316ffb011
commit 11dc690b21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 190 additions and 14 deletions

5
.gitignore vendored
View File

@ -79,3 +79,8 @@ javadoc/
#######################
bench-report.xml
##############
## Binaries ##
##############
enso

View File

@ -1,7 +1,89 @@
package org.enso.interpreter;
import org.apache.commons.cli.*;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Source;
import java.io.File;
import java.io.IOException;
/** The main CLI entry point class. */
public class Main {
public static void main(String[] args) {
System.out.println("Unimplemented");
private static final String RUN_OPTION = "run";
private static final String HELP_OPTION = "help";
/**
* Builds the {@link Options} object representing the CLI syntax.
*
* @return an {@link Options} object representing the CLI syntax
*/
private static Options buildOptions() {
Option help = Option.builder("h").longOpt(HELP_OPTION).desc("Displays this message.").build();
Option run =
Option.builder()
.hasArg(true)
.numberOfArgs(1)
.argName("file")
.longOpt(RUN_OPTION)
.desc("Runs a specified Enso file.")
.build();
Options options = new Options();
options.addOption(help).addOption(run);
return options;
}
/**
* Prints the help message to the standard output.
*
* @param options object representing the CLI syntax
*/
public static void printHelp(Options options) {
new HelpFormatter().printHelp(Constants.LANGUAGE_ID, options);
}
/** Terminates the process with a failure exit code. */
public static void exitFail() {
System.exit(1);
}
/** Terminates the process with a success exit code. */
public static void exitSuccess() {
System.exit(0);
}
/**
* Main entry point for the CLI program.
*
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {
Options options = buildOptions();
CommandLineParser parser = new DefaultParser();
CommandLine line;
try {
line = parser.parse(options, args);
} catch (ParseException e) {
printHelp(options);
exitFail();
return;
}
if (line.hasOption(HELP_OPTION)) {
printHelp(options);
exitSuccess();
return;
}
if (!line.hasOption(RUN_OPTION)) {
printHelp(options);
exitFail();
return;
}
File file = new File(line.getOptionValue(RUN_OPTION));
Context context =
Context.newBuilder(Constants.LANGUAGE_ID).out(System.out).in(System.in).build();
Source source = Source.newBuilder(Constants.LANGUAGE_ID, file).build();
context.eval(source);
}
}

View File

@ -1,3 +1,5 @@
import scala.sys.process._
// Global Configuration
organization := "org.enso"
scalaVersion := "2.12.8"
@ -16,6 +18,8 @@ javacOptions ++= Seq("-source", "12", "-target", "1.8")
lazy val Benchmark = config("bench") extend Test
lazy val bench = taskKey[Unit]("Run Benchmarks")
lazy val benchOnly = inputKey[Unit]("Run benchmarks by name substring")
lazy val buildNativeImage =
taskKey[Unit]("Build native image for the Enso executable")
// Global Project
lazy val enso = (project in file("."))
@ -79,16 +83,6 @@ val truffleRunOptions = Seq(
javaOptions += s"-Dgraal.TruffleBackgroundCompilation=false"
)
val truffleDebugOptions = Seq(
javaOptions += s"-Dgraal.PrintGraph=Network",
javaOptions += s"-Dgraal.Dump=Truffle:2",
javaOptions += s"-Dgraal.TraceTruffleCompilation=true",
javaOptions += s"-Dgraal.TraceTruffleCompilationCallTree=true",
javaOptions += s"-Dgraal.TraceTruffleInlining=true",
javaOptions += s"-Dgraal.TraceTrufflePerformanceWarnings=true",
javaOptions += s"-Dgraal.TruffleBackgroundCompilation=false"
)
val jmh = Seq(
"org.openjdk.jmh" % "jmh-core" % "1.21" % Benchmark,
"org.openjdk.jmh" % "jmh-generator-annprocess" % "1.21" % Benchmark
@ -99,6 +93,7 @@ lazy val interpreter = (project in file("Interpreter"))
mainClass in (Compile, run) := Some("org.enso.interpreter.Main"),
version := "0.1"
)
.settings(commands += RunDebugCommand.runDebug)
.settings(
libraryDependencies ++= Seq(
"com.chuusai" %% "shapeless" % "2.3.3",
@ -114,7 +109,8 @@ lazy val interpreter = (project in file("Interpreter"))
"org.scalacheck" %% "scalacheck" % "1.14.0" % Test,
"org.scalactic" %% "scalactic" % "3.0.8" % Test,
"org.scalatest" %% "scalatest" % "3.2.0-SNAP10" % Test,
"org.typelevel" %% "cats-core" % "2.0.0-M4"
"org.typelevel" %% "cats-core" % "2.0.0-M4",
"commons-cli" % "commons-cli" % "1.4"
),
libraryDependencies ++= jmh
)
@ -135,6 +131,19 @@ lazy val interpreter = (project in file("Interpreter"))
parallelExecution in Test := false,
logBuffered in Test := false
)
.settings(
buildNativeImage := Def
.task {
val javaHome = System.getProperty("java.home")
val nativeImagePath = s"$javaHome/bin/native-image"
val classPath = (Runtime / fullClasspath).value.files.mkString(":")
val cmd =
s"$nativeImagePath --macro:truffle --no-fallback --initialize-at-build-time -cp $classPath ${(Compile / mainClass).value.get} enso"
cmd !
}
.dependsOn(Compile / compile)
.value
)
.configs(Benchmark)
.settings(
logBuffered := false,
@ -145,7 +154,7 @@ lazy val interpreter = (project in file("Interpreter"))
import complete.Parsers.spaceDelimited
val name = spaceDelimited("<name>").parsed match {
case List(name) => name
case _ => throw new IllegalArgumentException("Expected one argument.")
case _ => throw new IllegalArgumentException("Expected one argument.")
}
Def.task {
(testOnly in Benchmark).toTask(" -- -z " + name).value

View File

@ -0,0 +1,80 @@
import sbt.Keys.javaOptions
import sbt._
/** Command allowing to run the CLI program with additional JVM-level flags.
* The supported flags are:
* * `--dumpGraphs`: dumps IGV output of the program
* * `--showCompilations`: prints Truffle compilation traces
* * `--printAssembly`: prints the disassembler output
* Any CLI arguments should be passed following `--` like so:
* {{{
* runDebug --dumpGraphs --printAssembly -- --run myFile.enso
* }}}
*/
object RunDebugCommand {
val truffleNoBackgroundCompilationOptions = Seq(
"-Dgraal.TruffleBackgroundCompilation=false"
)
val truffleDumpGraphsOptions = Seq(
"-Dgraal.PrintGraph=Network",
"-Dgraal.Dump=Truffle:2"
)
val truffleShowCompilationsOptions = Seq(
"-Dgraal.TraceTruffleCompilation=true",
"-Dgraal.TraceTruffleCompilationCallTree=true",
"-Dgraal.TraceTruffleInlining=true",
"-Dgraal.TraceTrufflePerformanceWarnings=true"
)
val trufflePrintAssemblyOptions = Seq(
"-XX:CompileCommand=print,*OptimizedCallTarget.callRoot",
"-XX:CompileCommand=exclude,*OptimizedCallTarget.callRoot"
)
val dumpGraphsOption = "--dumpGraphs"
val showCompilationsOptions = "--showCompilations"
val printAssemblyOption = "--printAssembly"
val argSeparator = "--"
val commandName = "runDebug"
/** The main logic for parsing and transforming the debug flags into JVM level flags */
def runDebug: Command = Command.args(commandName, "<arguments>") {
(state, args) =>
val (debugFlags, prefixedRunArgs) = args.span(_ != argSeparator)
val runArgs = " " + prefixedRunArgs.drop(1).mkString(" ")
val dumpGraphsOpts =
if (debugFlags.contains(dumpGraphsOption)) truffleDumpGraphsOptions
else Seq()
val showCompilationsOpts =
if (debugFlags.contains(showCompilationsOptions))
truffleShowCompilationsOptions
else Seq()
val printAssemblyOpts =
if (debugFlags.contains(printAssemblyOption))
trufflePrintAssemblyOptions
else Seq()
val javaOpts: Seq[String] = Seq(
truffleNoBackgroundCompilationOptions,
dumpGraphsOpts,
showCompilationsOpts,
printAssemblyOpts
).flatten
val extracted = Project.extract(state)
val withJavaOpts = extracted.appendWithoutSession(
Seq(Compile / Keys.run / Keys.javaOptions ++= javaOpts),
state
)
Project
.extract(withJavaOpts)
.runInputTask(Compile / Keys.run, runArgs, withJavaOpts)
state
}
}