mirror of
https://github.com/DanilaFe/abacus
synced 2026-01-31 19:15:20 +00:00
Rewrite number reducer in Kotlin.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package org.nwapw.abacus
|
||||
|
||||
import org.nwapw.abacus.config.Configuration
|
||||
import org.nwapw.abacus.context.MutableReductionContext
|
||||
import org.nwapw.abacus.context.ReductionContext
|
||||
import org.nwapw.abacus.number.NumberInterface
|
||||
import org.nwapw.abacus.number.PromotionManager
|
||||
import org.nwapw.abacus.parsing.LexerTokenizer
|
||||
@@ -36,10 +38,6 @@ class Abacus(val configuration: Configuration) {
|
||||
* The plugin manager used to handle loading and unloading plugins.
|
||||
*/
|
||||
val pluginManager = PluginManager(this)
|
||||
/**
|
||||
* The reducer used to turn trees into a single number.
|
||||
*/
|
||||
val numberReducer = NumberReducer(this)
|
||||
/**
|
||||
* The tree builder that handles the conversion of strings into trees.
|
||||
*/
|
||||
@@ -52,16 +50,16 @@ class Abacus(val configuration: Configuration) {
|
||||
* The database of variable definitions.
|
||||
*/
|
||||
val variableDatabase = VariableDatabase(this)
|
||||
|
||||
/**
|
||||
* The number implementation used by default.
|
||||
* The hidden, mutable implementation of the context.
|
||||
*/
|
||||
val numberImplementation: NumberImplementation
|
||||
get() {
|
||||
val selectedImplementation =
|
||||
pluginManager.numberImplementationFor(configuration.numberImplementation)
|
||||
if (selectedImplementation != null) return selectedImplementation
|
||||
return StandardPlugin.IMPLEMENTATION_NAIVE
|
||||
}
|
||||
private val mutableContext = MutableReductionContext(numberImplementation = StandardPlugin.IMPLEMENTATION_NAIVE)
|
||||
/**
|
||||
* The base context from which calculations are started.
|
||||
*/
|
||||
val context: ReductionContext
|
||||
get() = mutableContext
|
||||
|
||||
init {
|
||||
pluginManager.addListener(tokenizer)
|
||||
@@ -85,6 +83,7 @@ class Abacus(val configuration: Configuration) {
|
||||
* @param tree the tree to reduce, must not be null.
|
||||
* @return the resulting number, or null of the reduction failed.
|
||||
*/
|
||||
fun evaluateTree(tree: TreeNode): NumberInterface? = tree.reduce(numberReducer)
|
||||
fun evaluateTree(tree: TreeNode): NumberInterface? =
|
||||
tree.reduce(NumberReducer(this, context.mutableSubInstance()))
|
||||
|
||||
}
|
||||
57
core/src/main/kotlin/org/nwapw/abacus/tree/NumberReducer.kt
Normal file
57
core/src/main/kotlin/org/nwapw/abacus/tree/NumberReducer.kt
Normal file
@@ -0,0 +1,57 @@
|
||||
package org.nwapw.abacus.tree
|
||||
|
||||
import org.nwapw.abacus.Abacus
|
||||
import org.nwapw.abacus.context.MutableReductionContext
|
||||
import org.nwapw.abacus.function.NumberFunction
|
||||
import org.nwapw.abacus.number.NumberInterface
|
||||
|
||||
class NumberReducer(val abacus: Abacus, val context: MutableReductionContext) : Reducer<NumberInterface> {
|
||||
|
||||
override fun reduceNode(treeNode: TreeNode, vararg children: Any): NumberInterface? {
|
||||
val promotionManager = abacus.promotionManager
|
||||
return when(treeNode){
|
||||
is NumberNode -> {
|
||||
context.inheritedNumberImplementation?.instanceForString(treeNode.number)
|
||||
}
|
||||
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)
|
||||
null
|
||||
}
|
||||
is NumberUnaryNode -> {
|
||||
val child = children[0] as NumberInterface
|
||||
abacus.pluginManager.operatorFor(treeNode.operation)
|
||||
.apply(abacus.pluginManager.interfaceImplementationFor(child.javaClass), child)
|
||||
}
|
||||
is NumberBinaryNode -> {
|
||||
val left = children[0] as NumberInterface
|
||||
val right = children[1] as NumberInterface
|
||||
val promotionResult = promotionManager.promote(left, right) ?: return null
|
||||
abacus.pluginManager.operatorFor(treeNode.operation).apply(promotionResult.promotedTo, *promotionResult.items)
|
||||
}
|
||||
is FunctionNode -> {
|
||||
val promotionResult = promotionManager
|
||||
.promote(*children.map { it as NumberInterface }.toTypedArray()) ?: return null
|
||||
abacus.pluginManager.functionFor(treeNode.callTo).apply(promotionResult.promotedTo, *promotionResult.items)
|
||||
}
|
||||
is TreeValueUnaryNode -> {
|
||||
abacus.pluginManager.treeValueOperatorFor(treeNode.operation)
|
||||
.applyWithReducer(context.inheritedNumberImplementation!!, this, children[0] as TreeNode)
|
||||
}
|
||||
is TreeValueBinaryNode -> {
|
||||
abacus.pluginManager.treeValueOperatorFor(treeNode.operation)
|
||||
.applyWithReducer(context.inheritedNumberImplementation!!, this,
|
||||
children[0] as TreeNode, children[1] as TreeNode)
|
||||
}
|
||||
is TreeValueFunctionNode -> {
|
||||
abacus.pluginManager.treeValueFunctionFor(treeNode.callTo)
|
||||
.applyWithReducer(context.inheritedNumberImplementation!!, this,
|
||||
*children.map { it as TreeNode }.toTypedArray())
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user