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

115 lines
3.7 KiB
Kotlin
Raw Normal View History

2017-09-01 23:52:05 -07:00
package org.nwapw.abacus
import org.nwapw.abacus.config.Configuration
2017-09-06 22:54:21 -07:00
import org.nwapw.abacus.context.MutableEvaluationContext
import org.nwapw.abacus.context.EvaluationContext
2017-09-01 23:52:05 -07:00
import org.nwapw.abacus.number.PromotionManager
import org.nwapw.abacus.parsing.LexerTokenizer
import org.nwapw.abacus.parsing.ShuntingYardParser
import org.nwapw.abacus.parsing.TreeBuilder
import org.nwapw.abacus.plugin.PluginManager
import org.nwapw.abacus.plugin.StandardPlugin
import org.nwapw.abacus.tree.EvaluationResult
2017-09-01 23:52:05 -07:00
import org.nwapw.abacus.tree.NumberReducer
import org.nwapw.abacus.tree.TreeNode
/**
* Core class to handle all mathematics.
*
* The main calculator class. This is responsible
* for piecing together all of the components, allowing
* their interaction with each other.
*
* @property configuration the configuration to use.
*/
class Abacus(val configuration: Configuration) {
/**
* The tokenizer used to convert strings into tokens.
*/
private val tokenizer = LexerTokenizer()
/**
* Parser the parser used to convert tokens into trees.
*/
private val parser = ShuntingYardParser()
/**
* The plugin manager used to handle loading and unloading plugins.
*/
val pluginManager = PluginManager(this)
/**
* The tree builder that handles the conversion of strings into trees.
*/
val treeBuilder = TreeBuilder(tokenizer, parser)
/**
* The promotion manager used to convert between number implementations.
*/
val promotionManager = PromotionManager(this)
2017-09-06 20:39:38 -07:00
/**
* The hidden, mutable implementation of the context.
*/
2017-09-06 22:54:21 -07:00
private val mutableContext = MutableEvaluationContext(numberImplementation = StandardPlugin.IMPLEMENTATION_NAIVE)
2017-09-01 23:52:05 -07:00
/**
2017-09-06 20:39:38 -07:00
* The base context from which calculations are started.
2017-09-01 23:52:05 -07:00
*/
2017-09-06 22:54:21 -07:00
val context: EvaluationContext
2017-09-06 20:39:38 -07:00
get() = mutableContext
2017-09-01 23:52:05 -07:00
init {
pluginManager.addListener(tokenizer)
pluginManager.addListener(parser)
pluginManager.addListener(promotionManager)
}
/**
* Reloads the Abacus core.
*/
fun reload(){
pluginManager.reload()
with(mutableContext) {
numberImplementation = pluginManager.numberImplementationFor(configuration.numberImplementation)
?: StandardPlugin.IMPLEMENTATION_NAIVE
clearVariables()
clearDefinitions()
}
}
/**
* Merges the current context with the provided one, updating
* variables and the like.
* @param context the context to apply.
*/
2017-09-06 22:54:21 -07:00
fun applyToContext(context: EvaluationContext){
mutableContext.apply(context)
}
2017-09-01 23:52:05 -07:00
/**
* Parses a string into a tree structure using the main
* tree builder.
*
* @param input the input string to parse
* @return the resulting tree, null if the tree builder or the produced tree are null.
*/
fun parseString(input: String): TreeNode = treeBuilder.fromString(input)
2017-09-01 23:52:05 -07:00
/**
2017-09-06 22:54:21 -07:00
* Evaluates the given tree.
2017-09-01 23:52:05 -07:00
*
* @param tree the tree to reduce, must not be null.
2017-09-06 22:54:21 -07:00
* @return the evaluation result.
2017-09-01 23:52:05 -07:00
*/
fun evaluateTree(tree: TreeNode): EvaluationResult {
2017-09-06 22:54:21 -07:00
return evaluateTreeWithContext(tree, context.mutableSubInstance())
}
/**
* Evaluates the given tree using a different context than
* the default one.
*
* @param tree the tree to reduce, must not be null.
* @param context the context to use for the evaluation.
* @return the evaluation result.
*/
fun evaluateTreeWithContext(tree: TreeNode, context: MutableEvaluationContext): EvaluationResult {
val newReducer = NumberReducer(this, context)
val evaluationValue = tree.reduce(newReducer)
return EvaluationResult(evaluationValue, newReducer.context)
}
2017-09-01 23:52:05 -07:00
}