From bf474f6b69e1cde7198158f90faa9fb2f32b4703 Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Fri, 8 Sep 2023 00:04:36 -0700 Subject: [PATCH] evaluator: introduce and expose scope tracking --- .../pork/evaluator/CompilationUnitContext.kt | 7 +++-- .../gay/pizza/pork/evaluator/Evaluator.kt | 2 +- .../kotlin/gay/pizza/pork/evaluator/Scope.kt | 31 +++++++++++++++++-- examples/java.pork | 8 +---- .../kotlin/gay/pizza/pork/tool/RunCommand.kt | 14 ++++++--- 5 files changed, 44 insertions(+), 18 deletions(-) diff --git a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/CompilationUnitContext.kt b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/CompilationUnitContext.kt index 0cb3822..7ac02f5 100644 --- a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/CompilationUnitContext.kt +++ b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/CompilationUnitContext.kt @@ -9,10 +9,11 @@ import gay.pizza.pork.frontend.ImportLocator class CompilationUnitContext( val compilationUnit: CompilationUnit, val evaluator: Evaluator, - rootScope: Scope + rootScope: Scope, + name: String = "unknown" ) { - val internalScope = rootScope.fork() - val externalScope = rootScope.fork() + val internalScope = rootScope.fork("internal $name") + val externalScope = rootScope.fork("external $name") private var initialized = false diff --git a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/Evaluator.kt b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/Evaluator.kt index affe5ef..15d60c4 100644 --- a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/Evaluator.kt +++ b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/Evaluator.kt @@ -14,7 +14,7 @@ class Evaluator(val world: World, val scope: Scope) { val unit = world.load(locator) val identity = world.stableIdentity(locator) val context = contexts.computeIfAbsent(identity) { - CompilationUnitContext(unit, this, scope) + CompilationUnitContext(unit, this, scope, name = "${locator.form} ${locator.path}") } context.initIfNeeded() return context diff --git a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/Scope.kt b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/Scope.kt index 5ed68ac..b65f444 100644 --- a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/Scope.kt +++ b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/Scope.kt @@ -1,6 +1,10 @@ package gay.pizza.pork.evaluator -class Scope(val parent: Scope? = null, inherits: List = emptyList()) { +class Scope( + val parent: Scope? = null, + inherits: List = emptyList(), + val name: String? = null +) { private val inherited = inherits.toMutableList() private val variables = mutableMapOf() @@ -41,8 +45,8 @@ class Scope(val parent: Scope? = null, inherits: List = emptyList()) { return value } - fun fork(): Scope = - Scope(this) + fun fork(name: String? = null): Scope = + Scope(this, name = name) internal fun inherit(scope: Scope) { inherited.add(scope) @@ -55,5 +59,26 @@ class Scope(val parent: Scope? = null, inherits: List = emptyList()) { return parent } + fun crawlScopePath( + path: List = mutableListOf(name ?: "unknown"), + block: (String, List) -> Unit + ) { + for (key in variables.keys) { + block(key, path) + } + + for (inherit in inherited) { + val mutablePath = path.toMutableList() + mutablePath.add("inherit ${inherit.name ?: "unknown"}") + inherit.crawlScopePath(mutablePath, block) + } + + if (parent != null) { + val mutablePath = path.toMutableList() + mutablePath.add("parent ${parent.name ?: "unknown"}") + parent.crawlScopePath(mutablePath, block) + } + } + private object NotFound } diff --git a/examples/java.pork b/examples/java.pork index 456a80a..1c3e54b 100644 --- a/examples/java.pork +++ b/examples/java.pork @@ -1,13 +1,7 @@ import java java.lang.System import java java.io.PrintStream -import java java.io.InputStreamReader -import java java.io.BufferedReader export func main() { - let input = java_lang_System_in_get() - let reader = java_io_InputStreamReader_new_inputstream(input) - let bufferedReader = java_io_BufferedReader_new_reader(reader) - let line = java_io_BufferedReader_readLine(bufferedReader) let stream = java_lang_System_err_get() - java_io_PrintStream_println_string(stream, line) + java_io_PrintStream_println_string(stream, "Hello World") } diff --git a/tool/src/main/kotlin/gay/pizza/pork/tool/RunCommand.kt b/tool/src/main/kotlin/gay/pizza/pork/tool/RunCommand.kt index eb197b6..481a9dd 100644 --- a/tool/src/main/kotlin/gay/pizza/pork/tool/RunCommand.kt +++ b/tool/src/main/kotlin/gay/pizza/pork/tool/RunCommand.kt @@ -5,10 +5,7 @@ import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import gay.pizza.dough.fs.PlatformFsProvider -import gay.pizza.pork.evaluator.Arguments -import gay.pizza.pork.evaluator.CallableFunction -import gay.pizza.pork.evaluator.None -import gay.pizza.pork.evaluator.Scope +import gay.pizza.pork.evaluator.* import gay.pizza.pork.ffi.JavaNativeProvider import gay.pizza.pork.ffi.JnaNativeProvider @@ -16,6 +13,7 @@ class RunCommand : CliktCommand(help = "Run Program", name = "run") { val loop by option("--loop", help = "Loop Program").flag() val measure by option("--measure", help = "Measure Time").flag() val quiet by option("--quiet", help = "Silence Prints").flag() + val dumpScope by option("--dump-scope", help = "Dump Scope").flag() val path by argument("file") override fun run() { @@ -36,6 +34,14 @@ class RunCommand : CliktCommand(help = "Run Program", name = "run") { addNativeFunctionProvider("java", JavaNativeProvider()) }) + if (dumpScope) { + val functionContext = main as FunctionContext + val internalScope = functionContext.compilationUnitContext.internalScope + internalScope.crawlScopePath { key, path -> + println("[scope] $key [${path.joinToString(" -> ")}]") + } + } + maybeLoopAndMeasure(loop, measure) { main.call(Arguments(emptyList())) }