1
0
mirror of https://github.com/DanilaFe/abacus synced 2026-01-25 08:05:19 +00:00

Compare commits

...

16 Commits

Author SHA1 Message Date
566831246c Add an exception thrown when promotion fails. 2017-09-20 12:06:06 -07:00
ad8a0a9b2a Merge pull request #29 from DanilaFe/fixes
Revert "Remove unnecessary nullability from parseString."
2017-09-16 03:05:20 -07:00
e430e738cf Merge branch 'master' into fixes 2017-09-16 03:03:52 -07:00
f6e326e0f1 Revert "Remove unnecessary nullability from parseString."
88e3bb7109
2017-09-16 03:02:35 -07:00
07581557c7 Merge pull request #27 from DanilaFe/fixes
Fix a number of small issues not worthy of their own branches.
2017-09-16 01:26:40 -07:00
14ac9c67f4 Implement the comparable interface. 2017-09-16 00:18:43 -07:00
0ff071e212 Add a more complete .gitignore 2017-09-16 00:17:03 -07:00
88e3bb7109 Remove unnecessary nullability from parseString. 2017-09-16 00:16:48 -07:00
540e5d6099 Load default implementation if one is not found. 2017-09-16 00:16:32 -07:00
c9e93d87a2 Merge pull request #23 from DanilaFe/thread-safety
Make some parts of the code more thread safe.
2017-09-15 22:59:42 -07:00
337edd68fa Merge branch 'master' into thread-safety 2017-09-15 22:58:33 -07:00
08967fbb8f Merge pull request #22 from DanilaFe/less-null
Remove some null-heavy parts of the code.
2017-09-15 22:56:54 -07:00
46f78bb2ed Merge pull request #21 from DanilaFe/context
Implement a Context system which allows concurrent creation of variables.
2017-09-15 22:51:56 -07:00
87529da15f Precompute all the transitions ahead of time. 2017-09-11 19:32:51 -07:00
7cd117dac1 Add synchronization to the Standard plugin. 2017-09-11 19:32:51 -07:00
8975bfdb99 Precompute Pi, and do not store documentation on access. 2017-09-11 19:32:51 -07:00
9 changed files with 56 additions and 49 deletions

4
.gitignore vendored
View File

@@ -24,7 +24,9 @@ hs_err_pid*
# Custom Stuff
# Gradle
.gradle/*
build/*
**/build/*
**/out/**
**/.DS_Store
# IntelliJ
.idea/*

View File

@@ -0,0 +1,24 @@
package org.nwapw.abacus.exception;
/**
* Exception thrown when a promotion fails.
*/
public class PromotionException extends AbacusException {
/**
* Creates a new PromotionException with the default message
* and no additional information.
*/
public PromotionException() {
this("");
}
/**
* Creates a new PromotionException with the given additional message.
* @param message the additional message to include with the error.
*/
public PromotionException(String message) {
super("Failed to promote number instances.", message);
}
}

View File

@@ -5,7 +5,7 @@ import org.nwapw.abacus.exception.ComputationInterruptedException;
/**
* An interface used to represent a number.
*/
public abstract class NumberInterface {
public abstract class NumberInterface implements Comparable<NumberInterface> {
/**
* Check if the thread was interrupted and
@@ -158,14 +158,6 @@ public abstract class NumberInterface {
return intPowInternal(exponent);
}
/**
* Compares this number to another.
*
* @param number the number to compare to.
* @return same as Integer.compare();
*/
public abstract int compareTo(NumberInterface number);
/**
* Same as Math.signum().
*

View File

@@ -141,6 +141,7 @@ public class PluginManager {
registeredNumberImplementations.put(name, implementation);
interfaceImplementationNames.put(implementation.getImplementation(), name);
interfaceImplementations.put(implementation.getImplementation(), implementation);
cachedPi.put(implementation.getImplementation(), implementation.instanceForPi());
}
/**
@@ -218,10 +219,6 @@ public class PluginManager {
break;
}
}
if (toReturn == null) {
toReturn = new Documentation(name, "", "", "", type);
registerDocumentation(toReturn);
}
return toReturn;
}
@@ -252,14 +249,7 @@ public class PluginManager {
* @return pi
*/
public NumberInterface piFor(Class<? extends NumberInterface> forClass) {
if (cachedPi.containsKey(forClass)) return cachedPi.get(forClass);
NumberImplementation implementation = interfaceImplementationFor(forClass);
NumberInterface generatedPi = null;
if (implementation != null) {
generatedPi = implementation.instanceForPi();
}
cachedPi.put(forClass, generatedPi);
return generatedPi;
return cachedPi.get(forClass);
}
/**

View File

@@ -693,8 +693,7 @@ public class StandardPlugin extends Plugin {
* @param n non-negative integer.
* @return a number of numClass with value n factorial.
*/
public static NumberInterface factorial(NumberImplementation implementation, int n) {
synchronized public static NumberInterface factorial(NumberImplementation implementation, int n) {
if (!FACTORIAL_LISTS.containsKey(implementation)) {
FACTORIAL_LISTS.put(implementation, new ArrayList<>());
FACTORIAL_LISTS.get(implementation).add(implementation.instanceForString("1"));

View File

@@ -68,6 +68,7 @@ class Abacus(val configuration: Configuration) {
pluginManager.reload()
with(mutableContext) {
numberImplementation = pluginManager.numberImplementationFor(configuration.numberImplementation)
?: StandardPlugin.IMPLEMENTATION_NAIVE
clearVariables()
clearDefinitions()
}

View File

@@ -1,6 +1,7 @@
package org.nwapw.abacus.number
import org.nwapw.abacus.Abacus
import org.nwapw.abacus.exception.PromotionException
import org.nwapw.abacus.plugin.NumberImplementation
import org.nwapw.abacus.plugin.PluginListener
import org.nwapw.abacus.plugin.PluginManager
@@ -37,21 +38,6 @@ class PromotionManager(val abacus: Abacus) : PluginListener {
return null
}
/**
* If a path between the given implementations has already been computed, uses
* the already calculated path. Otherwise, calls [computePathBetween] to compute a new
* path.
*
* @param from the implementation to start from.
* @param to the implementation to get to.
* @return the resulting promotion path, or null if it is not found
*/
fun getPathBetween(from: NumberImplementation, to: NumberImplementation): PromotionPath? {
return computePaths.computeIfAbsent(from to to, {
computePathBetween(it.first, it.second)
})
}
/**
* Promote all the numbers in the list to the same number implementation, to ensure
* they can be used with each other. Finds the highest priority implementation
@@ -60,22 +46,32 @@ class PromotionManager(val abacus: Abacus) : PluginListener {
* @param numbers the numbers to promote.
* @return the resulting promotion result.
*/
fun promote(vararg numbers: NumberInterface): PromotionResult? {
fun promote(vararg numbers: NumberInterface): PromotionResult {
val pluginManager = abacus.pluginManager
val implementations = numbers.map { pluginManager.interfaceImplementationFor(it.javaClass) }
val highestPriority = implementations.sortedBy { it.priority }.last()
return PromotionResult(items = numbers.map {
if(it.javaClass == highestPriority.implementation) it
else getPathBetween(pluginManager.interfaceImplementationFor(it.javaClass), highestPriority)
?.promote(it) ?: return null
else computePaths[pluginManager.interfaceImplementationFor(it.javaClass) to highestPriority]
?.promote(it) ?: throw PromotionException()
}.toTypedArray(), promotedTo = highestPriority)
}
override fun onLoad(manager: PluginManager?) {
override fun onLoad(manager: PluginManager) {
val implementations = manager.allNumberImplementations.map { manager.numberImplementationFor(it) }
for((index, value) in implementations.withIndex()){
for(i in index until implementations.size){
val other = implementations[i]
val promoteFrom = if(other.priority > value.priority) value else other
val promoteTo = if(other.priority > value.priority) other else value
val path = computePathBetween(promoteFrom, promoteTo)
computePaths.put(promoteFrom to promoteTo, path)
}
}
}
override fun onUnload(manager: PluginManager?) {
override fun onUnload(manager: PluginManager) {
computePaths.clear()
}

View File

@@ -36,15 +36,13 @@ class NumberReducer(val abacus: Abacus, context: EvaluationContext) : Reducer<Nu
is NumberBinaryNode -> {
val left = children[0] as NumberInterface
val right = children[1] as NumberInterface
val promotionResult = promotionManager.promote(left, right) ?:
throw EvaluationException("promotion failed.")
val promotionResult = promotionManager.promote(left, right)
context.numberImplementation = promotionResult.promotedTo
abacus.pluginManager.operatorFor(treeNode.operation).apply(context, *promotionResult.items)
}
is FunctionNode -> {
val promotionResult = promotionManager
.promote(*children.map { it as NumberInterface }.toTypedArray()) ?:
throw EvaluationException("promotion failed.")
.promote(*children.map { it as NumberInterface }.toTypedArray())
context.numberImplementation = promotionResult.promotedTo
abacus.pluginManager.functionFor(treeNode.callTo).apply(context, *promotionResult.items)
}

View File

@@ -361,7 +361,12 @@ public class AbacusController implements PluginListener {
enabledPlugins.add(plugin);
}
PluginManager pluginManager = abacus.getPluginManager();
functionList.addAll(manager.getAllFunctions().stream().map(name -> pluginManager.documentationFor(name, DocumentationType.FUNCTION))
functionList.addAll(manager.getAllFunctions().stream().map(name -> {
Documentation documentationInstance = pluginManager.documentationFor(name, DocumentationType.FUNCTION);
if(documentationInstance == null)
documentationInstance = new Documentation(name, "", "", "", DocumentationType.FUNCTION);
return documentationInstance;
})
.collect(Collectors.toCollection(ArrayList::new)));
functionList.addAll(manager.getAllTreeValueFunctions().stream().map(name -> pluginManager.documentationFor(name, DocumentationType.TREE_VALUE_FUNCTION))
.collect(Collectors.toCollection(ArrayList::new)));