mirror of
https://github.com/DanilaFe/abacus
synced 2024-12-22 15:30:09 -08:00
Remove nullability from reduction.
This commit is contained in:
parent
1575d3e574
commit
52ab357fe1
|
@ -18,7 +18,7 @@ public class DomainException extends RuntimeException {
|
||||||
* Creates a new DomainException with a default message.
|
* Creates a new DomainException with a default message.
|
||||||
*/
|
*/
|
||||||
public DomainException(){
|
public DomainException(){
|
||||||
this("Domain Error");
|
this("Domain error.");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ public class EvaluationException extends RuntimeException {
|
||||||
* Creates a new EvaluationException with the default string.
|
* Creates a new EvaluationException with the default string.
|
||||||
*/
|
*/
|
||||||
public EvaluationException() {
|
public EvaluationException() {
|
||||||
super("Error evaluating expression.");
|
super("Evaluation error.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -10,7 +10,7 @@ public class ComputationInterruptedException extends RuntimeException {
|
||||||
* Creates a new exception of this type.
|
* Creates a new exception of this type.
|
||||||
*/
|
*/
|
||||||
public ComputationInterruptedException() {
|
public ComputationInterruptedException() {
|
||||||
super("Computation interrupted by user.");
|
super("Computation interrupted.");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,7 @@ public class StandardPlugin extends Plugin {
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(MutableEvaluationContext context, TreeNode[] params) {
|
public NumberInterface applyInternal(MutableEvaluationContext context, TreeNode[] params) {
|
||||||
String assignTo = ((VariableNode) params[0]).getVariable();
|
String assignTo = ((VariableNode) params[0]).getVariable();
|
||||||
NumberInterface value = params[1].reduce(context.getReducer());
|
NumberInterface value = params[1].reduce(context.getInheritedReducer());
|
||||||
if(value == null) throw new EvaluationException();
|
|
||||||
context.setVariable(assignTo, value);
|
context.setVariable(assignTo, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -48,9 +47,7 @@ public class StandardPlugin extends Plugin {
|
||||||
public NumberInterface applyInternal(MutableEvaluationContext context, TreeNode[] params) {
|
public NumberInterface applyInternal(MutableEvaluationContext context, TreeNode[] params) {
|
||||||
String assignTo = ((VariableNode) params[0]).getVariable();
|
String assignTo = ((VariableNode) params[0]).getVariable();
|
||||||
context.setDefinition(assignTo, params[1]);
|
context.setDefinition(assignTo, params[1]);
|
||||||
NumberInterface value = params[1].reduce(context.getReducer());
|
return params[1].reduce(context.getInheritedReducer());
|
||||||
if(value == null) throw new EvaluationException();
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,4 +3,4 @@ package org.nwapw.abacus.tree
|
||||||
import org.nwapw.abacus.context.MutableEvaluationContext
|
import org.nwapw.abacus.context.MutableEvaluationContext
|
||||||
import org.nwapw.abacus.number.NumberInterface
|
import org.nwapw.abacus.number.NumberInterface
|
||||||
|
|
||||||
data class EvaluationResult(val value: NumberInterface?, val resultingContext: MutableEvaluationContext)
|
data class EvaluationResult(val value: NumberInterface, val resultingContext: MutableEvaluationContext)
|
|
@ -10,8 +10,8 @@ package org.nwapw.abacus.tree
|
||||||
*/
|
*/
|
||||||
class FunctionNode(function: String, children: List<TreeNode>) : CallNode(function, children) {
|
class FunctionNode(function: String, children: List<TreeNode>) : CallNode(function, children) {
|
||||||
|
|
||||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
override fun <T : Any> reduce(reducer: Reducer<T>): T {
|
||||||
val children = Array<Any>(children.size, { children[it].reduce(reducer) ?: return null; })
|
val children = Array<Any>(children.size, { children[it].reduce(reducer) })
|
||||||
return reducer.reduceNode(this, *children)
|
return reducer.reduceNode(this, *children)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,9 @@ package org.nwapw.abacus.tree
|
||||||
class NumberBinaryNode(operation: String, left: TreeNode, right: TreeNode)
|
class NumberBinaryNode(operation: String, left: TreeNode, right: TreeNode)
|
||||||
: BinaryNode(operation, left, right) {
|
: BinaryNode(operation, left, right) {
|
||||||
|
|
||||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
override fun <T : Any> reduce(reducer: Reducer<T>): T {
|
||||||
val left = left.reduce(reducer) ?: return null
|
val left = left.reduce(reducer)
|
||||||
val right = right.reduce(reducer) ?: return null
|
val right = right.reduce(reducer)
|
||||||
return reducer.reduceNode(this, left, right)
|
return reducer.reduceNode(this, left, right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ package org.nwapw.abacus.tree
|
||||||
*/
|
*/
|
||||||
class NumberNode(val number: String) : TreeNode() {
|
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)
|
return reducer.reduceNode(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.nwapw.abacus.tree
|
||||||
|
|
||||||
import org.nwapw.abacus.Abacus
|
import org.nwapw.abacus.Abacus
|
||||||
import org.nwapw.abacus.context.EvaluationContext
|
import org.nwapw.abacus.context.EvaluationContext
|
||||||
|
import org.nwapw.abacus.function.EvaluationException
|
||||||
import org.nwapw.abacus.number.NumberInterface
|
import org.nwapw.abacus.number.NumberInterface
|
||||||
|
|
||||||
class NumberReducer(val abacus: Abacus, context: EvaluationContext) : Reducer<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
|
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
|
val promotionManager = abacus.promotionManager
|
||||||
return when(treeNode){
|
return when(treeNode){
|
||||||
is NumberNode -> {
|
is NumberNode -> {
|
||||||
context.inheritedNumberImplementation?.instanceForString(treeNode.number)
|
context.inheritedNumberImplementation?.instanceForString(treeNode.number)
|
||||||
|
?: throw EvaluationException()
|
||||||
}
|
}
|
||||||
is VariableNode -> {
|
is VariableNode -> {
|
||||||
val variable = context.getVariable(treeNode.variable)
|
val variable = context.getVariable(treeNode.variable)
|
||||||
if(variable != null) return variable
|
if(variable != null) return variable
|
||||||
val definition = context.getDefinition(treeNode.variable)
|
val definition = context.getDefinition(treeNode.variable)
|
||||||
if(definition != null) return definition.reduce(this)
|
if(definition != null) return definition.reduce(this)
|
||||||
null
|
throw EvaluationException()
|
||||||
}
|
}
|
||||||
is NumberUnaryNode -> {
|
is NumberUnaryNode -> {
|
||||||
val child = children[0] as NumberInterface
|
val child = children[0] as NumberInterface
|
||||||
|
@ -34,29 +36,29 @@ class NumberReducer(val abacus: Abacus, context: EvaluationContext) : Reducer<Nu
|
||||||
is NumberBinaryNode -> {
|
is NumberBinaryNode -> {
|
||||||
val left = children[0] as NumberInterface
|
val left = children[0] as NumberInterface
|
||||||
val right = children[1] as NumberInterface
|
val right = children[1] as NumberInterface
|
||||||
val promotionResult = promotionManager.promote(left, right) ?: return null
|
val promotionResult = promotionManager.promote(left, right) ?: throw EvaluationException()
|
||||||
context.numberImplementation = promotionResult.promotedTo
|
context.numberImplementation = promotionResult.promotedTo
|
||||||
abacus.pluginManager.operatorFor(treeNode.operation).apply(context, *promotionResult.items)
|
abacus.pluginManager.operatorFor(treeNode.operation).apply(context, *promotionResult.items)
|
||||||
}
|
}
|
||||||
is FunctionNode -> {
|
is FunctionNode -> {
|
||||||
val promotionResult = promotionManager
|
val promotionResult = promotionManager
|
||||||
.promote(*children.map { it as NumberInterface }.toTypedArray()) ?: return null
|
.promote(*children.map { it as NumberInterface }.toTypedArray()) ?: throw EvaluationException()
|
||||||
context.numberImplementation = promotionResult.promotedTo
|
context.numberImplementation = promotionResult.promotedTo
|
||||||
abacus.pluginManager.functionFor(treeNode.callTo).apply(context, *promotionResult.items)
|
abacus.pluginManager.functionFor(treeNode.callTo).apply(context, *promotionResult.items)
|
||||||
}
|
}
|
||||||
is TreeValueUnaryNode -> {
|
is TreeValueUnaryNode -> {
|
||||||
abacus.pluginManager.treeValueOperatorFor(treeNode.operation)
|
abacus.pluginManager.treeValueOperatorFor(treeNode.operation)
|
||||||
.apply(context, treeNode.applyTo ?: return null)
|
.apply(context, treeNode.applyTo)
|
||||||
}
|
}
|
||||||
is TreeValueBinaryNode -> {
|
is TreeValueBinaryNode -> {
|
||||||
abacus.pluginManager.treeValueOperatorFor(treeNode.operation)
|
abacus.pluginManager.treeValueOperatorFor(treeNode.operation)
|
||||||
.apply(context, treeNode.left ?: return null, treeNode.right ?: return null)
|
.apply(context, treeNode.left, treeNode.right)
|
||||||
}
|
}
|
||||||
is TreeValueFunctionNode -> {
|
is TreeValueFunctionNode -> {
|
||||||
abacus.pluginManager.treeValueFunctionFor(treeNode.callTo)
|
abacus.pluginManager.treeValueFunctionFor(treeNode.callTo)
|
||||||
.apply(context, *treeNode.children.toTypedArray())
|
.apply(context, *treeNode.children.toTypedArray())
|
||||||
}
|
}
|
||||||
else -> null
|
else -> throw EvaluationException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ package org.nwapw.abacus.tree
|
||||||
class NumberUnaryNode(operation: String, child: TreeNode)
|
class NumberUnaryNode(operation: String, child: TreeNode)
|
||||||
: UnaryNode(operation, child) {
|
: UnaryNode(operation, child) {
|
||||||
|
|
||||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
override fun <T : Any> reduce(reducer: Reducer<T>): T {
|
||||||
val child = applyTo.reduce(reducer)
|
val child = applyTo.reduce(reducer)
|
||||||
return reducer.reduceNode(this, child)
|
return reducer.reduceNode(this, child)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,6 @@ interface Reducer<out T> {
|
||||||
* @param treeNode the tree node to reduce.
|
* @param treeNode the tree node to reduce.
|
||||||
* @param children the list of children, of type T.
|
* @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 class TreeNode {
|
||||||
|
|
||||||
abstract fun <T : Any> reduce(reducer: Reducer<T>): T?
|
abstract fun <T : Any> reduce(reducer: Reducer<T>): T
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@ package org.nwapw.abacus.tree
|
||||||
class TreeValueBinaryNode(operation: String, left: TreeNode, right: TreeNode)
|
class TreeValueBinaryNode(operation: String, left: TreeNode, right: TreeNode)
|
||||||
: BinaryNode(operation, left, right) {
|
: 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)
|
return reducer.reduceNode(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ package org.nwapw.abacus.tree
|
||||||
*/
|
*/
|
||||||
class TreeValueFunctionNode(name: String, children: List<TreeNode>) : CallNode(name, children) {
|
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)
|
return reducer.reduceNode(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,8 @@ package org.nwapw.abacus.tree
|
||||||
class TreeValueUnaryNode(operation: String, child: TreeNode)
|
class TreeValueUnaryNode(operation: String, child: TreeNode)
|
||||||
: UnaryNode(operation, child) {
|
: UnaryNode(operation, child) {
|
||||||
|
|
||||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
override fun <T : Any> reduce(reducer: Reducer<T>): T {
|
||||||
return reducer.reduceNode(this);
|
return reducer.reduceNode(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -10,7 +10,7 @@ package org.nwapw.abacus.tree
|
||||||
*/
|
*/
|
||||||
class VariableNode(val variable: String) : TreeNode() {
|
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)
|
return reducer.reduceNode(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.nwapw.abacus.config.Configuration;
|
||||||
import org.nwapw.abacus.function.Documentation;
|
import org.nwapw.abacus.function.Documentation;
|
||||||
import org.nwapw.abacus.function.DocumentationType;
|
import org.nwapw.abacus.function.DocumentationType;
|
||||||
import org.nwapw.abacus.function.DomainException;
|
import org.nwapw.abacus.function.DomainException;
|
||||||
|
import org.nwapw.abacus.function.EvaluationException;
|
||||||
import org.nwapw.abacus.number.*;
|
import org.nwapw.abacus.number.*;
|
||||||
import org.nwapw.abacus.plugin.ClassFinder;
|
import org.nwapw.abacus.plugin.ClassFinder;
|
||||||
import org.nwapw.abacus.plugin.PluginListener;
|
import org.nwapw.abacus.plugin.PluginListener;
|
||||||
|
@ -147,16 +148,11 @@ public class AbacusController implements PluginListener {
|
||||||
}
|
}
|
||||||
EvaluationResult result = abacus.evaluateTree(constructedTree);
|
EvaluationResult result = abacus.evaluateTree(constructedTree);
|
||||||
NumberInterface evaluatedNumber = result.getValue();
|
NumberInterface evaluatedNumber = result.getValue();
|
||||||
if (evaluatedNumber == null) {
|
|
||||||
return ERR_EVAL;
|
|
||||||
}
|
|
||||||
String resultingString = evaluatedNumber.toString();
|
String resultingString = evaluatedNumber.toString();
|
||||||
historyData.add(new HistoryModel(inputField.getText(), constructedTree.toString(), resultingString));
|
historyData.add(new HistoryModel(inputField.getText(), constructedTree.toString(), resultingString));
|
||||||
abacus.applyToContext(result.getResultingContext());
|
abacus.applyToContext(result.getResultingContext());
|
||||||
return resultingString;
|
return resultingString;
|
||||||
} catch (ComputationInterruptedException exception) {
|
} catch (ComputationInterruptedException | DomainException | EvaluationException exception) {
|
||||||
return ERR_STOP;
|
|
||||||
} catch (DomainException exception) {
|
|
||||||
return exception.getMessage();
|
return exception.getMessage();
|
||||||
} catch (RuntimeException exception) {
|
} catch (RuntimeException exception) {
|
||||||
exception.printStackTrace();
|
exception.printStackTrace();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user