[BIG REFACTOR] Create new project structure and prepare scaffolding for external modules system

This commit is contained in:
2020-03-09 19:30:43 +01:00
parent ae9406cc50
commit dcdecee28f
155 changed files with 290 additions and 192 deletions

View 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}" }
}

View File

@@ -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)

View File

@@ -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))
}
}
}

View 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}" }
}

View File

@@ -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)

View File

@@ -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))
}
}
}

View File

@@ -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()}}>"
}
}

View File

@@ -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())
}
}
}

View 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)
}
}
}

View File

@@ -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(", ")})"
}

View File

@@ -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)"
}