Create method and function invocation exception along with arguments formatter

This commit is contained in:
2020-03-08 09:53:02 +01:00
parent 760270c026
commit 815bd29c99
6 changed files with 69 additions and 15 deletions

View File

@@ -1,11 +1,6 @@
package io.smnp
import io.smnp.api.enumeration.DataType
import io.smnp.api.environment.Environment
import io.smnp.api.matcher.Matcher.Companion.listOf
import io.smnp.api.matcher.Matcher.Companion.ofType
import io.smnp.api.model.Value
import io.smnp.api.signature.Signature
import io.smnp.dsl.ast.parser.RootParser
import io.smnp.dsl.token.tokenizer.DefaultTokenizer
import io.smnp.evaluation.evaluator.DefaultEvaluator
@@ -23,10 +18,4 @@ fun main(args: Array<String>) {
val value = evaluator.evaluate(ast.node.children[0], Environment()).value!!
val signature = Signature.vararg(ofType(DataType.INT), ofType(
DataType.BOOL), listOf(DataType.NOTE))
println(signature)
println(signature.parse(value.value!! as List<Value>))
}

View File

@@ -2,6 +2,7 @@ package io.smnp.api.callable
import io.smnp.api.environment.Environment
import io.smnp.api.model.Value
import io.smnp.error.FunctionInvocationException
abstract class Function(val name: String) {
private var definitions: List<FunctionDefinition> = mutableListOf()
@@ -15,8 +16,9 @@ abstract class Function(val name: String) {
fun call(environment: Environment, vararg arguments: Value): Value {
val (definition, args) = definitions
.map { Pair(it, it.signature.parse(arguments.toList())) }
.first { (_, args) -> args.signatureMatched }
// TODO: Throw exception if signature is not matched
.firstOrNull { (_, args) -> args.signatureMatched }
?: throw FunctionInvocationException(this, arguments)
return definition.body(environment, args.arguments)
}

View File

@@ -3,6 +3,7 @@ package io.smnp.api.callable
import io.smnp.api.environment.Environment
import io.smnp.api.matcher.Matcher
import io.smnp.api.model.Value
import io.smnp.error.MethodInvocationException
abstract class Method(val typeMatcher: Matcher, val name: String) {
private var definitions: List<MethodDefinition> = mutableListOf()
@@ -18,8 +19,9 @@ abstract class Method(val typeMatcher: Matcher, val name: String) {
fun call(environment: Environment, obj: Value, vararg arguments: Value): Value {
val (definition, args) = definitions
.map { Pair(it, it.signature.parse(arguments.toList())) }
.first { (_, args) -> args.signatureMatched }
// TODO: Throw exception if signature is not matched
.firstOrNull { (_, args) -> args.signatureMatched }
?: throw MethodInvocationException(this, obj, arguments)
return definition.body(environment, obj, args.arguments)
}

View File

@@ -0,0 +1,43 @@
package io.smnp.api.signature
import io.smnp.api.enumeration.DataType
import io.smnp.api.model.Value
object ActualSignatureFormatter {
fun format(arguments: Array<out Value>, parentheses: Boolean = true): String {
val output = mutableListOf<String>()
for(argument in arguments) {
output.add(when(argument.type) {
DataType.LIST -> listTypes(argument.value as List<Value>)
DataType.MAP -> mapTypes(argument.value as Map<Value, Value>)
else -> argument.type.name.toLowerCase()
})
}
return if(parentheses) "(${output.joinToString()})" else output.joinToString()
}
private fun listTypes(list: List<Value>, output: MutableList<String> = mutableListOf()): String {
for (item in list) {
output.add(when (item.type) {
DataType.LIST -> listTypes(item.value as List<Value>)
DataType.MAP -> mapTypes(item.value as Map<Value, Value>)
else -> item.type.name.toLowerCase()
})
}
return "list<${output.toSet().joinToString()}>"
}
private fun mapTypes(map: Map<Value, Value>, output: MutableMap<Value, String> = mutableMapOf()): String {
for ((k, v) in map) {
output[k] = when (v.type) {
DataType.LIST -> listTypes(v.value as List<Value>)
DataType.MAP -> mapTypes(v.value as Map<Value, Value>)
else -> v.type.name.toLowerCase()
}
}
return "map<${output.keys.toSet().joinToString()}><${output.values.toSet().joinToString()}}>"
}
}

View File

@@ -0,0 +1,9 @@
package io.smnp.error
import io.smnp.api.callable.Function
import io.smnp.api.model.Value
import io.smnp.api.signature.ActualSignatureFormatter.format
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}"
}

View File

@@ -0,0 +1,9 @@
package io.smnp.error
import io.smnp.api.callable.Method
import io.smnp.api.model.Value
import io.smnp.api.signature.ActualSignatureFormatter.format
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}"
}