Add support for defining custom methods
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package io.smnp.callable.function
|
||||
|
||||
import io.smnp.callable.util.FunctionEnvironmentProvider
|
||||
import io.smnp.callable.util.FunctionSignatureParser
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionArgumentsNode
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionNode
|
||||
import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
|
||||
42
app/src/main/kotlin/io/smnp/callable/method/CustomMethod.kt
Normal file
42
app/src/main/kotlin/io/smnp/callable/method/CustomMethod.kt
Normal file
@@ -0,0 +1,42 @@
|
||||
package io.smnp.callable.method
|
||||
|
||||
import io.smnp.callable.util.FunctionEnvironmentProvider
|
||||
import io.smnp.callable.util.FunctionSignatureParser
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionArgumentsNode
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionNode
|
||||
import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
import io.smnp.evaluation.evaluator.BlockEvaluator
|
||||
import io.smnp.evaluation.model.exception.Return
|
||||
import io.smnp.type.matcher.Matcher
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
object CustomMethod {
|
||||
fun create(type: Matcher, objectIdentifier: String, node: FunctionDefinitionNode): Method {
|
||||
val identifier = (node.identifier as IdentifierNode).token.rawValue
|
||||
|
||||
return object : Method(type, identifier) {
|
||||
override fun define(new: MethodDefinitionTool) {
|
||||
val (_, argumentsNode, bodyNode) = node
|
||||
val signature = FunctionSignatureParser.parseSignature(argumentsNode as FunctionDefinitionArgumentsNode)
|
||||
val evaluator = BlockEvaluator(dedicatedScope = false)
|
||||
|
||||
new method signature body { env, obj, args ->
|
||||
val boundArguments =
|
||||
FunctionEnvironmentProvider.provideEnvironment(argumentsNode, args, env).toMutableMap()
|
||||
boundArguments[objectIdentifier] = obj
|
||||
|
||||
try {
|
||||
env.pushScope(boundArguments)
|
||||
evaluator.evaluate(bodyNode, env)
|
||||
} catch (value: Return) {
|
||||
return@body value.value
|
||||
} finally {
|
||||
env.popScope()
|
||||
}
|
||||
|
||||
Value.void()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package io.smnp.callable.function
|
||||
package io.smnp.callable.util
|
||||
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionArgumentsNode
|
||||
import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
@@ -1,4 +1,4 @@
|
||||
package io.smnp.callable.function
|
||||
package io.smnp.callable.util
|
||||
|
||||
import io.smnp.callable.signature.Signature
|
||||
import io.smnp.dsl.ast.model.node.*
|
||||
@@ -54,7 +54,11 @@ object FunctionSignatureParser {
|
||||
val vararg =
|
||||
signature.items.indexOfFirst { it is RegularFunctionDefinitionArgumentNode && it.vararg != Node.NONE }
|
||||
|
||||
val metadata = SignatureMetadata(lastRegular != -1, firstOptional != -1, vararg != -1)
|
||||
val metadata = SignatureMetadata(
|
||||
lastRegular != -1,
|
||||
firstOptional != -1,
|
||||
vararg != -1
|
||||
)
|
||||
|
||||
if (metadata.hasVararg && metadata.hasOptional) {
|
||||
throw RuntimeException("Optional arguments and vararg cannot be mixed in same signature")
|
||||
@@ -77,13 +81,19 @@ object FunctionSignatureParser {
|
||||
}
|
||||
|
||||
if (unionTypeNode.items.size == 1) {
|
||||
return matcherForSingleTypeNode(unionTypeNode.items[0] as SingleTypeNode)
|
||||
return matcherForSingleTypeNode(
|
||||
unionTypeNode.items[0] as SingleTypeNode
|
||||
)
|
||||
}
|
||||
|
||||
return oneOf(*unionTypeNode.items.map { matcherForSingleTypeNode(it as SingleTypeNode) }.toTypedArray())
|
||||
return oneOf(*unionTypeNode.items.map {
|
||||
matcherForSingleTypeNode(
|
||||
it as SingleTypeNode
|
||||
)
|
||||
}.toTypedArray())
|
||||
}
|
||||
|
||||
private fun matcherForSingleTypeNode(singleTypeNode: SingleTypeNode): Matcher {
|
||||
fun matcherForSingleTypeNode(singleTypeNode: SingleTypeNode): Matcher {
|
||||
// TODO
|
||||
val type = DataType.valueOf((singleTypeNode.type as IdentifierNode).token.rawValue.toUpperCase())
|
||||
if (singleTypeNode.specifiers == Node.NONE) {
|
||||
@@ -107,7 +117,11 @@ object FunctionSignatureParser {
|
||||
types.add(allTypes())
|
||||
}
|
||||
|
||||
listSpecifierNode.items.forEach { types.add(matcherForSingleTypeNode(it as SingleTypeNode)) }
|
||||
listSpecifierNode.items.forEach { types.add(
|
||||
matcherForSingleTypeNode(
|
||||
it as SingleTypeNode
|
||||
)
|
||||
) }
|
||||
|
||||
return listOfMatchers(*types.toTypedArray())
|
||||
}
|
||||
@@ -124,8 +138,16 @@ object FunctionSignatureParser {
|
||||
values.add(allTypes())
|
||||
}
|
||||
|
||||
keySpecifierNode.items.forEach { keys.add(matcherForSingleTypeNode(it as SingleTypeNode)) }
|
||||
valueSpecifierNode.items.forEach { values.add(matcherForSingleTypeNode(it as SingleTypeNode)) }
|
||||
keySpecifierNode.items.forEach { keys.add(
|
||||
matcherForSingleTypeNode(
|
||||
it as SingleTypeNode
|
||||
)
|
||||
) }
|
||||
valueSpecifierNode.items.forEach { values.add(
|
||||
matcherForSingleTypeNode(
|
||||
it as SingleTypeNode
|
||||
)
|
||||
) }
|
||||
|
||||
return mapOfMatchers(keys, values)
|
||||
}
|
||||
Reference in New Issue
Block a user