Step 27E: add CLI bytecode fallback reporting
This commit is contained in:
parent
51319fa8b7
commit
a481371349
@ -27,7 +27,9 @@ import com.github.ajalt.clikt.parameters.arguments.optional
|
|||||||
import com.github.ajalt.clikt.parameters.options.flag
|
import com.github.ajalt.clikt.parameters.options.flag
|
||||||
import com.github.ajalt.clikt.parameters.options.option
|
import com.github.ajalt.clikt.parameters.options.option
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import net.sergeych.lyng.Compiler
|
||||||
import net.sergeych.lyng.LyngVersion
|
import net.sergeych.lyng.LyngVersion
|
||||||
|
import net.sergeych.lyng.Pos
|
||||||
import net.sergeych.lyng.Script
|
import net.sergeych.lyng.Script
|
||||||
import net.sergeych.lyng.ScriptError
|
import net.sergeych.lyng.ScriptError
|
||||||
import net.sergeych.lyng.Source
|
import net.sergeych.lyng.Source
|
||||||
@ -156,6 +158,7 @@ private class Lyng(val launcher: (suspend () -> Unit) -> Unit) : CliktCommand()
|
|||||||
|
|
||||||
val version by option("-v", "--version", help = "Print version and exit").flag()
|
val version by option("-v", "--version", help = "Print version and exit").flag()
|
||||||
val benchmark by option("--benchmark", help = "Run JVM microbenchmarks and exit").flag()
|
val benchmark by option("--benchmark", help = "Run JVM microbenchmarks and exit").flag()
|
||||||
|
val bytecodeFallbacks by option("--bytecode-fallbacks", help = "Report lambdas that fall back to interpreter").flag()
|
||||||
val script by argument(help = "one or more scripts to execute").optional()
|
val script by argument(help = "one or more scripts to execute").optional()
|
||||||
val execute: String? by option(
|
val execute: String? by option(
|
||||||
"-x", "--execute", help = """
|
"-x", "--execute", help = """
|
||||||
@ -198,7 +201,15 @@ private class Lyng(val launcher: (suspend () -> Unit) -> Unit) : CliktCommand()
|
|||||||
launcher {
|
launcher {
|
||||||
// there is no script name, it is a first argument instead:
|
// there is no script name, it is a first argument instead:
|
||||||
processErrors {
|
processErrors {
|
||||||
baseScope.eval(execute!!)
|
val reporter = bytecodeFallbackReporter(bytecodeFallbacks)
|
||||||
|
val script = Compiler.compileWithResolution(
|
||||||
|
Source("<eval>", execute!!),
|
||||||
|
baseScope.currentImportProvider,
|
||||||
|
seedScope = baseScope,
|
||||||
|
bytecodeFallbackReporter = reporter
|
||||||
|
)
|
||||||
|
script.execute(baseScope)
|
||||||
|
flushBytecodeFallbacks(reporter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,7 +220,7 @@ private class Lyng(val launcher: (suspend () -> Unit) -> Unit) : CliktCommand()
|
|||||||
echoFormattedHelp()
|
echoFormattedHelp()
|
||||||
} else {
|
} else {
|
||||||
baseScope.addConst("ARGV", ObjList(args.map { ObjString(it) }.toMutableList()))
|
baseScope.addConst("ARGV", ObjList(args.map { ObjString(it) }.toMutableList()))
|
||||||
launcher { executeFile(script!!) }
|
launcher { executeFile(script!!, bytecodeFallbacks) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,14 +228,14 @@ private class Lyng(val launcher: (suspend () -> Unit) -> Unit) : CliktCommand()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun executeFileWithArgs(fileName: String, args: List<String>) {
|
fun executeFileWithArgs(fileName: String, args: List<String>, reportBytecodeFallbacks: Boolean = false) {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
baseScopeDefer.await().addConst("ARGV", ObjList(args.map { ObjString(it) }.toMutableList()))
|
baseScopeDefer.await().addConst("ARGV", ObjList(args.map { ObjString(it) }.toMutableList()))
|
||||||
executeFile(fileName)
|
executeFile(fileName, reportBytecodeFallbacks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun executeFile(fileName: String) {
|
suspend fun executeFile(fileName: String, reportBytecodeFallbacks: Boolean = false) {
|
||||||
var text = FileSystem.SYSTEM.source(fileName.toPath()).use { fileSource ->
|
var text = FileSystem.SYSTEM.source(fileName.toPath()).use { fileSource ->
|
||||||
fileSource.buffer().use { bs ->
|
fileSource.buffer().use { bs ->
|
||||||
bs.readUtf8()
|
bs.readUtf8()
|
||||||
@ -236,7 +247,16 @@ suspend fun executeFile(fileName: String) {
|
|||||||
text = text.substring(pos + 1)
|
text = text.substring(pos + 1)
|
||||||
}
|
}
|
||||||
processErrors {
|
processErrors {
|
||||||
baseScopeDefer.await().eval(Source(fileName, text))
|
val scope = baseScopeDefer.await()
|
||||||
|
val reporter = bytecodeFallbackReporter(reportBytecodeFallbacks)
|
||||||
|
val script = Compiler.compileWithResolution(
|
||||||
|
Source(fileName, text),
|
||||||
|
scope.currentImportProvider,
|
||||||
|
seedScope = scope,
|
||||||
|
bytecodeFallbackReporter = reporter
|
||||||
|
)
|
||||||
|
script.execute(scope)
|
||||||
|
flushBytecodeFallbacks(reporter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,3 +268,22 @@ suspend fun processErrors(block: suspend () -> Unit) {
|
|||||||
println("\nError executing the script:\n$e\n")
|
println("\nError executing the script:\n$e\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun bytecodeFallbackReporter(enabled: Boolean): ((Pos, String) -> Unit)? {
|
||||||
|
if (!enabled) return null
|
||||||
|
val reports = ArrayList<String>()
|
||||||
|
val reporter: (Pos, String) -> Unit = { pos, msg ->
|
||||||
|
reports.add("$pos: $msg")
|
||||||
|
}
|
||||||
|
return object : (Pos, String) -> Unit by reporter {
|
||||||
|
override fun invoke(pos: Pos, msg: String) = reporter(pos, msg)
|
||||||
|
override fun toString(): String = reports.joinToString("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun flushBytecodeFallbacks(reporter: ((Pos, String) -> Unit)?) {
|
||||||
|
val text = reporter?.toString().orEmpty()
|
||||||
|
if (text.isBlank()) return
|
||||||
|
println("Bytecode lambda fallbacks:")
|
||||||
|
println(text)
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user