Abacus/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java

94 lines
4.6 KiB
Java
Raw Normal View History

package org.nwapw.abacus.tree;
import org.nwapw.abacus.Abacus;
2017-09-01 18:07:48 -07:00
import org.nwapw.abacus.function.NumberFunction;
import org.nwapw.abacus.function.NumberOperator;
import org.nwapw.abacus.function.TreeValueFunction;
import org.nwapw.abacus.function.TreeValueOperator;
import org.nwapw.abacus.number.NumberInterface;
import org.nwapw.abacus.number.PromotionManager;
import org.nwapw.abacus.number.PromotionResult;
import org.nwapw.abacus.variables.VariableDatabase;
/**
* A reducer implementation that turns a tree into a single number.
* This is not always guaranteed to work.
*/
public class NumberReducer implements Reducer<NumberInterface> {
/**
* The plugin manager from which to draw the functions.
*/
private Abacus abacus;
/**
* Creates a new number reducer.
2017-07-30 21:11:32 -07:00
*
* @param abacus the calculator instance.
*/
2017-07-30 21:11:32 -07:00
public NumberReducer(Abacus abacus) {
this.abacus = abacus;
}
@Override
public NumberInterface reduceNode(TreeNode node, Object... children) {
PromotionManager manager = abacus.getPromotionManager();
2017-07-30 21:11:32 -07:00
if (node instanceof NumberNode) {
return abacus.getNumberImplementation().instanceForString(((NumberNode) node).getNumber());
2017-09-01 18:07:48 -07:00
} else if (node instanceof VariableNode) {
VariableDatabase database = abacus.getVariableDatabase();
String name = ((VariableNode) node).getVariable();
NumberInterface variable = database.getVariables().get(name);
if(variable != null) return variable;
TreeNode definition = database.getDefinitions().get(name);
if(definition != null) return definition.reduce(this);
return abacus.getNumberImplementation().instanceForString("0");
} else if (node instanceof NumberBinaryNode) {
NumberInterface left = (NumberInterface) children[0];
NumberInterface right = (NumberInterface) children[1];
2017-08-25 15:42:10 -07:00
NumberOperator operator = abacus.getPluginManager().operatorFor(((BinaryNode) node).getOperation());
PromotionResult result = manager.promote(left, right);
2017-09-01 18:07:48 -07:00
if (result == null) return null;
return operator.apply(result.getPromotedTo(), result.getItems());
} else if (node instanceof NumberUnaryNode) {
2017-07-28 11:14:45 -07:00
NumberInterface child = (NumberInterface) children[0];
2017-08-25 15:42:10 -07:00
NumberOperator operator = abacus.getPluginManager().operatorFor(((UnaryNode) node).getOperation());
return operator.apply(abacus.getPluginManager().interfaceImplementationFor(child.getClass()), child);
2017-07-30 21:11:32 -07:00
} else if (node instanceof FunctionNode) {
2017-07-26 18:44:30 -07:00
NumberInterface[] convertedChildren = new NumberInterface[children.length];
2017-07-30 21:11:32 -07:00
for (int i = 0; i < convertedChildren.length; i++) {
2017-07-26 18:44:30 -07:00
convertedChildren[i] = (NumberInterface) children[i];
}
2017-08-25 14:56:36 -07:00
NumberFunction function = abacus.getPluginManager().functionFor(((FunctionNode) node).getCallTo());
2017-07-30 21:11:32 -07:00
if (function == null) return null;
PromotionResult result = manager.promote(convertedChildren);
2017-09-01 18:07:48 -07:00
if (result == null) return null;
return function.apply(result.getPromotedTo(), result.getItems());
2017-09-01 18:07:48 -07:00
} else if (node instanceof TreeValueFunctionNode) {
CallNode callNode = (CallNode) node;
TreeNode[] realChildren = new TreeNode[callNode.getChildren().size()];
2017-09-01 18:07:48 -07:00
for (int i = 0; i < realChildren.length; i++) {
realChildren[i] = callNode.getChildren().get(i);
}
TreeValueFunction function =
abacus.getPluginManager().treeValueFunctionFor(callNode.getCallTo());
2017-09-01 18:07:48 -07:00
if (function == null) return null;
return function.applyWithReducer(abacus.getNumberImplementation(), this, realChildren);
2017-08-25 18:48:05 -07:00
} else if (node instanceof TreeValueBinaryNode) {
BinaryNode binaryNode = (BinaryNode) node;
TreeValueOperator operator = abacus.getPluginManager()
.treeValueOperatorFor(binaryNode.getOperation());
2017-09-01 18:07:48 -07:00
if (operator == null) return null;
return operator.applyWithReducer(abacus.getNumberImplementation(), this, binaryNode.getLeft(), binaryNode.getRight());
2017-09-01 18:07:48 -07:00
} else if (node instanceof TreeValueUnaryNode) {
2017-08-25 18:48:05 -07:00
UnaryNode unaryNode = (UnaryNode) node;
TreeValueOperator operator = abacus.getPluginManager()
.treeValueOperatorFor(unaryNode.getOperation());
2017-09-01 18:07:48 -07:00
if (operator == null) return null;
return operator.applyWithReducer(abacus.getNumberImplementation(), this, unaryNode.getApplyTo());
}
return null;
}
}