mirror of
https://github.com/DanilaFe/abacus
synced 2026-01-25 08:05:19 +00:00
Compare commits
10 Commits
fxml-fix
...
tree-funct
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f0addccea | |||
| 1a47e07e97 | |||
| 26305c3bae | |||
| 6b9252f902 | |||
| bc26ad0b88 | |||
| c5cd0f81ad | |||
| ac19c7b230 | |||
| 40c80db914 | |||
| 00462281fe | |||
| 01f80bbb53 |
38
core/src/main/java/org/nwapw/abacus/function/Applicable.java
Normal file
38
core/src/main/java/org/nwapw/abacus/function/Applicable.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package org.nwapw.abacus.function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class that represents something that can be applied to one or more
|
||||||
|
* arguments of the same type, and returns a single value from that application.
|
||||||
|
* @param <T> the type of the parameters passed to this applicable.
|
||||||
|
* @param <O> the return type of the applicable.
|
||||||
|
*/
|
||||||
|
public abstract class Applicable<T, O> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given applicable can be used with the given parameters.
|
||||||
|
* @param params the parameter array to verify for compatibility.
|
||||||
|
* @return whether the array can be used with applyInternal.
|
||||||
|
*/
|
||||||
|
protected abstract boolean matchesParams(T[] params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the applicable object to the given parameters,
|
||||||
|
* without checking for compatibility.
|
||||||
|
* @param params the parameters to apply to.
|
||||||
|
* @return the result of the application.
|
||||||
|
*/
|
||||||
|
protected abstract O applyInternal(T[] params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the parameters can be used with this applicable, returns
|
||||||
|
* the result of the application of the applicable to the parameters.
|
||||||
|
* Otherwise, returns null.
|
||||||
|
* @param params the parameters to apply to.
|
||||||
|
* @return the result of the operation, or null if parameters do not match.
|
||||||
|
*/
|
||||||
|
public O apply(T... params){
|
||||||
|
if(!matchesParams(params)) return null;
|
||||||
|
return applyInternal(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,6 +6,6 @@ package org.nwapw.abacus.function;
|
|||||||
*/
|
*/
|
||||||
public enum DocumentationType {
|
public enum DocumentationType {
|
||||||
|
|
||||||
FUNCTION
|
FUNCTION, TREE_VALUE_FUNCTION
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,34 +6,6 @@ import org.nwapw.abacus.number.NumberInterface;
|
|||||||
* A function that operates on one or more
|
* A function that operates on one or more
|
||||||
* inputs and returns a single number.
|
* inputs and returns a single number.
|
||||||
*/
|
*/
|
||||||
public abstract class Function {
|
public abstract class Function extends Applicable<NumberInterface, NumberInterface> {
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the given params will work for the given function.
|
|
||||||
*
|
|
||||||
* @param params the given params
|
|
||||||
* @return true if the params can be used with this function.
|
|
||||||
*/
|
|
||||||
protected abstract boolean matchesParams(NumberInterface[] params);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal apply implementation, which already receives appropriately promoted
|
|
||||||
* parameters that have bee run through matchesParams
|
|
||||||
*
|
|
||||||
* @param params the promoted parameters.
|
|
||||||
* @return the return value of the function.
|
|
||||||
*/
|
|
||||||
protected abstract NumberInterface applyInternal(NumberInterface[] params);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to check, promote arguments and run the function.
|
|
||||||
*
|
|
||||||
* @param params the raw input parameters.
|
|
||||||
* @return the return value of the function, or null if an error occurred.
|
|
||||||
*/
|
|
||||||
public NumberInterface apply(NumberInterface... params) {
|
|
||||||
if (!matchesParams(params)) return null;
|
|
||||||
return applyInternal(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package org.nwapw.abacus.function;
|
||||||
|
|
||||||
|
import org.nwapw.abacus.number.NumberInterface;
|
||||||
|
import org.nwapw.abacus.tree.Reducer;
|
||||||
|
import org.nwapw.abacus.tree.TreeNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function that operates on parse tree nodes instead of on already simplified numbers.
|
||||||
|
* Despite this, it returns a number, not a tree.
|
||||||
|
*/
|
||||||
|
public abstract class TreeValueFunction extends Applicable<TreeNode, NumberInterface> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected NumberInterface applyInternal(TreeNode[] params) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NumberInterface apply(TreeNode... params) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the tree value functions to the given tree nodes,
|
||||||
|
* using the given reducer.
|
||||||
|
* @param reducer the reducer to use.
|
||||||
|
* @param params the parameters to apply to.
|
||||||
|
* @return the result of the application.
|
||||||
|
*/
|
||||||
|
public abstract NumberInterface applyWithReducerInternal(Reducer<NumberInterface> reducer, TreeNode[] params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given parameters and reducer can be used
|
||||||
|
* with this function, and if so, calls the function on them.
|
||||||
|
* @param reducer the reducer to use.
|
||||||
|
* @param params the parameters to apply to.
|
||||||
|
* @return the result of the application, or null if the parameters are incompatible.
|
||||||
|
*/
|
||||||
|
public NumberInterface applyWithReducer(Reducer<NumberInterface> reducer, TreeNode... params) {
|
||||||
|
if(!matchesParams(params) || reducer == null) return null;
|
||||||
|
return applyWithReducerInternal(reducer, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,6 +53,9 @@ public class LexerTokenizer implements Tokenizer<Match<TokenType>>, PluginListen
|
|||||||
for (String function : manager.getAllFunctions()) {
|
for (String function : manager.getAllFunctions()) {
|
||||||
lexer.register(Pattern.sanitize(function), TokenType.FUNCTION);
|
lexer.register(Pattern.sanitize(function), TokenType.FUNCTION);
|
||||||
}
|
}
|
||||||
|
for (String function : manager.getAllTreeValueFunctions()){
|
||||||
|
lexer.register(Pattern.sanitize(function), TokenType.TREE_VALUE_FUNCTION);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -63,6 +66,9 @@ public class LexerTokenizer implements Tokenizer<Match<TokenType>>, PluginListen
|
|||||||
for (String function : manager.getAllFunctions()) {
|
for (String function : manager.getAllFunctions()) {
|
||||||
lexer.unregister(Pattern.sanitize(function), TokenType.FUNCTION);
|
lexer.unregister(Pattern.sanitize(function), TokenType.FUNCTION);
|
||||||
}
|
}
|
||||||
|
for (String function : manager.getAllTreeValueFunctions()){
|
||||||
|
lexer.unregister(Pattern.sanitize(function), TokenType.TREE_VALUE_FUNCTION);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
|
|||||||
matchType = match.getType();
|
matchType = match.getType();
|
||||||
if (matchType == TokenType.NUM || matchType == TokenType.VARIABLE) {
|
if (matchType == TokenType.NUM || matchType == TokenType.VARIABLE) {
|
||||||
output.add(match);
|
output.add(match);
|
||||||
} else if (matchType == TokenType.FUNCTION) {
|
} else if (matchType == TokenType.FUNCTION || matchType == TokenType.TREE_VALUE_FUNCTION) {
|
||||||
output.add(new Match<>("", TokenType.INTERNAL_FUNCTION_END));
|
output.add(new Match<>("", TokenType.INTERNAL_FUNCTION_END));
|
||||||
tokenStack.push(match);
|
tokenStack.push(match);
|
||||||
} else if (matchType == TokenType.OP) {
|
} else if (matchType == TokenType.OP) {
|
||||||
@@ -78,7 +78,8 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
|
|||||||
while (!tokenStack.empty() && type == OperatorType.BINARY_INFIX) {
|
while (!tokenStack.empty() && type == OperatorType.BINARY_INFIX) {
|
||||||
Match<TokenType> otherMatch = tokenStack.peek();
|
Match<TokenType> otherMatch = tokenStack.peek();
|
||||||
TokenType otherMatchType = otherMatch.getType();
|
TokenType otherMatchType = otherMatch.getType();
|
||||||
if (!(otherMatchType == TokenType.OP || otherMatchType == TokenType.FUNCTION)) break;
|
if (!(otherMatchType == TokenType.OP || otherMatchType == TokenType.FUNCTION ||
|
||||||
|
otherMatchType == TokenType.TREE_VALUE_FUNCTION)) break;
|
||||||
|
|
||||||
if (otherMatchType == TokenType.OP) {
|
if (otherMatchType == TokenType.OP) {
|
||||||
int otherPrecedence = precedenceMap.get(otherMatch.getContent());
|
int otherPrecedence = precedenceMap.get(otherMatch.getContent());
|
||||||
@@ -105,7 +106,8 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
|
|||||||
while (!tokenStack.empty()) {
|
while (!tokenStack.empty()) {
|
||||||
Match<TokenType> match = tokenStack.peek();
|
Match<TokenType> match = tokenStack.peek();
|
||||||
TokenType newMatchType = match.getType();
|
TokenType newMatchType = match.getType();
|
||||||
if (!(newMatchType == TokenType.OP || newMatchType == TokenType.FUNCTION)) return null;
|
if (!(newMatchType == TokenType.OP || newMatchType == TokenType.FUNCTION ||
|
||||||
|
newMatchType == TokenType.TREE_VALUE_FUNCTION)) return null;
|
||||||
output.add(tokenStack.pop());
|
output.add(tokenStack.pop());
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
@@ -138,13 +140,18 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
|
|||||||
return new NumberNode(match.getContent());
|
return new NumberNode(match.getContent());
|
||||||
} else if (matchType == TokenType.VARIABLE) {
|
} else if (matchType == TokenType.VARIABLE) {
|
||||||
return new VariableNode(match.getContent());
|
return new VariableNode(match.getContent());
|
||||||
} else if (matchType == TokenType.FUNCTION) {
|
} else if (matchType == TokenType.FUNCTION || matchType == TokenType.TREE_VALUE_FUNCTION) {
|
||||||
String functionName = match.getContent();
|
String functionName = match.getContent();
|
||||||
FunctionNode node = new FunctionNode(functionName);
|
CallNode node;
|
||||||
|
if(matchType == TokenType.FUNCTION){
|
||||||
|
node = new FunctionNode(functionName);
|
||||||
|
} else {
|
||||||
|
node = new TreeValueFunctionNode(functionName);
|
||||||
|
}
|
||||||
while (!matches.isEmpty() && matches.get(0).getType() != TokenType.INTERNAL_FUNCTION_END) {
|
while (!matches.isEmpty() && matches.get(0).getType() != TokenType.INTERNAL_FUNCTION_END) {
|
||||||
TreeNode argument = constructRecursive(matches);
|
TreeNode argument = constructRecursive(matches);
|
||||||
if (argument == null) return null;
|
if (argument == null) return null;
|
||||||
node.prependChild(argument);
|
node.getChildren().add(0, argument);
|
||||||
}
|
}
|
||||||
if (matches.isEmpty()) return null;
|
if (matches.isEmpty()) return null;
|
||||||
matches.remove(0);
|
matches.remove(0);
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package org.nwapw.abacus.plugin;
|
package org.nwapw.abacus.plugin;
|
||||||
|
|
||||||
import org.nwapw.abacus.function.Documentation;
|
import org.nwapw.abacus.function.*;
|
||||||
import org.nwapw.abacus.function.DocumentationType;
|
|
||||||
import org.nwapw.abacus.function.Function;
|
|
||||||
import org.nwapw.abacus.function.Operator;
|
|
||||||
import org.nwapw.abacus.number.NumberInterface;
|
import org.nwapw.abacus.number.NumberInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,6 +66,17 @@ public abstract class Plugin {
|
|||||||
manager.registerFunction(name, toRegister);
|
manager.registerFunction(name, toRegister);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To be used in load(). Registers a tree value function abstract class
|
||||||
|
* with the plugin internally, which makes it accessible to the plugin manager.
|
||||||
|
*
|
||||||
|
* @param name the name to register by.
|
||||||
|
* @param toRegister the tree value function implementation.
|
||||||
|
*/
|
||||||
|
protected final void registerTreeValueFunction(String name, TreeValueFunction toRegister) {
|
||||||
|
manager.registerTreeValueFunction(name, toRegister);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To be used in load(). Registers an operator abstract class
|
* To be used in load(). Registers an operator abstract class
|
||||||
* with the plugin internally, which makes it accessible to
|
* with the plugin internally, which makes it accessible to
|
||||||
@@ -114,6 +122,18 @@ public abstract class Plugin {
|
|||||||
return manager.functionFor(name);
|
return manager.functionFor(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches the PluginManager for the given function name.
|
||||||
|
* This can be used by the plugins internally in order to call functions
|
||||||
|
* they do not provide.
|
||||||
|
*
|
||||||
|
* @param name the name for which to search.
|
||||||
|
* @return the resulting tree value function, or null if none was found for that name.
|
||||||
|
*/
|
||||||
|
protected final TreeValueFunction treeValueFunctionFor(String name){
|
||||||
|
return manager.treeValueFunctionFor(name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches the PluginManager for the given operator name.
|
* Searches the PluginManager for the given operator name.
|
||||||
* This can be used by the plugins internally in order to call
|
* This can be used by the plugins internally in order to call
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
package org.nwapw.abacus.plugin;
|
package org.nwapw.abacus.plugin;
|
||||||
|
|
||||||
import org.nwapw.abacus.Abacus;
|
import org.nwapw.abacus.Abacus;
|
||||||
import org.nwapw.abacus.function.Documentation;
|
import org.nwapw.abacus.function.*;
|
||||||
import org.nwapw.abacus.function.DocumentationType;
|
|
||||||
import org.nwapw.abacus.function.Function;
|
|
||||||
import org.nwapw.abacus.function.Operator;
|
|
||||||
import org.nwapw.abacus.number.NumberInterface;
|
import org.nwapw.abacus.number.NumberInterface;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@@ -31,6 +28,10 @@ public class PluginManager {
|
|||||||
* The map of functions registered by the plugins.
|
* The map of functions registered by the plugins.
|
||||||
*/
|
*/
|
||||||
private Map<String, Function> registeredFunctions;
|
private Map<String, Function> registeredFunctions;
|
||||||
|
/**
|
||||||
|
* The map of tree value functions regstered by the plugins.
|
||||||
|
*/
|
||||||
|
private Map<String, TreeValueFunction> registeredTreeValueFunctions;
|
||||||
/**
|
/**
|
||||||
* The map of operators registered by the plugins
|
* The map of operators registered by the plugins
|
||||||
*/
|
*/
|
||||||
@@ -72,6 +73,7 @@ public class PluginManager {
|
|||||||
loadedPluginClasses = new HashSet<>();
|
loadedPluginClasses = new HashSet<>();
|
||||||
plugins = new HashSet<>();
|
plugins = new HashSet<>();
|
||||||
registeredFunctions = new HashMap<>();
|
registeredFunctions = new HashMap<>();
|
||||||
|
registeredTreeValueFunctions = new HashMap<>();
|
||||||
registeredOperators = new HashMap<>();
|
registeredOperators = new HashMap<>();
|
||||||
registeredNumberImplementations = new HashMap<>();
|
registeredNumberImplementations = new HashMap<>();
|
||||||
registeredDocumentation = new HashSet<>();
|
registeredDocumentation = new HashSet<>();
|
||||||
@@ -90,6 +92,16 @@ public class PluginManager {
|
|||||||
registeredFunctions.put(name, function);
|
registeredFunctions.put(name, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a tree value function under the given name.
|
||||||
|
*
|
||||||
|
* @param name the name of the function.
|
||||||
|
* @param function the function to register.
|
||||||
|
*/
|
||||||
|
public void registerTreeValueFunction(String name, TreeValueFunction function) {
|
||||||
|
registeredTreeValueFunctions.put(name, function);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers an operator under the given name.
|
* Registers an operator under the given name.
|
||||||
*
|
*
|
||||||
@@ -130,6 +142,16 @@ public class PluginManager {
|
|||||||
return registeredFunctions.get(name);
|
return registeredFunctions.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the tree value function registered under the given name.
|
||||||
|
*
|
||||||
|
* @param name the name of the function.
|
||||||
|
* @return the function, or null if it was not found.
|
||||||
|
*/
|
||||||
|
public TreeValueFunction treeValueFunctionFor(String name){
|
||||||
|
return registeredTreeValueFunctions.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the operator registered under the given name.
|
* Gets the operator registered under the given name.
|
||||||
*
|
*
|
||||||
@@ -302,6 +324,15 @@ public class PluginManager {
|
|||||||
return registeredFunctions.keySet();
|
return registeredFunctions.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all the tree vlaue functions loaded by the PluginManager.
|
||||||
|
*
|
||||||
|
* @return the set of all the tree value functions that were loaded.
|
||||||
|
*/
|
||||||
|
public Set<String> getAllTreeValueFunctions() {
|
||||||
|
return registeredTreeValueFunctions.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all the operators loaded by the Plugin Manager.
|
* Gets all the operators loaded by the Plugin Manager.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.nwapw.abacus.tree;
|
|||||||
|
|
||||||
import org.nwapw.abacus.Abacus;
|
import org.nwapw.abacus.Abacus;
|
||||||
import org.nwapw.abacus.function.Function;
|
import org.nwapw.abacus.function.Function;
|
||||||
|
import org.nwapw.abacus.function.TreeValueFunction;
|
||||||
import org.nwapw.abacus.number.NumberInterface;
|
import org.nwapw.abacus.number.NumberInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,9 +47,19 @@ public class NumberReducer implements Reducer<NumberInterface> {
|
|||||||
for (int i = 0; i < convertedChildren.length; i++) {
|
for (int i = 0; i < convertedChildren.length; i++) {
|
||||||
convertedChildren[i] = (NumberInterface) children[i];
|
convertedChildren[i] = (NumberInterface) children[i];
|
||||||
}
|
}
|
||||||
Function function = abacus.getPluginManager().functionFor(((FunctionNode) node).getFunction());
|
Function function = abacus.getPluginManager().functionFor(((FunctionNode) node).getCallTo());
|
||||||
if (function == null) return null;
|
if (function == null) return null;
|
||||||
return function.apply(convertedChildren);
|
return function.apply(convertedChildren);
|
||||||
|
} else if (node instanceof TreeValueFunctionNode){
|
||||||
|
CallNode callNode = (CallNode) node;
|
||||||
|
TreeNode[] realChildren = new TreeNode[callNode.getChildren().size()];
|
||||||
|
for(int i = 0; i < realChildren.length; i++){
|
||||||
|
realChildren[i] = callNode.getChildren().get(i);
|
||||||
|
}
|
||||||
|
TreeValueFunction function =
|
||||||
|
abacus.getPluginManager().treeValueFunctionFor(callNode.getCallTo());
|
||||||
|
if(function == null) return null;
|
||||||
|
return function.applyWithReducer(this, realChildren);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ package org.nwapw.abacus.tree;
|
|||||||
public enum TokenType {
|
public enum TokenType {
|
||||||
|
|
||||||
INTERNAL_FUNCTION_END(-1),
|
INTERNAL_FUNCTION_END(-1),
|
||||||
ANY(0), WHITESPACE(1), COMMA(2), OP(3), NUM(4), VARIABLE(5), FUNCTION(6), OPEN_PARENTH(7), CLOSE_PARENTH(8);
|
ANY(0), WHITESPACE(1), COMMA(2), OP(3), NUM(4), VARIABLE(5), FUNCTION(6), TREE_VALUE_FUNCTION(6), OPEN_PARENTH(7), CLOSE_PARENTH(8);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The priority by which this token gets sorted.
|
* The priority by which this token gets sorted.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ package org.nwapw.abacus.tree
|
|||||||
* @param left the left node.
|
* @param left the left node.
|
||||||
* @param right the right node.
|
* @param right the right node.
|
||||||
*/
|
*/
|
||||||
data class BinaryNode(val operation: String, val left: TreeNode? = null, val right: TreeNode?) : TreeNode() {
|
class BinaryNode(val operation: String, val left: TreeNode? = null, val right: TreeNode?) : TreeNode() {
|
||||||
|
|
||||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||||
val leftReduce = left?.reduce(reducer) ?: return null
|
val leftReduce = left?.reduce(reducer) ?: return null
|
||||||
|
|||||||
29
core/src/main/kotlin/org/nwapw/abacus/tree/CallNode.kt
Normal file
29
core/src/main/kotlin/org/nwapw/abacus/tree/CallNode.kt
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package org.nwapw.abacus.tree
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a more generic function call.
|
||||||
|
*
|
||||||
|
* This class does not specify how it should be reduced, allowing other classes
|
||||||
|
* to extend this functionality.
|
||||||
|
*
|
||||||
|
* @param callTo the name of the things being called.
|
||||||
|
*/
|
||||||
|
abstract class CallNode(val callTo: String) : TreeNode() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of children this node has.
|
||||||
|
*/
|
||||||
|
val children: MutableList<TreeNode> = mutableListOf()
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
val buffer = StringBuffer()
|
||||||
|
buffer.append(callTo)
|
||||||
|
buffer.append("(")
|
||||||
|
for(i in 0 until children.size){
|
||||||
|
buffer.append(children[i].toString())
|
||||||
|
buffer.append(if(i != children.size - 1) ", " else ")")
|
||||||
|
}
|
||||||
|
return buffer.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,45 +8,11 @@ package org.nwapw.abacus.tree
|
|||||||
*
|
*
|
||||||
* @param function the function string.
|
* @param function the function string.
|
||||||
*/
|
*/
|
||||||
data class FunctionNode(val function: String) : TreeNode() {
|
class FunctionNode(function: String) : CallNode(function) {
|
||||||
|
|
||||||
/**
|
|
||||||
* List of function parameters added to this node.
|
|
||||||
*/
|
|
||||||
val children: MutableList<TreeNode> = mutableListOf()
|
|
||||||
|
|
||||||
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 null; })
|
||||||
return reducer.reduceNode(this, *children)
|
return reducer.reduceNode(this, *children)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
val buffer = StringBuffer()
|
|
||||||
buffer.append(function)
|
|
||||||
buffer.append('(')
|
|
||||||
for (i in 0 until children.size) {
|
|
||||||
buffer.append(children[i].toString())
|
|
||||||
buffer.append(if (i == children.size - 1) ")" else ",")
|
|
||||||
}
|
|
||||||
return buffer.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Appends a child to this node's list of children.
|
|
||||||
*
|
|
||||||
* @node the node to append.
|
|
||||||
*/
|
|
||||||
fun appendChild(node: TreeNode) {
|
|
||||||
children.add(node)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepends a child to this node's list of children.
|
|
||||||
*
|
|
||||||
* @node the node to prepend.
|
|
||||||
*/
|
|
||||||
fun prependChild(node: TreeNode) {
|
|
||||||
children.add(0, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ import org.nwapw.abacus.number.NumberInterface
|
|||||||
*
|
*
|
||||||
* @number the number value of this node.
|
* @number the number value of this node.
|
||||||
*/
|
*/
|
||||||
data 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)
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package org.nwapw.abacus.tree
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tree node that represents a tree value function call.
|
||||||
|
*
|
||||||
|
* This is in many ways similar to a simple FunctionNode, and the distinction
|
||||||
|
* 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) {
|
||||||
|
|
||||||
|
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||||
|
return reducer.reduceNode(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ package org.nwapw.abacus.tree
|
|||||||
* @param operation the operation applied to the given node.
|
* @param operation the operation applied to the given node.
|
||||||
* @param applyTo the node to which the operation will be applied.
|
* @param applyTo the node to which the operation will be applied.
|
||||||
*/
|
*/
|
||||||
data class UnaryNode(val operation: String, val applyTo: TreeNode? = null) : TreeNode() {
|
class UnaryNode(val operation: String, val applyTo: TreeNode? = null) : TreeNode() {
|
||||||
|
|
||||||
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||||
val reducedChild = applyTo?.reduce(reducer) ?: return null
|
val reducedChild = applyTo?.reduce(reducer) ?: return null
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ package org.nwapw.abacus.tree
|
|||||||
*
|
*
|
||||||
* @param variable the actual variable name that this node represents.
|
* @param variable the actual variable name that this node represents.
|
||||||
*/
|
*/
|
||||||
data 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)
|
||||||
|
|||||||
@@ -360,6 +360,8 @@ public class AbacusController implements PluginListener {
|
|||||||
PluginManager pluginManager = abacus.getPluginManager();
|
PluginManager pluginManager = abacus.getPluginManager();
|
||||||
functionList.addAll(manager.getAllFunctions().stream().map(name -> pluginManager.documentationFor(name, DocumentationType.FUNCTION))
|
functionList.addAll(manager.getAllFunctions().stream().map(name -> pluginManager.documentationFor(name, DocumentationType.FUNCTION))
|
||||||
.collect(Collectors.toCollection(ArrayList::new)));
|
.collect(Collectors.toCollection(ArrayList::new)));
|
||||||
|
functionList.addAll(manager.getAllTreeValueFunctions().stream().map(name -> pluginManager.documentationFor(name, DocumentationType.TREE_VALUE_FUNCTION))
|
||||||
|
.collect(Collectors.toCollection(ArrayList::new)));
|
||||||
functionList.sort(Comparator.comparing(Documentation::getCodeName));
|
functionList.sort(Comparator.comparing(Documentation::getCodeName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user