Abacus/core/src/main/kotlin/org/nwapw/abacus/tree/NumberReducer.kt

65 lines
2.9 KiB
Kotlin
Raw Normal View History

2017-09-06 20:39:38 -07:00
package org.nwapw.abacus.tree
import org.nwapw.abacus.Abacus
2017-09-06 22:54:21 -07:00
import org.nwapw.abacus.context.EvaluationContext
import org.nwapw.abacus.exception.NumberReducerException
import org.nwapw.abacus.exception.ReductionException
2017-09-06 20:39:38 -07:00
import org.nwapw.abacus.number.NumberInterface
2017-09-06 22:54:21 -07:00
class NumberReducer(val abacus: Abacus, context: EvaluationContext) : Reducer<NumberInterface> {
val context = context.mutableSubInstance()
init {
this.context.reducer = this
}
2017-09-06 20:39:38 -07:00
2017-09-07 12:53:12 -07:00
override fun reduceNode(treeNode: TreeNode, vararg children: Any): NumberInterface {
2017-09-06 20:39:38 -07:00
val promotionManager = abacus.promotionManager
return when(treeNode){
is NumberNode -> {
context.inheritedNumberImplementation.instanceForString(treeNode.number)
2017-09-06 20:39:38 -07:00
}
is VariableNode -> {
val variable = context.getVariable(treeNode.variable)
if(variable != null) return variable
val definition = context.getDefinition(treeNode.variable)
if(definition != null) return definition.reduce(this)
throw NumberReducerException("variable is not defined.")
2017-09-06 20:39:38 -07:00
}
is NumberUnaryNode -> {
val child = children[0] as NumberInterface
context.numberImplementation = abacus.pluginManager.interfaceImplementationFor(child.javaClass)
2017-09-06 20:39:38 -07:00
abacus.pluginManager.operatorFor(treeNode.operation)
.apply(context, child)
2017-09-06 20:39:38 -07:00
}
is NumberBinaryNode -> {
val left = children[0] as NumberInterface
val right = children[1] as NumberInterface
val promotionResult = promotionManager.promote(left, right)
context.numberImplementation = promotionResult.promotedTo
abacus.pluginManager.operatorFor(treeNode.operation).apply(context, *promotionResult.items)
2017-09-06 20:39:38 -07:00
}
is FunctionNode -> {
val promotionResult = promotionManager
.promote(*children.map { it as NumberInterface }.toTypedArray())
context.numberImplementation = promotionResult.promotedTo
abacus.pluginManager.functionFor(treeNode.callTo).apply(context, *promotionResult.items)
2017-09-06 20:39:38 -07:00
}
is TreeValueUnaryNode -> {
abacus.pluginManager.treeValueOperatorFor(treeNode.operation)
2017-09-07 12:53:12 -07:00
.apply(context, treeNode.applyTo)
2017-09-06 20:39:38 -07:00
}
is TreeValueBinaryNode -> {
abacus.pluginManager.treeValueOperatorFor(treeNode.operation)
2017-09-07 12:53:12 -07:00
.apply(context, treeNode.left, treeNode.right)
2017-09-06 20:39:38 -07:00
}
is TreeValueFunctionNode -> {
abacus.pluginManager.treeValueFunctionFor(treeNode.callTo)
.apply(context, *treeNode.children.toTypedArray())
2017-09-06 20:39:38 -07:00
}
else -> throw ReductionException("unrecognized tree node.")
2017-09-06 20:39:38 -07:00
}
}
}