mirror of
https://github.com/DanilaFe/abacus
synced 2026-01-31 19:15:20 +00:00
Merge branch 'master' into thread-safety
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
package org.nwapw.abacus.function.applicable
|
||||
|
||||
import org.nwapw.abacus.context.MutableEvaluationContext
|
||||
import org.nwapw.abacus.function.DomainException
|
||||
import org.nwapw.abacus.exception.DomainException
|
||||
|
||||
/**
|
||||
* A class that can be applied to arguments.
|
||||
@@ -36,7 +36,8 @@ interface Applicable<in T : Any, out O : Any> {
|
||||
* @return the result of the operation, or null if parameters do not match.
|
||||
*/
|
||||
fun apply(context: MutableEvaluationContext, vararg params: T): O {
|
||||
if (!matchesParams(context, params)) throw DomainException()
|
||||
if (!matchesParams(context, params))
|
||||
throw DomainException("parameters do not match function requirements.")
|
||||
return applyInternal(context, params)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ package org.nwapw.abacus.tree
|
||||
* @param left the left node.
|
||||
* @param right the right node.
|
||||
*/
|
||||
abstract class BinaryNode(val operation: String, val left: TreeNode? = null, val right: TreeNode?) : TreeNode() {
|
||||
abstract class BinaryNode(val operation: String, val left: TreeNode, val right: TreeNode) : TreeNode() {
|
||||
|
||||
override fun toString(): String {
|
||||
return "(" + (left?.toString() ?: "null") + operation + (right?.toString() ?: "null") + ")"
|
||||
return "(" + left.toString() + operation + right.toString() + ")"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,13 +7,9 @@ package org.nwapw.abacus.tree
|
||||
* to extend this functionality.
|
||||
*
|
||||
* @param callTo the name of the things being called.
|
||||
* @param children the children of this node.
|
||||
*/
|
||||
abstract class CallNode(val callTo: String) : TreeNode() {
|
||||
|
||||
/**
|
||||
* The list of children this node has.
|
||||
*/
|
||||
val children: MutableList<TreeNode> = mutableListOf()
|
||||
abstract class CallNode(val callTo: String, val children: List<TreeNode>) : TreeNode() {
|
||||
|
||||
override fun toString(): String {
|
||||
val buffer = StringBuffer()
|
||||
|
||||
@@ -3,4 +3,4 @@ package org.nwapw.abacus.tree
|
||||
import org.nwapw.abacus.context.MutableEvaluationContext
|
||||
import org.nwapw.abacus.number.NumberInterface
|
||||
|
||||
data class EvaluationResult(val value: NumberInterface?, val resultingContext: MutableEvaluationContext)
|
||||
data class EvaluationResult(val value: NumberInterface, val resultingContext: MutableEvaluationContext)
|
||||
@@ -8,10 +8,10 @@ package org.nwapw.abacus.tree
|
||||
*
|
||||
* @param function the function string.
|
||||
*/
|
||||
class FunctionNode(function: String) : CallNode(function) {
|
||||
class FunctionNode(function: String, children: List<TreeNode>) : CallNode(function, children) {
|
||||
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||
val children = Array<Any>(children.size, { children[it].reduce(reducer) ?: return null; })
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T {
|
||||
val children = Array<Any>(children.size, { children[it].reduce(reducer) })
|
||||
return reducer.reduceNode(this, *children)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ package org.nwapw.abacus.tree
|
||||
* @param left the left child of this node.
|
||||
* @param right the right child of this node.
|
||||
*/
|
||||
class NumberBinaryNode(operation: String, left: TreeNode?, right: TreeNode?)
|
||||
class NumberBinaryNode(operation: String, left: TreeNode, right: TreeNode)
|
||||
: BinaryNode(operation, left, right) {
|
||||
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||
val left = left?.reduce(reducer) ?: return null
|
||||
val right = right?.reduce(reducer) ?: return null
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T {
|
||||
val left = left.reduce(reducer)
|
||||
val right = right.reduce(reducer)
|
||||
return reducer.reduceNode(this, left, right)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ package org.nwapw.abacus.tree
|
||||
*/
|
||||
class NumberNode(val number: String) : TreeNode() {
|
||||
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T {
|
||||
return reducer.reduceNode(this)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.nwapw.abacus.tree
|
||||
|
||||
import org.nwapw.abacus.Abacus
|
||||
import org.nwapw.abacus.context.EvaluationContext
|
||||
import org.nwapw.abacus.exception.EvaluationException
|
||||
import org.nwapw.abacus.number.NumberInterface
|
||||
|
||||
class NumberReducer(val abacus: Abacus, context: EvaluationContext) : Reducer<NumberInterface> {
|
||||
@@ -12,18 +13,19 @@ class NumberReducer(val abacus: Abacus, context: EvaluationContext) : Reducer<Nu
|
||||
this.context.reducer = this
|
||||
}
|
||||
|
||||
override fun reduceNode(treeNode: TreeNode, vararg children: Any): NumberInterface? {
|
||||
override fun reduceNode(treeNode: TreeNode, vararg children: Any): NumberInterface {
|
||||
val promotionManager = abacus.promotionManager
|
||||
return when(treeNode){
|
||||
is NumberNode -> {
|
||||
context.inheritedNumberImplementation?.instanceForString(treeNode.number)
|
||||
?: throw EvaluationException("no number implementation selected.")
|
||||
}
|
||||
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
|
||||
throw EvaluationException("variable is not defined.")
|
||||
}
|
||||
is NumberUnaryNode -> {
|
||||
val child = children[0] as NumberInterface
|
||||
@@ -34,29 +36,31 @@ class NumberReducer(val abacus: Abacus, context: EvaluationContext) : Reducer<Nu
|
||||
is NumberBinaryNode -> {
|
||||
val left = children[0] as NumberInterface
|
||||
val right = children[1] as NumberInterface
|
||||
val promotionResult = promotionManager.promote(left, right) ?: return null
|
||||
val promotionResult = promotionManager.promote(left, right) ?:
|
||||
throw EvaluationException("promotion failed.")
|
||||
context.numberImplementation = promotionResult.promotedTo
|
||||
abacus.pluginManager.operatorFor(treeNode.operation).apply(context, *promotionResult.items)
|
||||
}
|
||||
is FunctionNode -> {
|
||||
val promotionResult = promotionManager
|
||||
.promote(*children.map { it as NumberInterface }.toTypedArray()) ?: return null
|
||||
.promote(*children.map { it as NumberInterface }.toTypedArray()) ?:
|
||||
throw EvaluationException("promotion failed.")
|
||||
context.numberImplementation = promotionResult.promotedTo
|
||||
abacus.pluginManager.functionFor(treeNode.callTo).apply(context, *promotionResult.items)
|
||||
}
|
||||
is TreeValueUnaryNode -> {
|
||||
abacus.pluginManager.treeValueOperatorFor(treeNode.operation)
|
||||
.apply(context, treeNode.applyTo ?: return null)
|
||||
.apply(context, treeNode.applyTo)
|
||||
}
|
||||
is TreeValueBinaryNode -> {
|
||||
abacus.pluginManager.treeValueOperatorFor(treeNode.operation)
|
||||
.apply(context, treeNode.left ?: return null, treeNode.right ?: return null)
|
||||
.apply(context, treeNode.left, treeNode.right)
|
||||
}
|
||||
is TreeValueFunctionNode -> {
|
||||
abacus.pluginManager.treeValueFunctionFor(treeNode.callTo)
|
||||
.apply(context, *treeNode.children.toTypedArray())
|
||||
}
|
||||
else -> null
|
||||
else -> throw EvaluationException("unrecognized tree node.")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ package org.nwapw.abacus.tree
|
||||
* @param operation the operation this node performs.
|
||||
* @param child the child this node should be applied to.
|
||||
*/
|
||||
class NumberUnaryNode(operation: String, child: TreeNode?)
|
||||
class NumberUnaryNode(operation: String, child: TreeNode)
|
||||
: UnaryNode(operation, child) {
|
||||
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||
val child = applyTo?.reduce(reducer) ?: return null
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T {
|
||||
val child = applyTo.reduce(reducer)
|
||||
return reducer.reduceNode(this, child)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,6 @@ interface Reducer<out T> {
|
||||
* @param treeNode the tree node to reduce.
|
||||
* @param children the list of children, of type T.
|
||||
*/
|
||||
fun reduceNode(treeNode: TreeNode, vararg children: Any): T?
|
||||
fun reduceNode(treeNode: TreeNode, vararg children: Any): T
|
||||
|
||||
}
|
||||
@@ -5,6 +5,6 @@ package org.nwapw.abacus.tree
|
||||
*/
|
||||
abstract class TreeNode {
|
||||
|
||||
abstract fun <T : Any> reduce(reducer: Reducer<T>): T?
|
||||
abstract fun <T : Any> reduce(reducer: Reducer<T>): T
|
||||
|
||||
}
|
||||
@@ -11,10 +11,10 @@ package org.nwapw.abacus.tree
|
||||
* @param left the left child of this node.
|
||||
* @param right the right child of this node.
|
||||
*/
|
||||
class TreeValueBinaryNode(operation: String, left: TreeNode?, right: TreeNode?)
|
||||
class TreeValueBinaryNode(operation: String, left: TreeNode, right: TreeNode)
|
||||
: BinaryNode(operation, left, right) {
|
||||
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T {
|
||||
return reducer.reduceNode(this)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ package org.nwapw.abacus.tree
|
||||
* is mostly to help the reducer. Besides that, this class also does not
|
||||
* even attempt to reduce its children.
|
||||
*/
|
||||
class TreeValueFunctionNode(name: String) : CallNode(name) {
|
||||
class TreeValueFunctionNode(name: String, children: List<TreeNode>) : CallNode(name, children) {
|
||||
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T {
|
||||
return reducer.reduceNode(this)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,11 @@ package org.nwapw.abacus.tree
|
||||
* @param operation the operation this node performs.
|
||||
* @param child the node the operation should be applied to.
|
||||
*/
|
||||
class TreeValueUnaryNode(operation: String, child: TreeNode?)
|
||||
class TreeValueUnaryNode(operation: String, child: TreeNode)
|
||||
: UnaryNode(operation, child) {
|
||||
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||
return reducer.reduceNode(this);
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T {
|
||||
return reducer.reduceNode(this)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,10 +9,10 @@ package org.nwapw.abacus.tree
|
||||
* @param operation the operation applied to the given node.
|
||||
* @param applyTo the node to which the operation will be applied.
|
||||
*/
|
||||
abstract class UnaryNode(val operation: String, val applyTo: TreeNode? = null) : TreeNode() {
|
||||
abstract class UnaryNode(val operation: String, val applyTo: TreeNode) : TreeNode() {
|
||||
|
||||
override fun toString(): String {
|
||||
return "(" + (applyTo?.toString() ?: "null") + ")" + operation
|
||||
return "(" + applyTo.toString() + ")" + operation
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,7 +10,7 @@ package org.nwapw.abacus.tree
|
||||
*/
|
||||
class VariableNode(val variable: String) : TreeNode() {
|
||||
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||
override fun <T : Any> reduce(reducer: Reducer<T>): T {
|
||||
return reducer.reduceNode(this)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user