Create scaffolding for custom functions
This commit is contained in:
@@ -30,7 +30,7 @@ abstract class Function(val name: String) {
|
||||
.firstOrNull { (_, args) -> args.signatureMatched }
|
||||
?: throw FunctionInvocationException(this, arguments)
|
||||
|
||||
return definition.body(environment, arguments.toList())
|
||||
return definition.body(environment, args.arguments)
|
||||
}
|
||||
|
||||
val signature: String
|
||||
|
||||
@@ -2,7 +2,7 @@ package io.smnp.data.entity
|
||||
|
||||
import io.smnp.data.enumeration.Pitch
|
||||
|
||||
class Note private constructor(val pitch: Pitch, val octave: Int, val duration: Int, val dot: Boolean) {
|
||||
data class Note (val pitch: Pitch, val octave: Int, val duration: Int, val dot: Boolean) {
|
||||
data class Builder(var pitch: Pitch = Pitch.A, var octave: Int = 4, var duration: Int = 4, var dot: Boolean = false) {
|
||||
fun pitch(pitch: Pitch) = apply { this.pitch = pitch }
|
||||
fun octave(octave: Int) = apply { this.octave = octave }
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.smnp.environment
|
||||
|
||||
import io.smnp.callable.function.Function
|
||||
import io.smnp.callable.method.Method
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
interface Environment {
|
||||
@@ -8,4 +10,6 @@ interface Environment {
|
||||
fun invokeFunction(name: String, arguments: List<Value>): Value
|
||||
fun invokeMethod(obj: Value, name: String, arguments: List<Value>): Value
|
||||
fun printCallStack()
|
||||
fun defineFunction(function: Function)
|
||||
fun defineMethod(method: Method)
|
||||
}
|
||||
@@ -32,8 +32,14 @@ class Module(
|
||||
}
|
||||
}
|
||||
|
||||
fun attachTo(module: Module) {
|
||||
module.addSubmodule(this)
|
||||
fun addFunction(function: Function) {
|
||||
function.module = this
|
||||
functions.add(function)
|
||||
}
|
||||
|
||||
fun addMethod(method: Method) {
|
||||
method.module = this
|
||||
methods.add(method)
|
||||
}
|
||||
|
||||
val canonicalName: String
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package io.smnp.callable.function
|
||||
|
||||
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.type.model.Value
|
||||
|
||||
object CustomFunction {
|
||||
fun create(node: FunctionDefinitionNode): Function {
|
||||
val identifier = (node.identifier as IdentifierNode).token.rawValue
|
||||
|
||||
return object : Function(identifier) {
|
||||
override fun define(new: FunctionDefinitionTool) {
|
||||
val (_, argumentsNode, bodyNode) = node
|
||||
val signature = FunctionSignatureParser.parseSignature(argumentsNode as FunctionDefinitionArgumentsNode)
|
||||
|
||||
new function signature define { env, args ->
|
||||
val boundArguments = FunctionEnvironmentProvider.provideEnvironment(argumentsNode, args, env)
|
||||
// TODO(Implement bodyNode evaluation)
|
||||
Value.void()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package io.smnp.callable.function
|
||||
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionArgumentsNode
|
||||
import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
import io.smnp.dsl.ast.model.node.OptionalFunctionDefinitionArgumentNode
|
||||
import io.smnp.dsl.ast.model.node.RegularFunctionDefinitionArgumentNode
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.ShouldNeverReachThisLineException
|
||||
import io.smnp.evaluation.evaluator.ExpressionEvaluator
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
object FunctionEnvironmentProvider {
|
||||
fun provideEnvironment(signature: FunctionDefinitionArgumentsNode, actualArgs: List<Value>, environment: Environment): Map<String, Value> {
|
||||
val evaluator = ExpressionEvaluator()
|
||||
return signature.items.mapIndexed { index, node ->
|
||||
when (node) {
|
||||
is RegularFunctionDefinitionArgumentNode -> (node.identifier as IdentifierNode).token.rawValue to actualArgs[index]
|
||||
is OptionalFunctionDefinitionArgumentNode -> (node.identifier as IdentifierNode).token.rawValue to evaluator.evaluate(
|
||||
node.defaultValue,
|
||||
environment
|
||||
).value!!
|
||||
else -> throw ShouldNeverReachThisLineException()
|
||||
}
|
||||
}.toMap()
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,10 @@ package io.smnp.dsl.ast.model.node
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class FunctionDefinitionNode(identifier: Node, arguments: Node, body: Node, position: TokenPosition) : Node(3, position) {
|
||||
operator fun component1() = children[0]
|
||||
operator fun component2() = children[1]
|
||||
operator fun component3() = children[2]
|
||||
|
||||
val identifier: Node
|
||||
get() = children[0]
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.smnp.environment
|
||||
|
||||
import io.smnp.callable.function.Function
|
||||
import io.smnp.callable.method.Method
|
||||
import io.smnp.callable.signature.ActualSignatureFormatter.format
|
||||
import io.smnp.ext.DefaultModuleRegistry
|
||||
import io.smnp.runtime.model.CallStack
|
||||
@@ -69,4 +71,12 @@ class DefaultEnvironment : Environment {
|
||||
override fun printCallStack() {
|
||||
callStack.pretty()
|
||||
}
|
||||
|
||||
override fun defineFunction(function: Function) {
|
||||
rootModule.addFunction(function)
|
||||
}
|
||||
|
||||
override fun defineMethod(method: Method) {
|
||||
rootModule.addMethod(method)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.smnp.evaluation.evaluator
|
||||
|
||||
import io.smnp.callable.function.CustomFunction
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
|
||||
class FunctionDefinitionEvaluator : Evaluator() {
|
||||
override fun supportedNodes() = listOf(FunctionDefinitionNode::class)
|
||||
|
||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||
val function = CustomFunction.create(node as FunctionDefinitionNode)
|
||||
environment.defineFunction(function)
|
||||
return EvaluatorOutput.ok()
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,11 @@ class RootEvaluator : Evaluator() {
|
||||
override fun supportedNodes() = listOf(RootNode::class)
|
||||
|
||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||
val evaluator = ExpressionEvaluator()
|
||||
val evaluator = oneOf(
|
||||
ExpressionEvaluator(),
|
||||
FunctionDefinitionEvaluator()
|
||||
)
|
||||
|
||||
for(child in node.children) {
|
||||
val output = evaluator.evaluate(child, environment)
|
||||
if(output.result == EvaluationResult.FAILED) {
|
||||
|
||||
Reference in New Issue
Block a user