Improve callstack() debug function and rename it to stacktrace()

This commit is contained in:
2020-03-14 16:44:28 +01:00
parent 5c56060e70
commit 8ee3195bef
7 changed files with 53 additions and 41 deletions

View File

@@ -10,7 +10,7 @@ interface Environment {
fun printModules(printContent: Boolean) fun printModules(printContent: Boolean)
fun invokeFunction(name: String, arguments: List<Value>): Value fun invokeFunction(name: String, arguments: List<Value>): Value
fun invokeMethod(obj: Value, name: String, arguments: List<Value>): Value fun invokeMethod(obj: Value, name: String, arguments: List<Value>): Value
fun printCallStack() fun printCallStack(scopes: Boolean = false)
fun stackTrace(): String fun stackTrace(): String
fun defineFunction(function: Function) fun defineFunction(function: Function)
fun defineMethod(method: Method) fun defineMethod(method: Method)

View File

@@ -6,24 +6,30 @@ import io.smnp.type.module.Module
class CallStack { class CallStack {
private val items = Stack.of<CallStackFrame>() private val items = Stack.of<CallStackFrame>()
fun push(module: Module, name: String, arguments: List<Value>) { fun push(module: Module, name: String, arguments: List<Value>) {
items.push(CallStackFrame(module, name, arguments)) items.push(CallStackFrame(module, name, arguments))
} }
fun push(frame: CallStackFrame) = items.push(frame) fun push(frame: CallStackFrame) = items.push(frame)
fun pop() = items.pop() fun pop() = items.pop()
fun top() = items.top() fun top() = items.top()
val size: Int val size: Int
get() = items.size get() = items.size
fun pretty() { fun pretty(scopes: Boolean = false) {
items.asReversed().forEachIndexed { index, item -> println("[${items.size - index - 1}] $item") } items.asReversed().mapIndexed { index, item ->
} println("[${items.size - index - 1}] $item")
if (scopes) {
item.scopes.forEach { println(" $it") }
}
}
}
fun stackTrace() = items.asReversed().mapIndexed { index, item -> "[${items.size - index - 1}] $item" }.joinToString("\n") val stackTrace: List<String>
get() = items.asReversed().mapIndexed { index, item -> "[${items.size - index - 1}] $item" }
} }

View File

@@ -11,29 +11,32 @@ data class CallStackFrame(
val name: String, val name: String,
val arguments: List<Value> val arguments: List<Value>
) { ) {
private val scopes = Stack.of<MutableMap<String, Value>>(mutableMapOf()) private val scopesStack = Stack.of<MutableMap<String, Value>>(mutableMapOf())
fun pushScope(scope: MutableMap<String, Value> = mutableMapOf()) { fun pushScope(scope: MutableMap<String, Value> = mutableMapOf()) {
scopes.push(scope) scopesStack.push(scope)
} }
fun popScope() = scopes.pop() fun popScope() = scopesStack.pop()
val scopesCount: Int val scopesCount: Int
get() = scopes.size get() = scopesStack.size
fun setVariable(name: String, value: Value) { fun setVariable(name: String, value: Value) {
val scope = scopes.lastOrNull { it.containsKey(name) } ?: scopes.top() val scope = scopesStack.lastOrNull { it.containsKey(name) } ?: scopesStack.top()
scope[name] = value scope[name] = value
} }
fun getVariable(name: String): Value { fun getVariable(name: String): Value {
return scopes.lastOrNull { it.containsKey(name) }?.get(name) ?: throw EvaluationException("Undefined variable `$name`") return scopesStack.lastOrNull { it.containsKey(name) }?.get(name) ?: throw EvaluationException("Undefined variable `$name`")
} }
fun prettyScope() { fun prettyScope() {
scopes.asReversed().forEachIndexed { index, item -> println("[${scopes.size - index - 1}] $item") } scopes.forEach { println(it) }
} }
val scopes: List<String>
get() = scopesStack.asReversed().mapIndexed { index, item -> "[${scopesStack.size - index - 1}] $item" }
override fun toString() = "${module.canonicalName}::$name${ActualSignatureFormatter.format(arguments.toTypedArray())}" override fun toString() = "${module.canonicalName}::$name${ActualSignatureFormatter.format(arguments.toTypedArray())}"
} }

View File

@@ -123,12 +123,12 @@ class DefaultEnvironment : Environment {
return value return value
} }
override fun printCallStack() { override fun printCallStack(scopes: Boolean) {
callStack.pretty() callStack.pretty(scopes)
} }
override fun stackTrace(): String { override fun stackTrace(): String {
return callStack.stackTrace() return callStack.stackTrace.joinToString("\n")
} }
override fun defineFunction(function: Function) { override fun defineFunction(function: Function) {

View File

@@ -1,9 +1,9 @@
package io.smnp.ext package io.smnp.ext
import io.smnp.ext.function.CallStackFunction import io.smnp.ext.function.StackTraceFuction
import org.pf4j.Extension import org.pf4j.Extension
@Extension @Extension
class DebugModule : NativeModuleProvider("smnp.lang.debug") { class DebugModule : NativeModuleProvider("smnp.lang.debug") {
override fun functions() = listOf(CallStackFunction()) override fun functions() = listOf(StackTraceFuction())
} }

View File

@@ -1,15 +0,0 @@
package io.smnp.ext.function
import io.smnp.callable.function.Function
import io.smnp.callable.function.FunctionDefinitionTool
import io.smnp.callable.signature.Signature
import io.smnp.type.model.Value
class CallStackFunction : Function("callstack") {
override fun define(new: FunctionDefinitionTool) {
new function Signature.simple() body { env, _ ->
env.printCallStack()
Value.void()
}
}
}

View File

@@ -0,0 +1,18 @@
package io.smnp.ext.function
import io.smnp.callable.function.Function
import io.smnp.callable.function.FunctionDefinitionTool
import io.smnp.callable.signature.Signature
import io.smnp.type.enumeration.DataType.BOOL
import io.smnp.type.matcher.Matcher.Companion.ofType
import io.smnp.type.matcher.Matcher.Companion.optional
import io.smnp.type.model.Value
class StackTraceFuction : Function("stacktrace") {
override fun define(new: FunctionDefinitionTool) {
new function Signature.simple(optional(ofType(BOOL))) body { env, args ->
env.printCallStack(args.getOrNull(0)?.value as Boolean? ?: false)
Value.void()
}
}
}