From 9c77fa8aeb10420a9997e63c11377327cd93ce57 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 18:23:44 -0700 Subject: [PATCH 1/3] Add a DomainException that avoids using null in functions. --- .../nwapw/abacus/number/DomainException.java | 24 +++++++++++++++++++ .../abacus/function/applicable/Applicable.kt | 7 +++--- .../function/applicable/ReducerApplicable.kt | 7 +++--- .../org/nwapw/abacus/fx/AbacusController.java | 2 ++ 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 core/src/main/java/org/nwapw/abacus/number/DomainException.java diff --git a/core/src/main/java/org/nwapw/abacus/number/DomainException.java b/core/src/main/java/org/nwapw/abacus/number/DomainException.java new file mode 100644 index 0000000..51a1769 --- /dev/null +++ b/core/src/main/java/org/nwapw/abacus/number/DomainException.java @@ -0,0 +1,24 @@ +package org.nwapw.abacus.number; + +/** + * Exception thrown if the function parameters do not match + * requirements. + */ +public class DomainException extends RuntimeException { + + /** + * Creates a new DomainException. + * @param reason the reason for which the exception is thrown. + */ + public DomainException(String reason) { + super(reason); + } + + /** + * Creates a new DomainException with a default message. + */ + public DomainException(){ + this("Domain Error"); + } + +} diff --git a/core/src/main/kotlin/org/nwapw/abacus/function/applicable/Applicable.kt b/core/src/main/kotlin/org/nwapw/abacus/function/applicable/Applicable.kt index 69f0afc..dce1129 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/function/applicable/Applicable.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/function/applicable/Applicable.kt @@ -1,5 +1,6 @@ package org.nwapw.abacus.function.applicable +import org.nwapw.abacus.number.DomainException import org.nwapw.abacus.plugin.NumberImplementation /** @@ -25,7 +26,7 @@ interface Applicable { * @param params the parameters to apply to. * @return the result of the application. */ - fun applyInternal(implementation: NumberImplementation, params: Array): O? + fun applyInternal(implementation: NumberImplementation, params: Array): O /** * If the parameters can be used with this applicable, returns @@ -34,8 +35,8 @@ interface Applicable { * @param params the parameters to apply to. * @return the result of the operation, or null if parameters do not match. */ - fun apply(implementation: NumberImplementation, vararg params: T): O? { - if (!matchesParams(implementation, params)) return null + fun apply(implementation: NumberImplementation, vararg params: T): O { + if (!matchesParams(implementation, params)) throw DomainException() return applyInternal(implementation, params) } diff --git a/core/src/main/kotlin/org/nwapw/abacus/function/applicable/ReducerApplicable.kt b/core/src/main/kotlin/org/nwapw/abacus/function/applicable/ReducerApplicable.kt index bdb3276..9a80edc 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/function/applicable/ReducerApplicable.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/function/applicable/ReducerApplicable.kt @@ -1,5 +1,6 @@ package org.nwapw.abacus.function.applicable +import org.nwapw.abacus.number.DomainException import org.nwapw.abacus.plugin.NumberImplementation import org.nwapw.abacus.tree.Reducer @@ -27,7 +28,7 @@ interface ReducerApplicable { * @param params the arguments to apply to. * @return the result of the application. */ - fun applyWithReducerInternal(implementation: NumberImplementation, reducer: Reducer, params: Array): O? + fun applyWithReducerInternal(implementation: NumberImplementation, reducer: Reducer, params: Array): O /** * Applies this applicable to the given arguments, and reducer, @@ -36,8 +37,8 @@ interface ReducerApplicable { * @param params the arguments to apply to. * @return the result of the application, or null if the arguments are incompatible. */ - fun applyWithReducer(implementation: NumberImplementation, reducer: Reducer, vararg params: T): O? { - if (!matchesParams(implementation, params)) return null + fun applyWithReducer(implementation: NumberImplementation, reducer: Reducer, vararg params: T): O { + if (!matchesParams(implementation, params)) throw DomainException() return applyWithReducerInternal(implementation, reducer, params) } diff --git a/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java b/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java index 4f62247..45cdf76 100644 --- a/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java +++ b/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java @@ -152,6 +152,8 @@ public class AbacusController implements PluginListener { return resultingString; } catch (ComputationInterruptedException exception) { return ERR_STOP; + } catch (DomainException exception) { + return exception.getMessage(); } catch (RuntimeException exception) { exception.printStackTrace(); return ERR_EXCEPTION; From 61616a428aca5ed14d3fa3564f43262e1562ae21 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 19:34:17 -0700 Subject: [PATCH 2/3] Fix tests that expected null from functions. --- .../org/nwapw/abacus/tests/CalculationTests.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java b/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java index b210226..3d3269e 100755 --- a/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java +++ b/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java @@ -5,6 +5,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.nwapw.abacus.Abacus; import org.nwapw.abacus.config.Configuration; +import org.nwapw.abacus.number.DomainException; import org.nwapw.abacus.number.NumberInterface; import org.nwapw.abacus.plugin.StandardPlugin; import org.nwapw.abacus.tree.TreeNode; @@ -28,11 +29,14 @@ public class CalculationTests { Assert.assertTrue(result.toString().startsWith(output)); } - private void testEvalError(String input, String parseOutput) { + private void testDomainException(String input, String parseOutput) { TreeNode parsedTree = abacus.parseString(input); Assert.assertNotNull(parsedTree); Assert.assertEquals(parsedTree.toString(), parseOutput); - Assert.assertNull(abacus.evaluateTree(parsedTree)); + try { + abacus.evaluateTree(parsedTree); + Assert.fail("Function did not throw DomainException."); + } catch (DomainException e){ } } @Test @@ -73,7 +77,7 @@ public class CalculationTests { @Test public void testLn() { - testEvalError("ln(-1)", "ln((1)`)"); + testDomainException("ln(-1)", "ln((1)`)"); testOutput("ln2", "ln(2)", "0.6931471805599453094172321214581765680755"); } @@ -100,8 +104,8 @@ public class CalculationTests { testOutput("2^-1", "(2^(1)`)", "0.5"); testOutput("2^50", "(2^50)", "112589990684262"); testOutput("7^(-sqrt2*17)", "(7^((sqrt(2)*17))`)", "4.81354609155297814551845300063563"); - testEvalError("0^0", "(0^0)"); - testEvalError("(-13)^.9999", "((13)`^.9999)"); + testDomainException("0^0", "(0^0)"); + testDomainException("(-13)^.9999", "((13)`^.9999)"); } } From 178f59ef7b8ccad288b3fc7c1fecfecb4eab2253 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 23:06:45 -0700 Subject: [PATCH 3/3] Move the exception to the correct package. --- .../org/nwapw/abacus/{number => function}/DomainException.java | 2 +- .../kotlin/org/nwapw/abacus/function/applicable/Applicable.kt | 2 +- .../org/nwapw/abacus/function/applicable/ReducerApplicable.kt | 2 +- core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java | 2 +- fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java | 1 + 5 files changed, 5 insertions(+), 4 deletions(-) rename core/src/main/java/org/nwapw/abacus/{number => function}/DomainException.java (93%) diff --git a/core/src/main/java/org/nwapw/abacus/number/DomainException.java b/core/src/main/java/org/nwapw/abacus/function/DomainException.java similarity index 93% rename from core/src/main/java/org/nwapw/abacus/number/DomainException.java rename to core/src/main/java/org/nwapw/abacus/function/DomainException.java index 51a1769..a7a449c 100644 --- a/core/src/main/java/org/nwapw/abacus/number/DomainException.java +++ b/core/src/main/java/org/nwapw/abacus/function/DomainException.java @@ -1,4 +1,4 @@ -package org.nwapw.abacus.number; +package org.nwapw.abacus.function; /** * Exception thrown if the function parameters do not match diff --git a/core/src/main/kotlin/org/nwapw/abacus/function/applicable/Applicable.kt b/core/src/main/kotlin/org/nwapw/abacus/function/applicable/Applicable.kt index dce1129..ed8bb91 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/function/applicable/Applicable.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/function/applicable/Applicable.kt @@ -1,6 +1,6 @@ package org.nwapw.abacus.function.applicable -import org.nwapw.abacus.number.DomainException +import org.nwapw.abacus.function.DomainException import org.nwapw.abacus.plugin.NumberImplementation /** diff --git a/core/src/main/kotlin/org/nwapw/abacus/function/applicable/ReducerApplicable.kt b/core/src/main/kotlin/org/nwapw/abacus/function/applicable/ReducerApplicable.kt index 9a80edc..54340a4 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/function/applicable/ReducerApplicable.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/function/applicable/ReducerApplicable.kt @@ -1,6 +1,6 @@ package org.nwapw.abacus.function.applicable -import org.nwapw.abacus.number.DomainException +import org.nwapw.abacus.function.DomainException import org.nwapw.abacus.plugin.NumberImplementation import org.nwapw.abacus.tree.Reducer diff --git a/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java b/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java index 3d3269e..39cf091 100755 --- a/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java +++ b/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java @@ -5,7 +5,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.nwapw.abacus.Abacus; import org.nwapw.abacus.config.Configuration; -import org.nwapw.abacus.number.DomainException; +import org.nwapw.abacus.function.DomainException; import org.nwapw.abacus.number.NumberInterface; import org.nwapw.abacus.plugin.StandardPlugin; import org.nwapw.abacus.tree.TreeNode; diff --git a/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java b/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java index 45cdf76..8b05f3f 100644 --- a/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java +++ b/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java @@ -14,6 +14,7 @@ import org.nwapw.abacus.Abacus; import org.nwapw.abacus.config.Configuration; import org.nwapw.abacus.function.Documentation; import org.nwapw.abacus.function.DocumentationType; +import org.nwapw.abacus.function.DomainException; import org.nwapw.abacus.number.*; import org.nwapw.abacus.plugin.ClassFinder; import org.nwapw.abacus.plugin.PluginListener;