[BIG REFACTOR] Create new project structure and prepare scaffolding for external modules system
This commit is contained in:
27
api/src/main/kotlin/io/smnp/callable/function/Function.kt
Normal file
27
api/src/main/kotlin/io/smnp/callable/function/Function.kt
Normal file
@@ -0,0 +1,27 @@
|
||||
package io.smnp.callable.function
|
||||
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.FunctionInvocationException
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
abstract class Function(val name: String) {
|
||||
private var definitions: List<FunctionDefinition> = mutableListOf()
|
||||
|
||||
abstract fun define(new: FunctionDefinitionTool)
|
||||
|
||||
init {
|
||||
definitions = FunctionDefinitionTool().apply { define(this) }.definitions
|
||||
}
|
||||
|
||||
fun call(environment: Environment, vararg arguments: Value): Value {
|
||||
val (definition, args) = definitions
|
||||
.map { Pair(it, it.signature.parse(arguments.toList())) }
|
||||
.firstOrNull { (_, args) -> args.signatureMatched }
|
||||
?: throw FunctionInvocationException(this, arguments)
|
||||
|
||||
return definition.body(environment, args.arguments)
|
||||
}
|
||||
|
||||
val signature: String
|
||||
get() = definitions.joinToString("\nor\n") { "$name${it.signature}" }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package io.smnp.callable.function
|
||||
|
||||
import io.smnp.callable.signature.Signature
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
class FunctionDefinition(val signature: Signature, val body: (Environment, List<Value>) -> Value)
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.smnp.callable.function
|
||||
|
||||
import io.smnp.callable.signature.Signature
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
class FunctionDefinitionTool {
|
||||
val definitions: MutableList<FunctionDefinition> = mutableListOf()
|
||||
|
||||
infix fun function(signature: Signature): FunctionDefinitionToolStage2 {
|
||||
return FunctionDefinitionToolStage2(signature)
|
||||
}
|
||||
|
||||
inner class FunctionDefinitionToolStage2(private val signature: Signature) {
|
||||
infix fun define(body: (Environment, List<Value>) -> Value) {
|
||||
definitions.add(FunctionDefinition(signature, body))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
30
api/src/main/kotlin/io/smnp/callable/method/Method.kt
Normal file
30
api/src/main/kotlin/io/smnp/callable/method/Method.kt
Normal file
@@ -0,0 +1,30 @@
|
||||
package io.smnp.callable.method
|
||||
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.MethodInvocationException
|
||||
import io.smnp.type.matcher.Matcher
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
abstract class Method(val typeMatcher: Matcher, val name: String) {
|
||||
private var definitions: List<MethodDefinition> = mutableListOf()
|
||||
|
||||
abstract fun define(new: MethodDefinitionTool)
|
||||
|
||||
init {
|
||||
definitions = MethodDefinitionTool().apply { define(this) }.definitions
|
||||
}
|
||||
|
||||
fun verifyType(type: Value) = typeMatcher.match(type)
|
||||
|
||||
fun call(environment: Environment, obj: Value, vararg arguments: Value): Value {
|
||||
val (definition, args) = definitions
|
||||
.map { Pair(it, it.signature.parse(arguments.toList())) }
|
||||
.firstOrNull { (_, args) -> args.signatureMatched }
|
||||
?: throw MethodInvocationException(this, obj, arguments)
|
||||
|
||||
return definition.body(environment, obj, args.arguments)
|
||||
}
|
||||
|
||||
val signature: String
|
||||
get() = definitions.joinToString("\nor\n") { "$typeMatcher.$name${it.signature}" }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package io.smnp.callable.method
|
||||
|
||||
import io.smnp.callable.signature.Signature
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
class MethodDefinition(val signature: Signature, val body: (Environment, Value, List<Value>) -> Value)
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.smnp.callable.method
|
||||
|
||||
import io.smnp.callable.signature.Signature
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
class MethodDefinitionTool {
|
||||
val definitions: MutableList<MethodDefinition> = mutableListOf()
|
||||
|
||||
infix fun method(signature: Signature): MethodDefinitionToolStage2 {
|
||||
return MethodDefinitionToolStage2(signature)
|
||||
}
|
||||
|
||||
inner class MethodDefinitionToolStage2(private val signature: Signature) {
|
||||
infix fun define(body: (Environment, Value, List<Value>) -> Value) {
|
||||
definitions.add(MethodDefinition(signature, body))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package io.smnp.callable.signature
|
||||
|
||||
import io.smnp.type.enumeration.DataType
|
||||
import io.smnp.type.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()}}>"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package io.smnp.callable.signature
|
||||
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
class ArgumentsList(val signatureMatched: Boolean, val arguments: List<Value>) {
|
||||
operator fun get(index: Int) = arguments[index]
|
||||
|
||||
fun toArray() = arguments.toTypedArray()
|
||||
|
||||
override fun toString() = if(signatureMatched) "valid($arguments)" else "invalid"
|
||||
|
||||
companion object {
|
||||
fun valid(arguments: List<Value>): ArgumentsList {
|
||||
return ArgumentsList(true, arguments)
|
||||
}
|
||||
|
||||
fun invalid(): ArgumentsList {
|
||||
return ArgumentsList(false, emptyList())
|
||||
}
|
||||
}
|
||||
}
|
||||
18
api/src/main/kotlin/io/smnp/callable/signature/Signature.kt
Normal file
18
api/src/main/kotlin/io/smnp/callable/signature/Signature.kt
Normal file
@@ -0,0 +1,18 @@
|
||||
package io.smnp.callable.signature
|
||||
|
||||
import io.smnp.type.matcher.Matcher
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
interface Signature {
|
||||
fun parse(arguments: List<Value>): ArgumentsList
|
||||
|
||||
companion object {
|
||||
fun simple(vararg signature: Matcher): Signature {
|
||||
return SimpleSignature(*signature)
|
||||
}
|
||||
|
||||
fun vararg(varargMatcher: Matcher, vararg signature: Matcher): Signature {
|
||||
return VarargSignature(varargMatcher, *signature)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package io.smnp.callable.signature
|
||||
|
||||
import io.smnp.type.matcher.Matcher
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
class SimpleSignature(private vararg val signature: Matcher) :
|
||||
Signature {
|
||||
override fun parse(arguments: List<Value>): ArgumentsList {
|
||||
if (arguments.size > signature.size || arguments.size < signature.count { !it.optional }) {
|
||||
return ArgumentsList.invalid()
|
||||
}
|
||||
|
||||
return ArgumentsList(signature.zip(arguments).all { (matcher, argument) ->
|
||||
matcher.match(
|
||||
argument
|
||||
)
|
||||
}, arguments)
|
||||
}
|
||||
|
||||
override fun toString() = "(${signature.joinToString(", ")})"
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package io.smnp.callable.signature
|
||||
|
||||
import io.smnp.type.matcher.Matcher
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
class VarargSignature(private val varargMatcher: Matcher, private vararg val signature: Matcher) :
|
||||
Signature {
|
||||
override fun parse(arguments: List<Value>): ArgumentsList {
|
||||
if ((arrayListOf(varargMatcher) + signature).any { it.optional }) {
|
||||
throw RuntimeException("Vararg signature does not support optional arguments")
|
||||
}
|
||||
|
||||
if (signature.size > arguments.size) {
|
||||
return ArgumentsList.invalid()
|
||||
}
|
||||
|
||||
for (i in signature.indices) {
|
||||
if (!signature[i].match(arguments[i])) {
|
||||
return ArgumentsList.invalid()
|
||||
}
|
||||
}
|
||||
|
||||
for (i in signature.size until arguments.size) {
|
||||
if (!varargMatcher.match(arguments[i])) {
|
||||
return ArgumentsList.invalid()
|
||||
}
|
||||
}
|
||||
|
||||
return ArgumentsList.valid(
|
||||
arguments.subList(0, signature.size) + listOf(
|
||||
Value.list(
|
||||
arguments.subList(
|
||||
signature.size,
|
||||
arguments.size
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun toString() =
|
||||
"(${signature.joinToString(", ")}${if (signature.isNotEmpty()) ", " else ""}...$varargMatcher)"
|
||||
}
|
||||
Reference in New Issue
Block a user