mirror of
https://github.com/DanilaFe/abacus
synced 2026-01-26 08:35:20 +00:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e6cf08ec2 | ||
|
|
fee9f091fd | ||
|
|
4226df72f5 | ||
|
|
1f0e6a7ce4 | ||
|
|
efe76a6fdc | ||
|
|
ca6d8d2ba2 | ||
|
|
1d6957c4d9 | ||
|
|
b6e4c6d2ea | ||
| 12710c625b | |||
| e71b037195 | |||
| fe92929856 | |||
| ff7d90967e | |||
| 355a91d690 | |||
| 5f0fba15eb | |||
| 3bdc0e2ae5 | |||
| e54b5cdd66 | |||
| fd87cb66a3 | |||
| 200f4c7288 | |||
| f28e915c9a | |||
| 7a0863380a |
@@ -1,3 +1,8 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
id 'application'
|
||||||
|
id 'org.jetbrains.kotlin.jvm' version '1.1.3'
|
||||||
|
}
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
apply plugin: 'application'
|
apply plugin: 'application'
|
||||||
|
|
||||||
@@ -7,6 +12,7 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.moandjiezana.toml:toml4j:0.7.1'
|
compile 'com.moandjiezana.toml:toml4j:0.7.1'
|
||||||
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8"
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
package org.nwapw.abacus.function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class that represents a single infix operator.
|
|
||||||
*/
|
|
||||||
public class Operator {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The associativity of the operator.
|
|
||||||
*/
|
|
||||||
private OperatorAssociativity associativity;
|
|
||||||
/**
|
|
||||||
* The type of this operator.
|
|
||||||
*/
|
|
||||||
private OperatorType type;
|
|
||||||
/**
|
|
||||||
* The precedence of the operator.
|
|
||||||
*/
|
|
||||||
private int precedence;
|
|
||||||
/**
|
|
||||||
* The function that is called by this operator.
|
|
||||||
*/
|
|
||||||
private Function function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new operator with the given parameters.
|
|
||||||
*
|
|
||||||
* @param associativity the associativity of the operator.
|
|
||||||
* @param operatorType the type of this operator, like binary infix or unary postfix.
|
|
||||||
* @param precedence the precedence of the operator.
|
|
||||||
* @param function the function that the operator calls.
|
|
||||||
*/
|
|
||||||
public Operator(OperatorAssociativity associativity, OperatorType operatorType, int precedence, Function function) {
|
|
||||||
this.associativity = associativity;
|
|
||||||
this.type = operatorType;
|
|
||||||
this.precedence = precedence;
|
|
||||||
this.function = function;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the operator's associativity.
|
|
||||||
*
|
|
||||||
* @return the associativity.
|
|
||||||
*/
|
|
||||||
public OperatorAssociativity getAssociativity() {
|
|
||||||
return associativity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the operator's type.
|
|
||||||
*
|
|
||||||
* @return the type.
|
|
||||||
*/
|
|
||||||
public OperatorType getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the operator's precedence.
|
|
||||||
*
|
|
||||||
* @return the precedence.
|
|
||||||
*/
|
|
||||||
public int getPrecedence() {
|
|
||||||
return precedence;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the operator's function.
|
|
||||||
*
|
|
||||||
* @return the function.
|
|
||||||
*/
|
|
||||||
public Function getFunction() {
|
|
||||||
return function;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -5,6 +5,7 @@ import javafx.beans.value.ChangeListener;
|
|||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.collections.transformation.FilteredList;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.cell.CheckBoxListCell;
|
import javafx.scene.control.cell.CheckBoxListCell;
|
||||||
@@ -72,6 +73,8 @@ public class AbacusController implements PluginListener {
|
|||||||
@FXML
|
@FXML
|
||||||
private Tab settingsTab;
|
private Tab settingsTab;
|
||||||
@FXML
|
@FXML
|
||||||
|
private Tab functionListTab;
|
||||||
|
@FXML
|
||||||
private TableView<HistoryModel> historyTable;
|
private TableView<HistoryModel> historyTable;
|
||||||
@FXML
|
@FXML
|
||||||
private TableColumn<HistoryModel, String> inputColumn;
|
private TableColumn<HistoryModel, String> inputColumn;
|
||||||
@@ -93,6 +96,10 @@ public class AbacusController implements PluginListener {
|
|||||||
private ListView<ToggleablePlugin> enabledPluginView;
|
private ListView<ToggleablePlugin> enabledPluginView;
|
||||||
@FXML
|
@FXML
|
||||||
private TextField computationLimitField;
|
private TextField computationLimitField;
|
||||||
|
@FXML
|
||||||
|
private ListView<String> functionListView;
|
||||||
|
@FXML
|
||||||
|
private TextField functionListSearchField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of history entries, created by the users.
|
* The list of history entries, created by the users.
|
||||||
@@ -110,6 +117,14 @@ public class AbacusController implements PluginListener {
|
|||||||
* and, when reloaded, get added to the plugin manager's black list.
|
* and, when reloaded, get added to the plugin manager's black list.
|
||||||
*/
|
*/
|
||||||
private ObservableList<ToggleablePlugin> enabledPlugins;
|
private ObservableList<ToggleablePlugin> enabledPlugins;
|
||||||
|
/**
|
||||||
|
* The list of functions that are registered in the calculator.
|
||||||
|
*/
|
||||||
|
private ObservableList<String> functionList;
|
||||||
|
/**
|
||||||
|
* The filtered list displayed to the user.
|
||||||
|
*/
|
||||||
|
private FilteredList<String> functionFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The abacus instance used for changing the plugin configuration.
|
* The abacus instance used for changing the plugin configuration.
|
||||||
@@ -201,7 +216,7 @@ public class AbacusController implements PluginListener {
|
|||||||
Callback<TableColumn<HistoryModel, String>, TableCell<HistoryModel, String>> cellFactory =
|
Callback<TableColumn<HistoryModel, String>, TableCell<HistoryModel, String>> cellFactory =
|
||||||
param -> new CopyableCell<>();
|
param -> new CopyableCell<>();
|
||||||
Callback<ListView<ToggleablePlugin>, ListCell<ToggleablePlugin>> pluginCellFactory =
|
Callback<ListView<ToggleablePlugin>, ListCell<ToggleablePlugin>> pluginCellFactory =
|
||||||
param -> new CheckBoxListCell<>(ToggleablePlugin::enabledProperty, new StringConverter<ToggleablePlugin>() {
|
param -> new CheckBoxListCell<>(ToggleablePlugin::getEnabledProperty, new StringConverter<ToggleablePlugin>() {
|
||||||
@Override
|
@Override
|
||||||
public String toString(ToggleablePlugin object) {
|
public String toString(ToggleablePlugin object) {
|
||||||
return object.getClassName().substring(object.getClassName().lastIndexOf('.') + 1);
|
return object.getClassName().substring(object.getClassName().lastIndexOf('.') + 1);
|
||||||
@@ -209,10 +224,15 @@ public class AbacusController implements PluginListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ToggleablePlugin fromString(String string) {
|
public ToggleablePlugin fromString(String string) {
|
||||||
return new ToggleablePlugin(true, string);
|
return new ToggleablePlugin(string, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
functionList = FXCollections.observableArrayList();
|
||||||
|
functionFilter = new FilteredList<>(functionList, (s) -> true);
|
||||||
|
functionListView.setItems(functionFilter);
|
||||||
|
functionListSearchField.textProperty().addListener((observable, oldValue, newValue) ->
|
||||||
|
functionFilter.setPredicate((newValue.length() == 0) ? ((s) -> true) : ((s) -> s.contains(newValue))));
|
||||||
historyData = FXCollections.observableArrayList();
|
historyData = FXCollections.observableArrayList();
|
||||||
historyTable.setItems(historyData);
|
historyTable.setItems(historyData);
|
||||||
numberImplementationOptions = FXCollections.observableArrayList();
|
numberImplementationOptions = FXCollections.observableArrayList();
|
||||||
@@ -223,11 +243,11 @@ public class AbacusController implements PluginListener {
|
|||||||
enabledPluginView.setItems(enabledPlugins);
|
enabledPluginView.setItems(enabledPlugins);
|
||||||
enabledPluginView.setCellFactory(pluginCellFactory);
|
enabledPluginView.setCellFactory(pluginCellFactory);
|
||||||
inputColumn.setCellFactory(cellFactory);
|
inputColumn.setCellFactory(cellFactory);
|
||||||
inputColumn.setCellValueFactory(cell -> cell.getValue().inputProperty());
|
inputColumn.setCellValueFactory(cell -> cell.getValue().getInputProperty());
|
||||||
parsedColumn.setCellFactory(cellFactory);
|
parsedColumn.setCellFactory(cellFactory);
|
||||||
parsedColumn.setCellValueFactory(cell -> cell.getValue().parsedProperty());
|
parsedColumn.setCellValueFactory(cell -> cell.getValue().getParsedProperty());
|
||||||
outputColumn.setCellFactory(cellFactory);
|
outputColumn.setCellFactory(cellFactory);
|
||||||
outputColumn.setCellValueFactory(cell -> cell.getValue().outputProperty());
|
outputColumn.setCellValueFactory(cell -> cell.getValue().getOutputProperty());
|
||||||
coreTabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
|
coreTabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
if (oldValue.equals(settingsTab)) alertIfApplyNeeded(true);
|
if (oldValue.equals(settingsTab)) alertIfApplyNeeded(true);
|
||||||
});
|
});
|
||||||
@@ -323,14 +343,17 @@ public class AbacusController implements PluginListener {
|
|||||||
numberImplementationBox.getSelectionModel().select(toSelect);
|
numberImplementationBox.getSelectionModel().select(toSelect);
|
||||||
for (Class<?> pluginClass : abacus.getPluginManager().getLoadedPluginClasses()) {
|
for (Class<?> pluginClass : abacus.getPluginManager().getLoadedPluginClasses()) {
|
||||||
String fullName = pluginClass.getName();
|
String fullName = pluginClass.getName();
|
||||||
ToggleablePlugin plugin = new ToggleablePlugin(!disabledPlugins.contains(fullName), fullName);
|
ToggleablePlugin plugin = new ToggleablePlugin(fullName, !disabledPlugins.contains(fullName));
|
||||||
plugin.enabledProperty().addListener(e -> changesMade = true);
|
plugin.getEnabledProperty().addListener(e -> changesMade = true);
|
||||||
enabledPlugins.add(plugin);
|
enabledPlugins.add(plugin);
|
||||||
}
|
}
|
||||||
|
functionList.addAll(manager.getAllFunctions());
|
||||||
|
functionList.sort(String::compareTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUnload(PluginManager manager) {
|
public void onUnload(PluginManager manager) {
|
||||||
|
functionList.clear();
|
||||||
enabledPlugins.clear();
|
enabledPlugins.clear();
|
||||||
numberImplementationOptions.clear();
|
numberImplementationOptions.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
package org.nwapw.abacus.fx;
|
|
||||||
|
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
|
||||||
import javafx.beans.property.StringProperty;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The data model used for storing history entries.
|
|
||||||
*/
|
|
||||||
public class HistoryModel {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The property used for displaying the column
|
|
||||||
* for the user input.
|
|
||||||
*/
|
|
||||||
private final StringProperty input;
|
|
||||||
/**
|
|
||||||
* The property used for displaying the column
|
|
||||||
* that contains the parsed input.
|
|
||||||
*/
|
|
||||||
private final StringProperty parsed;
|
|
||||||
/**
|
|
||||||
* The property used for displaying the column
|
|
||||||
* that contains the program output.
|
|
||||||
*/
|
|
||||||
private final StringProperty output;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new history model with the given variables.
|
|
||||||
*
|
|
||||||
* @param input the user input
|
|
||||||
* @param parsed the parsed input
|
|
||||||
* @param output the program output.
|
|
||||||
*/
|
|
||||||
public HistoryModel(String input, String parsed, String output) {
|
|
||||||
this.input = new SimpleStringProperty();
|
|
||||||
this.parsed = new SimpleStringProperty();
|
|
||||||
this.output = new SimpleStringProperty();
|
|
||||||
this.input.setValue(input);
|
|
||||||
this.parsed.setValue(parsed);
|
|
||||||
this.output.setValue(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the input property.
|
|
||||||
*
|
|
||||||
* @return the input property.
|
|
||||||
*/
|
|
||||||
public StringProperty inputProperty() {
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the input.
|
|
||||||
*
|
|
||||||
* @return the input.
|
|
||||||
*/
|
|
||||||
public String getInput() {
|
|
||||||
return input.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the parsed input property.
|
|
||||||
*
|
|
||||||
* @return the parsed input property.
|
|
||||||
*/
|
|
||||||
public StringProperty parsedProperty() {
|
|
||||||
return parsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the parsed input.
|
|
||||||
*
|
|
||||||
* @return the parsed input.
|
|
||||||
*/
|
|
||||||
public String getParsed() {
|
|
||||||
return parsed.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the output property.
|
|
||||||
*
|
|
||||||
* @return the output property.
|
|
||||||
*/
|
|
||||||
public StringProperty outputProperty() {
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the program output.
|
|
||||||
*
|
|
||||||
* @return the output.
|
|
||||||
*/
|
|
||||||
public String getOutput() {
|
|
||||||
return output.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package org.nwapw.abacus.fx;
|
|
||||||
|
|
||||||
import javafx.beans.property.BooleanProperty;
|
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class that represents an entry in the plugin check box list.
|
|
||||||
* The changes from this property are written to the config on application.
|
|
||||||
*/
|
|
||||||
public class ToggleablePlugin {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The property that determines whether the plugin will be enabled.
|
|
||||||
*/
|
|
||||||
private final BooleanProperty enabled;
|
|
||||||
/**
|
|
||||||
* The name of the class this entry toggles.
|
|
||||||
*/
|
|
||||||
private final String className;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new toggleable plugin with the given properties.
|
|
||||||
*
|
|
||||||
* @param enabled the enabled / disabled state at the beginning.
|
|
||||||
* @param className the name of the class this plugin toggles.
|
|
||||||
*/
|
|
||||||
public ToggleablePlugin(boolean enabled, String className) {
|
|
||||||
this.enabled = new SimpleBooleanProperty();
|
|
||||||
this.enabled.setValue(enabled);
|
|
||||||
this.className = className;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the enabled property of this plugin.
|
|
||||||
*
|
|
||||||
* @return the enabled property.
|
|
||||||
*/
|
|
||||||
public BooleanProperty enabledProperty() {
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if this plugin entry should be enabled.
|
|
||||||
*
|
|
||||||
* @return whether this plugin will be enabled.
|
|
||||||
*/
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return enabled.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the class name this plugin toggles.
|
|
||||||
*
|
|
||||||
* @return the class name that should be disabled.
|
|
||||||
*/
|
|
||||||
public String getClassName() {
|
|
||||||
return className;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -209,6 +209,9 @@ public class PluginManager {
|
|||||||
if (disabledPlugins.contains(plugin.getClass().getName())) continue;
|
if (disabledPlugins.contains(plugin.getClass().getName())) continue;
|
||||||
plugin.disable();
|
plugin.disable();
|
||||||
}
|
}
|
||||||
|
registeredFunctions.clear();
|
||||||
|
registeredOperators.clear();
|
||||||
|
registeredNumberImplementations.clear();
|
||||||
cachedInterfaceImplementations.clear();
|
cachedInterfaceImplementations.clear();
|
||||||
cachedPi.clear();
|
cachedPi.clear();
|
||||||
listeners.forEach(e -> e.onUnload(this));
|
listeners.forEach(e -> e.onUnload(this));
|
||||||
|
|||||||
@@ -451,6 +451,144 @@ public class StandardPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arcsine function (return type in radians).
|
||||||
|
*/
|
||||||
|
public final Function functionArcsin = new Function() {
|
||||||
|
@Override
|
||||||
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
|
return params.length == 1
|
||||||
|
&& FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), 1)) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
|
if(FUNCTION_ABS.apply(params[0]).compareTo(new NaiveNumber(0.8).promoteTo(params[0].getClass())) >= 0){
|
||||||
|
NumberInterface[] newParams = {FUNCTION_SQRT.apply(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))};
|
||||||
|
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
||||||
|
.subtract(applyInternal(newParams)).multiply(fromInt(params[0].getClass(), params[0].signum()));
|
||||||
|
}
|
||||||
|
NumberInterface currentTerm = params[0], sum = currentTerm,
|
||||||
|
multiplier = currentTerm.multiply(currentTerm), summandBound = sum.getMaxError().multiply(fromInt(sum.getClass(), 1).subtract(multiplier)),
|
||||||
|
power = currentTerm, coefficient = fromInt(params[0].getClass(), 1);
|
||||||
|
int exponent = 1;
|
||||||
|
while(FUNCTION_ABS.apply(currentTerm).compareTo(summandBound) > 0){
|
||||||
|
exponent += 2;
|
||||||
|
power = power.multiply(multiplier);
|
||||||
|
coefficient = coefficient.multiply(fromInt(params[0].getClass(), exponent-2))
|
||||||
|
.divide(fromInt(params[0].getClass(), exponent - 1));
|
||||||
|
currentTerm = power.multiply(coefficient).divide(fromInt(power.getClass(), exponent));
|
||||||
|
sum = sum.add(currentTerm);
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arccosine function.
|
||||||
|
*/
|
||||||
|
public final Function functionArccos = new Function() {
|
||||||
|
@Override
|
||||||
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
|
return params.length == 1 && FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), 1)) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
|
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
||||||
|
.subtract(functionArcsin.apply(params));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arccosecant function.
|
||||||
|
*/
|
||||||
|
public final Function functionArccsc = new Function() {
|
||||||
|
@Override
|
||||||
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
|
return params.length == 1 && FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), 1)) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
|
NumberInterface[] reciprocalParamArr = {fromInt(params[0].getClass(), 1).divide(params[0])};
|
||||||
|
return functionArcsin.apply(reciprocalParamArr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arcsecant function.
|
||||||
|
*/
|
||||||
|
public final Function functionArcsec = new Function() {
|
||||||
|
@Override
|
||||||
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
|
return params.length == 1 && FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), 1)) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
|
NumberInterface[] reciprocalParamArr = {fromInt(params[0].getClass(), 1).divide(params[0])};
|
||||||
|
return functionArccos.apply(reciprocalParamArr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arctangent function.
|
||||||
|
*/
|
||||||
|
public final Function functionArctan = new Function() {
|
||||||
|
@Override
|
||||||
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
|
return params.length == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
|
if(params[0].signum() == -1){
|
||||||
|
NumberInterface[] negatedParams = {params[0].negate()};
|
||||||
|
return applyInternal(negatedParams).negate();
|
||||||
|
}
|
||||||
|
if(params[0].compareTo(fromInt(params[0].getClass(), 1)) > 0){
|
||||||
|
NumberInterface[] reciprocalParams = {fromInt(params[0].getClass(), 1).divide(params[0])};
|
||||||
|
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
||||||
|
.subtract(applyInternal(reciprocalParams));
|
||||||
|
}
|
||||||
|
if(params[0].compareTo(fromInt(params[0].getClass(), 1)) == 0){
|
||||||
|
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 4));
|
||||||
|
}
|
||||||
|
if(params[0].compareTo(new NaiveNumber(0.9).promoteTo(params[0].getClass())) >= 0){
|
||||||
|
NumberInterface[] newParams = {params[0].multiply(fromInt(params[0].getClass(),2 ))
|
||||||
|
.divide(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))};
|
||||||
|
return applyInternal(newParams).divide(fromInt(params[0].getClass(), 2));
|
||||||
|
}
|
||||||
|
NumberInterface currentPower = params[0], currentTerm = currentPower, sum = currentTerm,
|
||||||
|
maxError = params[0].getMaxError(), multiplier = currentPower.multiply(currentPower).negate();
|
||||||
|
int n = 1;
|
||||||
|
while(FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0){
|
||||||
|
n += 2;
|
||||||
|
currentPower = currentPower.multiply(multiplier);
|
||||||
|
currentTerm = currentPower.divide(fromInt(currentPower.getClass(), n));
|
||||||
|
sum = sum.add(currentTerm);
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arccotangent function. Range: (0, pi).
|
||||||
|
*/
|
||||||
|
public final Function functionArccot = new Function() {
|
||||||
|
@Override
|
||||||
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
|
return params.length == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
|
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
||||||
|
.subtract(functionArctan.apply(params));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public StandardPlugin(PluginManager manager) {
|
public StandardPlugin(PluginManager manager) {
|
||||||
super(manager);
|
super(manager);
|
||||||
}
|
}
|
||||||
@@ -568,6 +706,12 @@ public class StandardPlugin extends Plugin {
|
|||||||
registerFunction("sec", functionSec);
|
registerFunction("sec", functionSec);
|
||||||
registerFunction("csc", functionCsc);
|
registerFunction("csc", functionCsc);
|
||||||
registerFunction("cot", functionCot);
|
registerFunction("cot", functionCot);
|
||||||
|
registerFunction("arcsin", functionArcsin);
|
||||||
|
registerFunction("arccos", functionArccos);
|
||||||
|
registerFunction("arccsc", functionArccsc);
|
||||||
|
registerFunction("arcsec", functionArcsec);
|
||||||
|
registerFunction("arctan", functionArctan);
|
||||||
|
registerFunction("arccot", functionArccot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
package org.nwapw.abacus.tree;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A tree node that represents an operation being applied to two operands.
|
|
||||||
*/
|
|
||||||
public class BinaryNode extends TreeNode {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The operation being applied.
|
|
||||||
*/
|
|
||||||
private String operation;
|
|
||||||
/**
|
|
||||||
* The left node of the operation.
|
|
||||||
*/
|
|
||||||
private TreeNode left;
|
|
||||||
/**
|
|
||||||
* The right node of the operation.
|
|
||||||
*/
|
|
||||||
private TreeNode right;
|
|
||||||
|
|
||||||
private BinaryNode() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new operation node with the given operation
|
|
||||||
* and no child nodes.
|
|
||||||
*
|
|
||||||
* @param operation the operation.
|
|
||||||
*/
|
|
||||||
public BinaryNode(String operation) {
|
|
||||||
this(operation, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new operation node with the given operation
|
|
||||||
* and child nodes.
|
|
||||||
*
|
|
||||||
* @param operation the operation.
|
|
||||||
* @param left the left node of the expression.
|
|
||||||
* @param right the right node of the expression.
|
|
||||||
*/
|
|
||||||
public BinaryNode(String operation, TreeNode left, TreeNode right) {
|
|
||||||
this.operation = operation;
|
|
||||||
this.left = left;
|
|
||||||
this.right = right;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the operation in this node.
|
|
||||||
*
|
|
||||||
* @return the operation in this node.
|
|
||||||
*/
|
|
||||||
public String getOperation() {
|
|
||||||
return operation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the left sub-expression of this node.
|
|
||||||
*
|
|
||||||
* @return the left node.
|
|
||||||
*/
|
|
||||||
public TreeNode getLeft() {
|
|
||||||
return left;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the left sub-expression of this node.
|
|
||||||
*
|
|
||||||
* @param left the sub-expression to apply.
|
|
||||||
*/
|
|
||||||
public void setLeft(TreeNode left) {
|
|
||||||
this.left = left;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the right sub-expression of this node.
|
|
||||||
*
|
|
||||||
* @return the right node.
|
|
||||||
*/
|
|
||||||
public TreeNode getRight() {
|
|
||||||
return right;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the right sub-expression of this node.
|
|
||||||
*
|
|
||||||
* @param right the sub-expression to apply.
|
|
||||||
*/
|
|
||||||
public void setRight(TreeNode right) {
|
|
||||||
this.right = right;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T reduce(Reducer<T> reducer) {
|
|
||||||
T leftReduce = left.reduce(reducer);
|
|
||||||
T rightReduce = right.reduce(reducer);
|
|
||||||
if (leftReduce == null || rightReduce == null) return null;
|
|
||||||
return reducer.reduceNode(this, leftReduce, rightReduce);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
String leftString = left != null ? left.toString() : "null";
|
|
||||||
String rightString = right != null ? right.toString() : "null";
|
|
||||||
|
|
||||||
return "(" + leftString + operation + rightString + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
package org.nwapw.abacus.tree;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A node that represents a function call.
|
|
||||||
*/
|
|
||||||
public class FunctionNode extends TreeNode {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the function being called
|
|
||||||
*/
|
|
||||||
private String function;
|
|
||||||
/**
|
|
||||||
* The list of arguments to the function.
|
|
||||||
*/
|
|
||||||
private List<TreeNode> children;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a function node with no function.
|
|
||||||
*/
|
|
||||||
private FunctionNode() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new function node with the given function name.
|
|
||||||
*
|
|
||||||
* @param function the function name.
|
|
||||||
*/
|
|
||||||
public FunctionNode(String function) {
|
|
||||||
this.function = function;
|
|
||||||
children = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the function name for this node.
|
|
||||||
*
|
|
||||||
* @return the function name.
|
|
||||||
*/
|
|
||||||
public String getFunction() {
|
|
||||||
return function;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a child to the end of this node's child list.
|
|
||||||
*
|
|
||||||
* @param node the child to add.
|
|
||||||
*/
|
|
||||||
public void appendChild(TreeNode node) {
|
|
||||||
children.add(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new child to the beginning of this node's child list.
|
|
||||||
*
|
|
||||||
* @param node the node to add.
|
|
||||||
*/
|
|
||||||
public void prependChild(TreeNode node) {
|
|
||||||
children.add(0, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T reduce(Reducer<T> reducer) {
|
|
||||||
Object[] reducedChildren = new Object[children.size()];
|
|
||||||
for (int i = 0; i < reducedChildren.length; i++) {
|
|
||||||
reducedChildren[i] = children.get(i).reduce(reducer);
|
|
||||||
if (reducedChildren[i] == null) return null;
|
|
||||||
}
|
|
||||||
return reducer.reduceNode(this, reducedChildren);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder buffer = new StringBuilder();
|
|
||||||
buffer.append(function);
|
|
||||||
buffer.append("(");
|
|
||||||
for (int i = 0; i < children.size(); i++) {
|
|
||||||
buffer.append(children.get(i));
|
|
||||||
buffer.append(i == children.size() - 1 ? "" : ", ");
|
|
||||||
}
|
|
||||||
buffer.append(")");
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
package org.nwapw.abacus.tree;
|
|
||||||
|
|
||||||
import org.nwapw.abacus.number.NumberInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A node implementation that represents a single number.
|
|
||||||
*/
|
|
||||||
public class NumberNode extends TreeNode {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number that is represented by this number node.
|
|
||||||
*/
|
|
||||||
private NumberInterface number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a number node with no number.
|
|
||||||
*/
|
|
||||||
public NumberNode() {
|
|
||||||
number = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new number node with the given double value.
|
|
||||||
*
|
|
||||||
* @param newNumber the number for which to create a number node.
|
|
||||||
*/
|
|
||||||
public NumberNode(NumberInterface newNumber) {
|
|
||||||
this.number = newNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the number value of this node.
|
|
||||||
*
|
|
||||||
* @return the number value of this node.
|
|
||||||
*/
|
|
||||||
public NumberInterface getNumber() {
|
|
||||||
return number;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T reduce(Reducer<T> reducer) {
|
|
||||||
return reducer.reduceNode(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return number != null ? number.toString() : "null";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package org.nwapw.abacus.tree;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An abstract class that represents an expression tree node.
|
|
||||||
*/
|
|
||||||
public abstract class TreeNode {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The function that reduces a tree to a single vale.
|
|
||||||
*
|
|
||||||
* @param reducer the reducer used to reduce the tree.
|
|
||||||
* @param <T> the type the reducer produces.
|
|
||||||
* @return the result of the reduction, or null on error.
|
|
||||||
*/
|
|
||||||
public abstract <T> T reduce(Reducer<T> reducer);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
package org.nwapw.abacus.tree;
|
|
||||||
|
|
||||||
public class UnaryNode extends TreeNode {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The operation this node will apply.
|
|
||||||
*/
|
|
||||||
private String operation;
|
|
||||||
/**
|
|
||||||
* The tree node to apply the operation to.
|
|
||||||
*/
|
|
||||||
private TreeNode applyTo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new node with the given operation and no child.
|
|
||||||
*
|
|
||||||
* @param operation the operation for this node.
|
|
||||||
*/
|
|
||||||
public UnaryNode(String operation) {
|
|
||||||
this(operation, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new node with the given operation and child.
|
|
||||||
*
|
|
||||||
* @param operation the operation for this node.
|
|
||||||
* @param applyTo the node to apply the function to.
|
|
||||||
*/
|
|
||||||
public UnaryNode(String operation, TreeNode applyTo) {
|
|
||||||
this.operation = operation;
|
|
||||||
this.applyTo = applyTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T reduce(Reducer<T> reducer) {
|
|
||||||
Object reducedChild = applyTo.reduce(reducer);
|
|
||||||
if (reducedChild == null) return null;
|
|
||||||
return reducer.reduceNode(this, reducedChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the operation of this node.
|
|
||||||
*
|
|
||||||
* @return the operation this node performs.
|
|
||||||
*/
|
|
||||||
public String getOperation() {
|
|
||||||
return operation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the node to which this node's operation applies.
|
|
||||||
*
|
|
||||||
* @return the tree node to which the operation will be applied.
|
|
||||||
*/
|
|
||||||
public TreeNode getApplyTo() {
|
|
||||||
return applyTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "(" + (applyTo == null ? "null" : applyTo.toString()) + ")" + operation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
14
src/main/kotlin/org/nwapw/abacus/function/Operator.kt
Normal file
14
src/main/kotlin/org/nwapw/abacus/function/Operator.kt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package org.nwapw.abacus.function
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single operator that can be used by Abacus.
|
||||||
|
*
|
||||||
|
* This is a data class that holds the information about a single operator, such as a plus or minus.
|
||||||
|
*
|
||||||
|
* @param associativity the associativity of this operator, used for order of operations;.
|
||||||
|
* @param type the type of this operator, used for parsing (infix / prefix / postfix and binary / unary)
|
||||||
|
* @param precedence the precedence of this operator, used for order of operations.
|
||||||
|
* @param function the function this operator applies to its arguments.
|
||||||
|
*/
|
||||||
|
data class Operator(val associativity: OperatorAssociativity, val type: OperatorType,
|
||||||
|
val precedence: Int, val function: Function)
|
||||||
32
src/main/kotlin/org/nwapw/abacus/fx/HistoryModel.kt
Normal file
32
src/main/kotlin/org/nwapw/abacus/fx/HistoryModel.kt
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package org.nwapw.abacus.fx
|
||||||
|
|
||||||
|
import javafx.beans.property.SimpleStringProperty
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A model representing an input / output in the calculator.
|
||||||
|
*
|
||||||
|
* The HistoryModel class stores a record of a single user-provided input,
|
||||||
|
* its parsed form as it was interpreted by the calculator, and the output
|
||||||
|
* that was provided by the calculator. These are represented as properties
|
||||||
|
* to allow easy access by JavaFX cells.
|
||||||
|
*
|
||||||
|
* @param input the user input
|
||||||
|
* @param parsed the parsed version of the input.
|
||||||
|
* @param output the output string.
|
||||||
|
*/
|
||||||
|
class HistoryModel(input: String, parsed: String, output: String){
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property that holds the input.
|
||||||
|
*/
|
||||||
|
val inputProperty = SimpleStringProperty(input)
|
||||||
|
/**
|
||||||
|
* The property that holds the parsed input.
|
||||||
|
*/
|
||||||
|
val parsedProperty = SimpleStringProperty(parsed)
|
||||||
|
/**
|
||||||
|
* The property that holds the output.
|
||||||
|
*/
|
||||||
|
val outputProperty = SimpleStringProperty(output)
|
||||||
|
|
||||||
|
}
|
||||||
31
src/main/kotlin/org/nwapw/abacus/fx/ToggleablePlugin.kt
Normal file
31
src/main/kotlin/org/nwapw/abacus/fx/ToggleablePlugin.kt
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package org.nwapw.abacus.fx
|
||||||
|
|
||||||
|
import javafx.beans.property.SimpleBooleanProperty
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A model representing a plugin that can be disabled or enabled.
|
||||||
|
*
|
||||||
|
* ToggleablePlugin is a model that is used to present to the user the option
|
||||||
|
* of disabling / enabling plugins. The class name in this plugin is stored if
|
||||||
|
* its "enabledPropery" is false, essentially blacklisting the plugin.
|
||||||
|
*
|
||||||
|
* @param className the name of the class that this model concerns.
|
||||||
|
* @param enabled whether or not the model should start enabled.
|
||||||
|
*/
|
||||||
|
class ToggleablePlugin (val className: String, enabled: Boolean) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property used to interact with JavaFX components.
|
||||||
|
*/
|
||||||
|
val enabledProperty = SimpleBooleanProperty(enabled)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this plugin is currently enabled or not.
|
||||||
|
*
|
||||||
|
* @return true if it is enabled, false otherwise.
|
||||||
|
*/
|
||||||
|
fun isEnabled(): Boolean {
|
||||||
|
return enabledProperty.value
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
26
src/main/kotlin/org/nwapw/abacus/tree/BinaryNode.kt
Normal file
26
src/main/kotlin/org/nwapw/abacus/tree/BinaryNode.kt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package org.nwapw.abacus.tree
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tree node that holds a binary operation.
|
||||||
|
*
|
||||||
|
* This node represents any binary operation, such as binary infix or binary postfix. The only
|
||||||
|
* currently implemented into Abacus is binary infix, but that has more to do with the parser than
|
||||||
|
* this class, which doesn't care about the order that its operation and nodes were found in text.
|
||||||
|
*
|
||||||
|
* @param operation the operation this node performs on its children.
|
||||||
|
* @param left the left node.
|
||||||
|
* @param right the right node.
|
||||||
|
*/
|
||||||
|
data class BinaryNode(val operation: String, val left: TreeNode? = null, val right: TreeNode?) : TreeNode() {
|
||||||
|
|
||||||
|
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||||
|
val leftReduce = left?.reduce(reducer) ?: return null
|
||||||
|
val rightReduce = right?.reduce(reducer) ?: return null
|
||||||
|
return reducer.reduceNode(this, leftReduce, rightReduce)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "(" + (left?.toString() ?: "null") + operation + (right?.toString() ?: "null") + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
52
src/main/kotlin/org/nwapw/abacus/tree/FunctionNode.kt
Normal file
52
src/main/kotlin/org/nwapw/abacus/tree/FunctionNode.kt
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package org.nwapw.abacus.tree
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tree node that holds a function call.
|
||||||
|
*
|
||||||
|
* The function call node can hold any number of children, and passes the to the appropriate reducer,
|
||||||
|
* but that is its sole purpose.
|
||||||
|
*
|
||||||
|
* @param function the function string.
|
||||||
|
*/
|
||||||
|
data class FunctionNode(val function: String) : TreeNode() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of function parameters added to this node.
|
||||||
|
*/
|
||||||
|
val children: MutableList<TreeNode> = mutableListOf()
|
||||||
|
|
||||||
|
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||||
|
val children = Array<Any?>(children.size, { children[it].reduce(reducer) ?: return null; })
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
23
src/main/kotlin/org/nwapw/abacus/tree/NumberNode.kt
Normal file
23
src/main/kotlin/org/nwapw/abacus/tree/NumberNode.kt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package org.nwapw.abacus.tree
|
||||||
|
|
||||||
|
import org.nwapw.abacus.number.NumberInterface
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tree node that holds a single number value.
|
||||||
|
*
|
||||||
|
* This is a tree node that holds a single NumberInterface, which represents any number,
|
||||||
|
* and is not defined during compile time.
|
||||||
|
*
|
||||||
|
* @number the number value of this node.
|
||||||
|
*/
|
||||||
|
data class NumberNode(val number: NumberInterface) : TreeNode() {
|
||||||
|
|
||||||
|
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||||
|
return reducer.reduceNode(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return number.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
10
src/main/kotlin/org/nwapw/abacus/tree/TreeNode.kt
Normal file
10
src/main/kotlin/org/nwapw/abacus/tree/TreeNode.kt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package org.nwapw.abacus.tree
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tree node.
|
||||||
|
*/
|
||||||
|
abstract class TreeNode {
|
||||||
|
|
||||||
|
abstract fun <T: Any> reduce(reducer: Reducer<T>) : T?
|
||||||
|
|
||||||
|
}
|
||||||
23
src/main/kotlin/org/nwapw/abacus/tree/UnaryNode.kt
Normal file
23
src/main/kotlin/org/nwapw/abacus/tree/UnaryNode.kt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package org.nwapw.abacus.tree
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tree node that holds a unary operation.
|
||||||
|
*
|
||||||
|
* This node holds a single operator applied to a single parameter, and does not care
|
||||||
|
* whether the operation was found before or after the parameter in the text.
|
||||||
|
*
|
||||||
|
* @param operation the operation applied to the given node.
|
||||||
|
* @param applyTo the node to which the operation will be applied.
|
||||||
|
*/
|
||||||
|
data class UnaryNode(val operation: String, val applyTo: TreeNode? = null) : TreeNode() {
|
||||||
|
|
||||||
|
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
|
||||||
|
val reducedChild = applyTo?.reduce(reducer) ?: return null
|
||||||
|
return reducer.reduceNode(this, reducedChild)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "(" + (applyTo?.toString() ?: "null") + ")" + operation
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -60,6 +60,15 @@
|
|||||||
</FlowPane>
|
</FlowPane>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</Tab>
|
</Tab>
|
||||||
|
<Tab fx:id="functionListTab" text="Functions" closable="false">
|
||||||
|
<VBox spacing="10">
|
||||||
|
<padding>
|
||||||
|
<Insets left="10" right="10" top="10" bottom="10"/>
|
||||||
|
</padding>
|
||||||
|
<TextField fx:id="functionListSearchField" maxWidth="Infinity"/>
|
||||||
|
<ListView maxWidth="Infinity" fx:id="functionListView"/>
|
||||||
|
</VBox>
|
||||||
|
</Tab>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user