1
0
mirror of https://github.com/DanilaFe/abacus synced 2026-01-26 08:35:20 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Riley Jones
c03e191c36 add live load and unload 2017-08-02 14:31:29 -07:00
10 changed files with 87 additions and 47 deletions

View File

@@ -9,7 +9,7 @@ import org.nwapw.abacus.parsing.ShuntingYardParser;
import org.nwapw.abacus.parsing.TreeBuilder; import org.nwapw.abacus.parsing.TreeBuilder;
import org.nwapw.abacus.plugin.ClassFinder; import org.nwapw.abacus.plugin.ClassFinder;
import org.nwapw.abacus.plugin.PluginManager; import org.nwapw.abacus.plugin.PluginManager;
import org.nwapw.abacus.plugin.StandardPlugin; //import org.nwapw.abacus.plugin.StandardPlugin;
import org.nwapw.abacus.tree.NumberReducer; import org.nwapw.abacus.tree.NumberReducer;
import org.nwapw.abacus.tree.TreeNode; import org.nwapw.abacus.tree.TreeNode;
@@ -67,16 +67,22 @@ public class Abacus {
pluginManager.addListener(lexerTokenizer); pluginManager.addListener(lexerTokenizer);
pluginManager.addListener(shuntingYardParser); pluginManager.addListener(shuntingYardParser);
pluginManager.addInstantiated(new StandardPlugin(pluginManager)); //pluginManager.addInstantiated(new StandardPlugin(pluginManager));
/*
try { try {
ClassFinder.loadJars("plugins") ClassFinder.loadJars("plugins")
.forEach(plugin -> pluginManager.addClass(plugin)); .forEach(plugin -> pluginManager.addClass(plugin));
} catch (IOException | ClassNotFoundException e) { } catch (IOException | ClassNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
} }//*/
pluginManager.load(); pluginManager.load();
} }
public void loadClass(Class<?> newClass){
pluginManager.addClass(newClass);
}
public void unloadClass(Class<?> newClass){
pluginManager.removeClass(newClass);
}
public static void main(String[] args) { public static void main(String[] args) {
AbacusApplication.launch(AbacusApplication.class, args); AbacusApplication.launch(AbacusApplication.class, args);
} }

View File

@@ -4,5 +4,5 @@ package org.nwapw.abacus.function;
* The type of an operator, describing how it should behave. * The type of an operator, describing how it should behave.
*/ */
public enum OperatorType { public enum OperatorType {
BINARY_INFIX, UNARY_POSTFIX, UNARY_PREFIX BINARY_INFIX, UNARY_POSTFIX
} }

View File

@@ -8,8 +8,11 @@ import javafx.scene.text.Text;
import javafx.util.Callback; import javafx.util.Callback;
import org.nwapw.abacus.Abacus; import org.nwapw.abacus.Abacus;
import org.nwapw.abacus.number.NumberInterface; import org.nwapw.abacus.number.NumberInterface;
import org.nwapw.abacus.plugin.ClassFinder;
import org.nwapw.abacus.tree.TreeNode; import org.nwapw.abacus.tree.TreeNode;
import java.io.IOException;
/** /**
* The controller for the abacus FX UI, responsible * The controller for the abacus FX UI, responsible
@@ -42,6 +45,12 @@ public class AbacusController {
private Button inputButton; private Button inputButton;
@FXML @FXML
private ComboBox<String> numberImplementationBox; private ComboBox<String> numberImplementationBox;
@FXML
private Button loadButton;
@FXML
private Button unloadButton;
@FXML
private TextField loadField;
/** /**
* The list of history entries, created by the users. * The list of history entries, created by the users.
@@ -106,5 +115,38 @@ public class AbacusController {
inputButton.setDisable(false); inputButton.setDisable(false);
inputField.setText(""); inputField.setText("");
} }
@FXML
private void loadClass(){
try {
for(Class<?> plugin :ClassFinder.loadJars("plugins")){
String name = "";
//String name = plugin.getName();
while(!(name.indexOf('/') ==-1)){
name=name.substring(name.indexOf('/')+1);
}
if(loadField.getText().equals("")||loadField.getText().equals(name)||(loadField.getText()+".class").equals(name)){
//abacus.loadClass(plugin);
}
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
@FXML
private void unloadClass(){
try {
for(Class<?> plugin :ClassFinder.loadJars("plugins")){
String name = plugin.getName();
while(!(name.indexOf('/') ==-1)){
name=name.substring(name.indexOf('/')+1);
}
if(loadField.getText().equals("")||loadField.getText().equals(name)||(loadField.getText()+".class").equals(name)){
//abacus.unloadClass(plugin);
}
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
} }

View File

@@ -55,12 +55,9 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
public List<Match<TokenType>> intoPostfix(List<Match<TokenType>> from) { public List<Match<TokenType>> intoPostfix(List<Match<TokenType>> from) {
ArrayList<Match<TokenType>> output = new ArrayList<>(); ArrayList<Match<TokenType>> output = new ArrayList<>();
Stack<Match<TokenType>> tokenStack = new Stack<>(); Stack<Match<TokenType>> tokenStack = new Stack<>();
TokenType previousType;
TokenType matchType = null;
while (!from.isEmpty()) { while (!from.isEmpty()) {
Match<TokenType> match = from.remove(0); Match<TokenType> match = from.remove(0);
previousType = matchType; TokenType matchType = match.getType();
matchType = match.getType();
if (matchType == TokenType.NUM) { if (matchType == TokenType.NUM) {
output.add(match); output.add(match);
} else if (matchType == TokenType.FUNCTION) { } else if (matchType == TokenType.FUNCTION) {
@@ -77,13 +74,7 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
continue; continue;
} }
if(tokenString.equals("-") && (previousType == null || previousType == TokenType.OP || while (!tokenStack.empty()) {
previousType == TokenType.OPEN_PARENTH)){
from.add(0, new Match<>("`", TokenType.OP));
continue;
}
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)) break;
@@ -112,8 +103,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 matchType = match.getType();
if (!(newMatchType == TokenType.OP || newMatchType == TokenType.FUNCTION)) return null; if (!(matchType == TokenType.OP || matchType == TokenType.FUNCTION)) return null;
output.add(tokenStack.pop()); output.add(tokenStack.pop());
} }
return output; return output;
@@ -136,11 +127,11 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
TreeNode right = constructRecursive(matches); TreeNode right = constructRecursive(matches);
TreeNode left = constructRecursive(matches); TreeNode left = constructRecursive(matches);
if (left == null || right == null) return null; if (left == null || right == null) return null;
else return new BinaryNode(operator, left, right); else return new BinaryInfixNode(operator, left, right);
} else { } else {
TreeNode applyTo = constructRecursive(matches); TreeNode applyTo = constructRecursive(matches);
if (applyTo == null) return null; if (applyTo == null) return null;
else return new UnaryNode(operator, applyTo); else return new UnaryPrefixNode(operator, applyTo);
} }
} else if (matchType == TokenType.NUM) { } else if (matchType == TokenType.NUM) {
return new NumberNode(abacus.numberFromString(match.getContent())); return new NumberNode(abacus.numberFromString(match.getContent()));

View File

@@ -140,6 +140,11 @@ public class PluginManager {
plugins.add(plugin); plugins.add(plugin);
loadedPluginClasses.add(plugin.getClass()); loadedPluginClasses.add(plugin.getClass());
} }
public void removeInstantiated(Plugin plugin){
if (loadedPluginClasses.contains(plugin.getClass())) return;
plugins.remove(plugin);
loadedPluginClasses.remove(plugin.getClass());
}
/** /**
* Instantiates a class of plugin, and adds it to this * Instantiates a class of plugin, and adds it to this
@@ -155,6 +160,14 @@ public class PluginManager {
e.printStackTrace(); e.printStackTrace();
} }
} }
public void removeClass(Class<?> newClass){
if (!Plugin.class.isAssignableFrom(newClass) || newClass == Plugin.class) return;
try {
removeInstantiated((Plugin) newClass.getConstructor(PluginManager.class).newInstance(this));
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
}
/** /**
* Loads all the plugins in the PluginManager. * Loads all the plugins in the PluginManager.

View File

@@ -52,20 +52,6 @@ public class StandardPlugin extends Plugin {
return params[0].subtract(params[1]); return params[0].subtract(params[1]);
} }
}); });
/**
* The negation operator, -
*/
public static final Operator OP_NEGATE = new Operator(OperatorAssociativity.LEFT, OperatorType.UNARY_PREFIX, 0, new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return params[0].negate();
}
});
/** /**
* The multiplication operator, * * The multiplication operator, *
*/ */
@@ -331,7 +317,6 @@ public class StandardPlugin extends Plugin {
registerOperator("+", OP_ADD); registerOperator("+", OP_ADD);
registerOperator("-", OP_SUBTRACT); registerOperator("-", OP_SUBTRACT);
registerOperator("`", OP_NEGATE);
registerOperator("*", OP_MULTIPLY); registerOperator("*", OP_MULTIPLY);
registerOperator("/", OP_DIVIDE); registerOperator("/", OP_DIVIDE);
registerOperator("^", OP_CARET); registerOperator("^", OP_CARET);
@@ -350,7 +335,7 @@ public class StandardPlugin extends Plugin {
public static NumberInterface factorial(Class<? extends NumberInterface> numberClass, int n){ public static NumberInterface factorial(Class<? extends NumberInterface> numberClass, int n){
if(!factorialLists.containsKey(numberClass)){ if(!factorialLists.containsKey(numberClass)){
factorialLists.put(numberClass, new ArrayList<>()); factorialLists.put(numberClass, new ArrayList<NumberInterface>());
factorialLists.get(numberClass).add(NaiveNumber.ONE.promoteTo(numberClass)); factorialLists.get(numberClass).add(NaiveNumber.ONE.promoteTo(numberClass));
factorialLists.get(numberClass).add(NaiveNumber.ONE.promoteTo(numberClass)); factorialLists.get(numberClass).add(NaiveNumber.ONE.promoteTo(numberClass));
} }

View File

@@ -3,7 +3,7 @@ package org.nwapw.abacus.tree;
/** /**
* A tree node that represents an operation being applied to two operands. * A tree node that represents an operation being applied to two operands.
*/ */
public class BinaryNode extends TreeNode { public class BinaryInfixNode extends TreeNode {
/** /**
* The operation being applied. * The operation being applied.
@@ -18,7 +18,7 @@ public class BinaryNode extends TreeNode {
*/ */
private TreeNode right; private TreeNode right;
private BinaryNode() { private BinaryInfixNode() {
} }
/** /**
@@ -27,7 +27,7 @@ public class BinaryNode extends TreeNode {
* *
* @param operation the operation. * @param operation the operation.
*/ */
public BinaryNode(String operation) { public BinaryInfixNode(String operation) {
this(operation, null, null); this(operation, null, null);
} }
@@ -39,7 +39,7 @@ public class BinaryNode extends TreeNode {
* @param left the left node of the expression. * @param left the left node of the expression.
* @param right the right node of the expression. * @param right the right node of the expression.
*/ */
public BinaryNode(String operation, TreeNode left, TreeNode right) { public BinaryInfixNode(String operation, TreeNode left, TreeNode right) {
this.operation = operation; this.operation = operation;
this.left = left; this.left = left;
this.right = right; this.right = right;

View File

@@ -28,15 +28,15 @@ public class NumberReducer implements Reducer<NumberInterface> {
public NumberInterface reduceNode(TreeNode node, Object... children) { public NumberInterface reduceNode(TreeNode node, Object... children) {
if (node instanceof NumberNode) { if (node instanceof NumberNode) {
return ((NumberNode) node).getNumber(); return ((NumberNode) node).getNumber();
} else if (node instanceof BinaryNode) { } else if (node instanceof BinaryInfixNode) {
NumberInterface left = (NumberInterface) children[0]; NumberInterface left = (NumberInterface) children[0];
NumberInterface right = (NumberInterface) children[1]; NumberInterface right = (NumberInterface) children[1];
Function function = abacus.getPluginManager().operatorFor(((BinaryNode) node).getOperation()).getFunction(); Function function = abacus.getPluginManager().operatorFor(((BinaryInfixNode) node).getOperation()).getFunction();
if (function == null) return null; if (function == null) return null;
return function.apply(left, right); return function.apply(left, right);
} else if (node instanceof UnaryNode) { } else if (node instanceof UnaryPrefixNode) {
NumberInterface child = (NumberInterface) children[0]; NumberInterface child = (NumberInterface) children[0];
Function functionn = abacus.getPluginManager().operatorFor(((UnaryNode) node).getOperation()).getFunction(); Function functionn = abacus.getPluginManager().operatorFor(((UnaryPrefixNode) node).getOperation()).getFunction();
if (functionn == null) return null; if (functionn == null) return null;
return functionn.apply(child); return functionn.apply(child);
} else if (node instanceof FunctionNode) { } else if (node instanceof FunctionNode) {

View File

@@ -1,6 +1,6 @@
package org.nwapw.abacus.tree; package org.nwapw.abacus.tree;
public class UnaryNode extends TreeNode { public class UnaryPrefixNode extends TreeNode {
/** /**
* The operation this node will apply. * The operation this node will apply.
@@ -16,7 +16,7 @@ public class UnaryNode extends TreeNode {
* *
* @param operation the operation for this node. * @param operation the operation for this node.
*/ */
public UnaryNode(String operation) { public UnaryPrefixNode(String operation) {
this(operation, null); this(operation, null);
} }
@@ -26,7 +26,7 @@ public class UnaryNode extends TreeNode {
* @param operation the operation for this node. * @param operation the operation for this node.
* @param applyTo the node to apply the function to. * @param applyTo the node to apply the function to.
*/ */
public UnaryNode(String operation, TreeNode applyTo) { public UnaryPrefixNode(String operation, TreeNode applyTo) {
this.operation = operation; this.operation = operation;
this.applyTo = applyTo; this.applyTo = applyTo;
} }

View File

@@ -46,6 +46,9 @@
<padding><Insets left="10" right="10" top="10" bottom="10"/></padding> <padding><Insets left="10" right="10" top="10" bottom="10"/></padding>
<Label text="Number Implementation" GridPane.columnIndex="0" GridPane.rowIndex="0"/> <Label text="Number Implementation" GridPane.columnIndex="0" GridPane.rowIndex="0"/>
<ComboBox fx:id="numberImplementationBox" GridPane.columnIndex="1" GridPane.rowIndex="0"/> <ComboBox fx:id="numberImplementationBox" GridPane.columnIndex="1" GridPane.rowIndex="0"/>
<Button fx:id="loadButton" text="Load" GridPane.rowIndex="1" GridPane.columnIndex="0" maxWidth = "Infinity" onAction="#loadClass"/>
<Button fx:id="unloadButton" text="Unload" GridPane.rowIndex="1" GridPane.columnIndex="1" maxWidth = "Infinity" onAction="#unloadClass"/>
<TextField fx:id="loadField" GridPane.rowIndex="1" GridPane.columnIndex="2"/>
</GridPane> </GridPane>
</Tab> </Tab>
</TabPane> </TabPane>