Introduce basic error handling

This commit is contained in:
2020-03-13 19:55:58 +01:00
parent 7eb543f2bc
commit a0a09ecb55
48 changed files with 534 additions and 263 deletions

View File

@@ -2,7 +2,6 @@ package io.smnp.callable.function
import io.smnp.environment.Environment
import io.smnp.error.FunctionInvocationException
import io.smnp.error.RuntimeException
import io.smnp.type.model.Value
import io.smnp.type.module.Module
@@ -25,7 +24,7 @@ abstract class Function(val name: String) {
val (definition, args) = definitions
.map { Pair(it, it.signature.parse(arguments.toList())) }
.firstOrNull { (_, args) -> args.signatureMatched }
?: throw FunctionInvocationException(this, arguments)
?: throw FunctionInvocationException(this, arguments, environment)
return definition.body(environment, args.arguments)
}

View File

@@ -2,7 +2,6 @@ package io.smnp.callable.method
import io.smnp.environment.Environment
import io.smnp.error.MethodInvocationException
import io.smnp.error.RuntimeException
import io.smnp.type.matcher.Matcher
import io.smnp.type.model.Value
import io.smnp.type.module.Module
@@ -28,7 +27,7 @@ abstract class Method(val typeMatcher: Matcher, val name: String) {
val (definition, args) = definitions
.map { Pair(it, it.signature.parse(arguments.toList())) }
.firstOrNull { (_, args) -> args.signatureMatched }
?: throw MethodInvocationException(this, obj, arguments)
?: throw MethodInvocationException(this, obj, arguments, environment)
return definition.body(environment, obj, args.arguments)
}

View File

@@ -11,6 +11,7 @@ interface Environment {
fun invokeFunction(name: String, arguments: List<Value>): Value
fun invokeMethod(obj: Value, name: String, arguments: List<Value>): Value
fun printCallStack()
fun stackTrace(): String
fun defineFunction(function: Function)
fun defineMethod(method: Method)
fun pushScope(scope: MutableMap<String, Value> = mutableMapOf())

View File

@@ -1,3 +1,3 @@
package io.smnp.error
class CustomException(message: String?) : Exception(message)
class CustomException(message: String?) : SmnpException("Error", message)

View File

@@ -0,0 +1,8 @@
package io.smnp.error
import io.smnp.environment.Environment
class EnvironmentException(exception: SmnpException, val environment: Environment) : SmnpException(
exception.friendlyName,
"${exception.message}\n\nStack trace:\n${environment.stackTrace()}"
)

View File

@@ -0,0 +1,3 @@
package io.smnp.error
class EvaluationException(message: String?) : SmnpException("Runtime error", message)

View File

@@ -2,8 +2,14 @@ package io.smnp.error
import io.smnp.callable.function.Function
import io.smnp.callable.signature.ActualSignatureFormatter.format
import io.smnp.environment.Environment
import io.smnp.type.model.Value
class FunctionInvocationException(private val function: Function, private val passedArguments: Array<out Value>) : Exception() {
override fun toString() = "Invalid signature: ${function.name}${format(passedArguments)}\nAllowed signatures:\n${function.signature}"
}
class FunctionInvocationException(
function: Function,
passedArguments: Array<out Value>,
val environment: Environment
) : SmnpException(
"Function invocation error",
"Invalid signature: ${function.name}${format(passedArguments)}\nAllowed signatures:\n${function.signature}"
)

View File

@@ -2,8 +2,15 @@ package io.smnp.error
import io.smnp.callable.method.Method
import io.smnp.callable.signature.ActualSignatureFormatter.format
import io.smnp.environment.Environment
import io.smnp.type.model.Value
class MethodInvocationException(private val method: Method, private val obj: Value, private val passedArguments: Array<out Value>) : Exception() {
override fun toString() = "Invalid signature: $obj.${method.name}${format(passedArguments)}\nAllowed signatures:\n${method.signature}"
}
class MethodInvocationException(
method: Method,
obj: Value,
passedArguments: Array<out Value>,
val environment: Environment
) : SmnpException(
"Method invocation error",
"Invalid signature: $obj.${method.name}${format(passedArguments)}\nAllowed signatures:\n${method.signature}"
)

View File

@@ -1,3 +0,0 @@
package io.smnp.error
class RuntimeException(message: String?) : Exception(message)

View File

@@ -0,0 +1,3 @@
package io.smnp.error
abstract class SmnpException(val friendlyName: String, message: String? = null) : Exception(message)

View File

@@ -21,4 +21,6 @@ class CallStack {
fun pretty() {
items.asReversed().forEachIndexed { index, item -> println("[${items.size - index - 1}] $item") }
}
fun stackTrace() = items.asReversed().mapIndexed { index, item -> "[${items.size - index - 1}] $item" }.joinToString("\n")
}

View File

@@ -2,6 +2,7 @@ package io.smnp.runtime.model
import io.smnp.callable.signature.ActualSignatureFormatter
import io.smnp.collection.Stack
import io.smnp.error.EvaluationException
import io.smnp.type.model.Value
import io.smnp.type.module.Module
@@ -24,7 +25,7 @@ data class CallStackFrame(
}
fun getVariable(name: String): Value {
return scopes.lastOrNull { it.containsKey(name) }?.get(name) ?: throw RuntimeException("Undefined variable `$name`")
return scopes.lastOrNull { it.containsKey(name) }?.get(name) ?: throw EvaluationException("Undefined variable `$name`")
}
fun prettyScope() {