diff --git a/src/main/kotlin/io/smnp/SMNP.kt b/src/main/kotlin/io/smnp/SMNP.kt index 0aec9be..3951565 100644 --- a/src/main/kotlin/io/smnp/SMNP.kt +++ b/src/main/kotlin/io/smnp/SMNP.kt @@ -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) { 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)) } \ No newline at end of file diff --git a/src/main/kotlin/io/smnp/api/callable/Function.kt b/src/main/kotlin/io/smnp/api/callable/Function.kt index 28c2347..ea0f074 100644 --- a/src/main/kotlin/io/smnp/api/callable/Function.kt +++ b/src/main/kotlin/io/smnp/api/callable/Function.kt @@ -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 = 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) } diff --git a/src/main/kotlin/io/smnp/api/callable/Method.kt b/src/main/kotlin/io/smnp/api/callable/Method.kt index 38ecb3a..d654c49 100644 --- a/src/main/kotlin/io/smnp/api/callable/Method.kt +++ b/src/main/kotlin/io/smnp/api/callable/Method.kt @@ -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 = 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) } diff --git a/src/main/kotlin/io/smnp/api/signature/ActualSignatureFormatter.kt b/src/main/kotlin/io/smnp/api/signature/ActualSignatureFormatter.kt new file mode 100644 index 0000000..12d5ffd --- /dev/null +++ b/src/main/kotlin/io/smnp/api/signature/ActualSignatureFormatter.kt @@ -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, parentheses: Boolean = true): String { + val output = mutableListOf() + for(argument in arguments) { + output.add(when(argument.type) { + DataType.LIST -> listTypes(argument.value as List) + DataType.MAP -> mapTypes(argument.value as Map) + else -> argument.type.name.toLowerCase() + }) + } + + return if(parentheses) "(${output.joinToString()})" else output.joinToString() + } + + private fun listTypes(list: List, output: MutableList = mutableListOf()): String { + for (item in list) { + output.add(when (item.type) { + DataType.LIST -> listTypes(item.value as List) + DataType.MAP -> mapTypes(item.value as Map) + else -> item.type.name.toLowerCase() + }) + } + + return "list<${output.toSet().joinToString()}>" + } + + private fun mapTypes(map: Map, output: MutableMap = mutableMapOf()): String { + for ((k, v) in map) { + output[k] = when (v.type) { + DataType.LIST -> listTypes(v.value as List) + DataType.MAP -> mapTypes(v.value as Map) + else -> v.type.name.toLowerCase() + } + } + + return "map<${output.keys.toSet().joinToString()}><${output.values.toSet().joinToString()}}>" + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/smnp/error/FunctionInvocationException.kt b/src/main/kotlin/io/smnp/error/FunctionInvocationException.kt new file mode 100644 index 0000000..90612eb --- /dev/null +++ b/src/main/kotlin/io/smnp/error/FunctionInvocationException.kt @@ -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) : Exception() { + override fun toString() = "Invalid signature: ${function.name}${format(passedArguments)}\nAllowed signatures:\n${function.signature}" +} \ No newline at end of file diff --git a/src/main/kotlin/io/smnp/error/MethodInvocationException.kt b/src/main/kotlin/io/smnp/error/MethodInvocationException.kt new file mode 100644 index 0000000..f748899 --- /dev/null +++ b/src/main/kotlin/io/smnp/error/MethodInvocationException.kt @@ -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) : Exception() { + override fun toString() = "Invalid signature: $obj.${method.name}${format(passedArguments)}\nAllowed signatures:\n${method.signature}" +} \ No newline at end of file