Reduce creation of Map objects in Pattern matching

This commit is contained in:
Riccardo Azzolini 2019-08-10 20:51:29 +02:00
parent a76511ea19
commit e297d3592f
49 changed files with 280 additions and 332 deletions

View File

@ -88,43 +88,47 @@ public interface Function {
ObjectArrayList<Block> toBlock(MathContext context) throws Error;
/**
* Accepts a <code>Function.Visitor</code> by calling the correct overload of <code>visit</code>.
* Accepts a {@code Function.Visitor<Argument, Result>} by calling the correct overload of <code>visit</code>.
*
* @param visitor The visitor to be accepted.
* @param <T> The return type of the <code>visit</code> method.
* @param visitor The visitor to be accepted.
* @param argument An additional argument to be passed to <code>visit</code>.
* @param <Argument> The type of an additional argument to be passed to the <code>visit</code> method.
* @param <Result> The return type of the <code>visit</code> method.
* @return The value returned by <code>visit</code>.
*/
<T> T accept(Visitor<T> visitor);
<Argument, Result> Result accept(Visitor<Argument, Result> visitor, Argument argument);
/**
* Executes a different overload of a method for each <code>Function</code> implementation.
*
* @param <T> The return type of all <code>visit</code> method overloads.
* @param <Argument> The type of an additional argument which can be passed to all <code>visit</code> method overloads.
* If the argument is not required, this type parameter should be set to {@link Void}.
* @param <Result> The return type of all <code>visit</code> method overloads.
*/
interface Visitor<T> {
T visit(ArcCosine arcCosine);
T visit(ArcSine arcSine);
T visit(ArcTangent arcTangent);
T visit(Cosine cosine);
T visit(Division division);
T visit(Equation equation);
T visit(EquationsSystem equationsSystem);
T visit(EquationsSystemPart equationsSystemPart);
T visit(Expression expression);
T visit(Joke joke);
T visit(Logarithm logarithm);
T visit(Multiplication multiplication);
T visit(Negative negative);
T visit(Number number);
T visit(Power power);
T visit(Root root);
T visit(RootSquare rootSquare);
T visit(Sine sine);
T visit(Subtraction subtraction);
T visit(SumSubtraction sumSubtraction);
T visit(Sum sum);
T visit(Tangent tangent);
T visit(Undefined undefined);
T visit(Variable variable);
interface Visitor<Argument, Result> {
Result visit(ArcCosine arcCosine, Argument argument);
Result visit(ArcSine arcSine, Argument argument);
Result visit(ArcTangent arcTangent, Argument argument);
Result visit(Cosine cosine, Argument argument);
Result visit(Division division, Argument argument);
Result visit(Equation equation, Argument argument);
Result visit(EquationsSystem equationsSystem, Argument argument);
Result visit(EquationsSystemPart equationsSystemPart, Argument argument);
Result visit(Expression expression, Argument argument);
Result visit(Joke joke, Argument argument);
Result visit(Logarithm logarithm, Argument argument);
Result visit(Multiplication multiplication, Argument argument);
Result visit(Negative negative, Argument argument);
Result visit(Number number, Argument argument);
Result visit(Power power, Argument argument);
Result visit(Root root, Argument argument);
Result visit(RootSquare rootSquare, Argument argument);
Result visit(Sine sine, Argument argument);
Result visit(Subtraction subtraction, Argument argument);
Result visit(SumSubtraction sumSubtraction, Argument argument);
Result visit(Sum sum, Argument argument);
Result visit(Tangent tangent, Argument argument);
Result visit(Undefined undefined, Argument argument);
Result visit(Variable variable, Argument argument);
}
}

View File

@ -61,7 +61,7 @@ public class Division extends FunctionOperator {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -583,8 +583,8 @@ public class Expression extends FunctionSingle {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
@Override

View File

@ -62,8 +62,7 @@ public class Joke implements Function {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -56,8 +56,7 @@ public class Logarithm extends FunctionOperator {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -85,8 +85,8 @@ public class Multiplication extends FunctionOperator {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
public boolean isNegative() {

View File

@ -51,7 +51,7 @@ public class Negative extends FunctionSingle {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -274,8 +274,8 @@ public class Number implements Function {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
@Override

View File

@ -52,7 +52,7 @@ public class Power extends FunctionOperator {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -40,8 +40,7 @@ public class Root extends FunctionOperator {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -49,8 +49,7 @@ public class RootSquare extends FunctionOperator {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -41,8 +41,7 @@ public class Subtraction extends FunctionOperator {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -45,7 +45,7 @@ public class Sum extends FunctionOperator {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -41,8 +41,7 @@ public class SumSubtraction extends FunctionOperator {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -59,8 +59,8 @@ public class Undefined implements Function {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
@Override

View File

@ -133,7 +133,7 @@ public class Variable implements Function {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -76,8 +76,7 @@ public class Equation extends FunctionOperator {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -64,8 +64,7 @@ public class EquationsSystem extends FunctionDynamic {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -36,8 +36,7 @@ public class EquationsSystemPart extends FunctionSingle {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -44,8 +44,8 @@ public class ArcCosine extends FunctionSingle {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -44,8 +44,7 @@ public class ArcSine extends FunctionSingle {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -44,8 +44,7 @@ public class ArcTangent extends FunctionSingle {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -44,8 +44,7 @@ public class Cosine extends FunctionSingle {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -52,8 +52,7 @@ public class Sine extends FunctionSingle {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -43,8 +43,7 @@ public class Tangent extends FunctionSingle {
}
@Override
public <T> T accept(final Function.Visitor<T> visitor) {
return visitor.visit(this);
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
}

View File

@ -4,6 +4,7 @@ import it.cavallium.warppi.math.Function;
import it.cavallium.warppi.math.MathContext;
import it.cavallium.warppi.math.rules.dsl.patterns.SubFunctionPattern;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@ -19,7 +20,26 @@ public interface Pattern {
* @return The captured sub-functions, or an empty <code>Optional</code> if
* the pattern doesn't match.
*/
Optional<Map<String, Function>> match(Function function);
default Optional<Map<String, Function>> match(Function function) {
Map<String, Function> subFunctions = new HashMap<>();
return match(function, subFunctions) ? Optional.of(subFunctions) : Optional.empty();
}
/**
* Tries to match this pattern against a function and capture sub-functions.
* <p>
* This overload is provided to allow for a more efficient implementation of matching, by mutating the given
* <code>Map</code> instead of creating and merging multiple ones.
* For all other purposes, use of the {@link #match(Function)} overload is recommended instead.
* <p>
* When the pattern matches, all captured sub-functions are added to the map (if not present already).
* If, instead, the pattern doesn't match, the contents of the map are undefined.
*
* @param function The function to test the pattern against.
* @param subFunctions The map used to capture sub-functions.
* @return <code>true</code> if the pattern matches, or <code>false</code> otherwise.
*/
boolean match(Function function, Map<String, Function> subFunctions);
/**
* Creates a new function by filling in sub-functions within this pattern.

View File

@ -1,7 +1,5 @@
package it.cavallium.warppi.math.rules.dsl;
import it.cavallium.warppi.math.Function;
import it.cavallium.warppi.math.FunctionOperator;
import it.cavallium.warppi.math.rules.dsl.patterns.SubFunctionPattern;
import java.util.*;
@ -13,64 +11,6 @@ import java.util.stream.Collectors;
public class PatternUtils {
private PatternUtils() {}
/**
* Gathers captured sub-functions from two matches, checking for equality
* of ones with the same name.
*
* @param match1 Sub-functions from one match.
* @param match2 Sub-functions from the other match.
* @return A <code>Map</code> containing all sub-functions, or an empty
* <code>Optional</code> if the same name is used to refer to
* non-equal sub-functions in the two matches.
*/
public static Optional<Map<String, Function>> mergeMatches(
final Map<String, Function> match1,
final Map<String, Function> match2
) {
if (!checkSubFunctionEquality(match1, match2)) {
return Optional.empty();
}
final Map<String, Function> merged = new HashMap<>();
merged.putAll(match1);
merged.putAll(match2);
return Optional.of(merged);
}
private static boolean checkSubFunctionEquality(
final Map<String, Function> match1,
final Map<String, Function> match2
) {
for (final Map.Entry<String, Function> leftSubFunction : match1.entrySet()) {
final String key = leftSubFunction.getKey();
if (match2.containsKey(key)
&& !match2.get(key).equals(leftSubFunction.getValue())) {
return false;
}
}
return true;
}
/**
* Tries to match the given patterns against the two parameters of a <code>FunctionOperator</code>.
*
* @param functionOperator The <code>FunctionOperator</code> to be matched.
* @param pattern1 The <code>Pattern</code> used to match <code>functionOperator.parameter1</code>.
* @param pattern2 The <code>Pattern</code> used to match <code>functionOperator.parameter2</code>.
* @return The combined result of the two matches.
* @see #mergeMatches(Map, Map)
*/
public static Optional<Map<String, Function>> matchFunctionOperatorParameters(
final FunctionOperator functionOperator,
final Pattern pattern1,
final Pattern pattern2
) {
return pattern1.match(functionOperator.getParameter1())
.flatMap(match1 -> pattern2.match(functionOperator.getParameter2())
.flatMap(match2 -> mergeMatches(match1, match2))
);
}
/**
* Gathers all sub-function patterns from multiple patterns.
*

View File

@ -9,134 +9,133 @@ import it.cavallium.warppi.math.functions.equations.EquationsSystemPart;
import it.cavallium.warppi.math.functions.trigonometry.*;
import java.util.Map;
import java.util.Optional;
/**
* A <code>Pattern</code> which implements <code>match</code> as a visitor.
*/
public abstract class VisitorPattern implements Pattern, Function.Visitor<Optional<Map<String, Function>>> {
public abstract class VisitorPattern implements Pattern, Function.Visitor<Map<String, Function>, Boolean> {
@Override
public Optional<Map<String, Function>> match(final Function function) {
return function.accept(this);
public boolean match(Function function, Map<String, Function> subFunctions) {
return function.accept(this, subFunctions);
}
@Override
public Optional<Map<String, Function>> visit(final ArcCosine arcCosine) {
return Optional.empty();
public Boolean visit(final ArcCosine arcCosine, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final ArcSine arcSine) {
return Optional.empty();
public Boolean visit(final ArcSine arcSine, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final ArcTangent arcTangent) {
return Optional.empty();
public Boolean visit(final ArcTangent arcTangent, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Cosine cosine) {
return Optional.empty();
public Boolean visit(final Cosine cosine, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Division division) {
return Optional.empty();
public Boolean visit(final Division division, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Equation equation) {
return Optional.empty();
public Boolean visit(final Equation equation, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final EquationsSystem equationsSystem) {
return Optional.empty();
public Boolean visit(final EquationsSystem equationsSystem, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final EquationsSystemPart equationsSystemPart) {
return Optional.empty();
public Boolean visit(final EquationsSystemPart equationsSystemPart, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Expression expression) {
return Optional.empty();
public Boolean visit(final Expression expression, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Joke joke) {
return Optional.empty();
public Boolean visit(final Joke joke, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Logarithm logarithm) {
return Optional.empty();
public Boolean visit(final Logarithm logarithm, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Multiplication multiplication) {
return Optional.empty();
public Boolean visit(final Multiplication multiplication, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Negative negative) {
return Optional.empty();
public Boolean visit(final Negative negative, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Number number) {
return Optional.empty();
public Boolean visit(final Number number, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Power power) {
return Optional.empty();
public Boolean visit(final Power power, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Root root) {
return Optional.empty();
public Boolean visit(final Root root, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final RootSquare rootSquare) {
return Optional.empty();
public Boolean visit(final RootSquare rootSquare, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Sine sine) {
return Optional.empty();
public Boolean visit(final Sine sine, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Subtraction subtraction) {
return Optional.empty();
public Boolean visit(final Subtraction subtraction, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final SumSubtraction sumSubtraction) {
return Optional.empty();
public Boolean visit(final SumSubtraction sumSubtraction, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Sum sum) {
return Optional.empty();
public Boolean visit(final Sum sum, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Tangent tangent) {
return Optional.empty();
public Boolean visit(final Tangent tangent, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Undefined undefined) {
return Optional.empty();
public Boolean visit(final Undefined undefined, final Map<String, Function> subFunctions) {
return false;
}
@Override
public Optional<Map<String, Function>> visit(final Variable variable) {
return Optional.empty();
public Boolean visit(final Variable variable, final Map<String, Function> subFunctions) {
return false;
}
}

View File

@ -8,7 +8,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -22,15 +21,15 @@ public class ArcCosinePattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final ArcCosine arcCosine) {
return argument.match(arcCosine.getParameter());
public Boolean visit(final ArcCosine arcCosine, final Map<String, Function> subFunctions) {
return argument.match(arcCosine.getParameter(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new ArcCosine(
mathContext,
argument.replace(mathContext, subFunctions)
mathContext,
argument.replace(mathContext, subFunctions)
);
}

View File

@ -8,7 +8,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -22,15 +21,15 @@ public class ArcSinePattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final ArcSine arcSine) {
return argument.match(arcSine.getParameter());
public Boolean visit(final ArcSine arcSine, final Map<String, Function> subFunctions) {
return argument.match(arcSine.getParameter(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new ArcSine(
mathContext,
argument.replace(mathContext, subFunctions)
mathContext,
argument.replace(mathContext, subFunctions)
);
}

View File

@ -8,7 +8,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -22,15 +21,15 @@ public class ArcTangentPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final ArcTangent arcTangent) {
return argument.match(arcTangent.getParameter());
public Boolean visit(final ArcTangent arcTangent, final Map<String, Function> subFunctions) {
return argument.match(arcTangent.getParameter(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new ArcTangent(
mathContext,
argument.replace(mathContext, subFunctions)
mathContext,
argument.replace(mathContext, subFunctions)
);
}

View File

@ -5,7 +5,10 @@ import it.cavallium.warppi.math.MathContext;
import it.cavallium.warppi.math.functions.Variable;
import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.*;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* Matches and generates a specific symbolic constant.
@ -18,13 +21,9 @@ public class ConstantPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Variable variable) {
if (variable.getType().equals(Variable.V_TYPE.CONSTANT)
&& variable.getChar() == symbol) {
return Optional.of(Collections.emptyMap());
} else {
return Optional.empty();
}
public Boolean visit(final Variable variable, final Map<String, Function> subFunctions) {
return variable.getType().equals(Variable.V_TYPE.CONSTANT)
&& variable.getChar() == symbol;
}
@Override

View File

@ -8,7 +8,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -22,15 +21,15 @@ public class CosinePattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Cosine cosine) {
return argument.match(cosine.getParameter());
public Boolean visit(final Cosine cosine, final Map<String, Function> subFunctions) {
return argument.match(cosine.getParameter(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new Cosine(
mathContext,
argument.replace(mathContext, subFunctions)
mathContext,
argument.replace(mathContext, subFunctions)
);
}

View File

@ -9,7 +9,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -25,16 +24,17 @@ public class DivisionPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Division division) {
return PatternUtils.matchFunctionOperatorParameters(division, dividend, divisor);
public Boolean visit(final Division division, final Map<String, Function> subFunctions) {
return dividend.match(division.getParameter1(), subFunctions)
&& divisor.match(division.getParameter2(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new Division(
mathContext,
dividend.replace(mathContext, subFunctions),
divisor.replace(mathContext, subFunctions)
mathContext,
dividend.replace(mathContext, subFunctions),
divisor.replace(mathContext, subFunctions)
);
}

View File

@ -9,7 +9,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -25,16 +24,17 @@ public class EquationPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Equation equation) {
return PatternUtils.matchFunctionOperatorParameters(equation, left, right);
public Boolean visit(final Equation equation, final Map<String, Function> subFunctions) {
return left.match(equation.getParameter1(), subFunctions)
&& right.match(equation.getParameter2(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new Equation(
mathContext,
left.replace(mathContext, subFunctions),
right.replace(mathContext, subFunctions)
mathContext,
left.replace(mathContext, subFunctions),
right.replace(mathContext, subFunctions)
);
}

View File

@ -7,7 +7,9 @@ import it.cavallium.warppi.math.rules.dsl.Pattern;
import it.cavallium.warppi.math.rules.dsl.PatternUtils;
import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.*;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
/**
* Matches and generates a system of equations of multiple other patterns.
@ -20,28 +22,27 @@ public class EquationsSystemPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final EquationsSystem equationsSystem) {
public Boolean visit(final EquationsSystem equationsSystem, final Map<String, Function> subFunctions) {
if (patterns.length != equationsSystem.getParametersLength()) {
return Optional.empty();
return false;
}
Optional<Map<String, Function>> subFunctions = Optional.of(Collections.emptyMap());
for (int i = 0; i < patterns.length && subFunctions.isPresent(); i++) {
for (int i = 0; i < patterns.length; i++) {
final Pattern curPattern = patterns[i];
final Function curFunction = equationsSystem.getParameter(i);
subFunctions = subFunctions
.flatMap(prevMatch -> curPattern.match(curFunction)
.flatMap(curMatch -> PatternUtils.mergeMatches(prevMatch, curMatch))
);
if (!curPattern.match(curFunction, subFunctions)) {
return false;
}
}
return subFunctions;
return true;
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
final Function[] functions = Arrays.stream(patterns)
.map(pattern -> pattern.replace(mathContext, subFunctions))
.toArray(Function[]::new);
.map(pattern -> pattern.replace(mathContext, subFunctions))
.toArray(Function[]::new);
return new EquationsSystem(mathContext, functions);
}

View File

@ -9,7 +9,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -25,16 +24,17 @@ public class LogarithmPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Logarithm logarithm) {
return PatternUtils.matchFunctionOperatorParameters(logarithm, base, argument);
public Boolean visit(final Logarithm logarithm, final Map<String, Function> subFunctions) {
return base.match(logarithm.getParameter1(), subFunctions)
&& argument.match(logarithm.getParameter2(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new Logarithm(
mathContext,
base.replace(mathContext, subFunctions),
argument.replace(mathContext, subFunctions)
mathContext,
base.replace(mathContext, subFunctions),
argument.replace(mathContext, subFunctions)
);
}

View File

@ -9,7 +9,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -25,16 +24,17 @@ public class MultiplicationPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Multiplication multiplication) {
return PatternUtils.matchFunctionOperatorParameters(multiplication, left, right);
public Boolean visit(final Multiplication multiplication, final Map<String, Function> subFunctions) {
return left.match(multiplication.getParameter1(), subFunctions)
&& right.match(multiplication.getParameter2(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new Multiplication(
mathContext,
left.replace(mathContext, subFunctions),
right.replace(mathContext, subFunctions)
mathContext,
left.replace(mathContext, subFunctions),
right.replace(mathContext, subFunctions)
);
}

View File

@ -10,7 +10,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -24,18 +23,18 @@ public class NegativePattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Negative negative) {
return inner.match(negative.getParameter());
public Boolean visit(final Negative negative, final Map<String, Function> subFunctions) {
return inner.match(negative.getParameter(), subFunctions);
}
@Override
public Optional<Map<String, Function>> visit(final Number number) {
public Boolean visit(final Number number, final Map<String, Function> subFunctions) {
final BigDecimal value = number.getTerm();
if (value.signum() < 0) {
return inner.match(new Number(number.getMathContext(), value.abs()));
} else {
return Optional.empty();
if (value.signum() >= 0) {
return false;
}
final Number absoluteValue = new Number(number.getMathContext(), value.abs());
return inner.match(absoluteValue, subFunctions);
}
@Override
@ -46,8 +45,8 @@ public class NegativePattern extends VisitorPattern {
return ((Number) newInner).multiply(new Number(mathContext, -1));
} else {
return new Negative(
mathContext,
inner.replace(mathContext, subFunctions)
mathContext,
inner.replace(mathContext, subFunctions)
);
}
}

View File

@ -6,7 +6,10 @@ import it.cavallium.warppi.math.functions.Number;
import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.math.BigDecimal;
import java.util.*;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* Matches and generates a specific number.
@ -19,12 +22,8 @@ public class NumberPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Number number) {
if (number.getTerm().compareTo(value) == 0) {
return Optional.of(Collections.emptyMap());
} else {
return Optional.empty();
}
public Boolean visit(final Number number, final Map<String, Function> subFunctions) {
return number.getTerm().compareTo(value) == 0;
}
@Override

View File

@ -9,7 +9,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -25,16 +24,17 @@ public class PowerPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Power power) {
return PatternUtils.matchFunctionOperatorParameters(power, base, exponent);
public Boolean visit(final Power power, final Map<String, Function> subFunctions) {
return base.match(power.getParameter1(), subFunctions)
&& exponent.match(power.getParameter2(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new Power(
mathContext,
base.replace(mathContext, subFunctions),
exponent.replace(mathContext, subFunctions)
mathContext,
base.replace(mathContext, subFunctions),
exponent.replace(mathContext, subFunctions)
);
}

View File

@ -12,7 +12,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -30,13 +29,15 @@ public class RootPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Root root) {
return PatternUtils.matchFunctionOperatorParameters(root, degree, radicand);
public Boolean visit(final Root root, final Map<String, Function> subFunctions) {
return degree.match(root.getParameter1(), subFunctions)
&& radicand.match(root.getParameter2(), subFunctions);
}
@Override
public Optional<Map<String, Function>> visit(RootSquare rootSquare) {
return PatternUtils.matchFunctionOperatorParameters(rootSquare, degree, radicand);
public Boolean visit(final RootSquare rootSquare, final Map<String, Function> subFunctions) {
return degree.match(rootSquare.getParameter1(), subFunctions)
&& radicand.match(rootSquare.getParameter2(), subFunctions);
}
@Override
@ -45,7 +46,7 @@ public class RootPattern extends VisitorPattern {
final Function newRadicand = radicand.replace(mathContext, subFunctions);
if (newDegree instanceof Number
&& ((Number) newDegree).getTerm().compareTo(new BigDecimal(2)) == 0) {
&& ((Number) newDegree).getTerm().compareTo(new BigDecimal(2)) == 0) {
return new RootSquare(mathContext, newRadicand);
} else {
return new Root(mathContext, newDegree, newRadicand);

View File

@ -8,7 +8,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -22,15 +21,15 @@ public class SinePattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Sine sine) {
return argument.match(sine.getParameter());
public Boolean visit(final Sine sine, final Map<String, Function> subFunctions) {
return argument.match(sine.getParameter(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new Sine(
mathContext,
argument.replace(mathContext, subFunctions)
mathContext,
argument.replace(mathContext, subFunctions)
);
}

View File

@ -4,7 +4,10 @@ import it.cavallium.warppi.math.Function;
import it.cavallium.warppi.math.MathContext;
import it.cavallium.warppi.math.rules.dsl.Pattern;
import java.util.*;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* Matches and generates any function as a named sub-function.
@ -17,8 +20,9 @@ public class SubFunctionPattern implements Pattern {
}
@Override
public Optional<Map<String, Function>> match(final Function function) {
return Optional.of(Collections.singletonMap(name, function));
public boolean match(final Function function, final Map<String, Function> subFunctions) {
final Function existingSubFunction = subFunctions.putIfAbsent(name, function);
return existingSubFunction == null || existingSubFunction.equals(function);
}
@Override

View File

@ -9,7 +9,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -25,16 +24,17 @@ public class SubtractionPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Subtraction subtraction) {
return PatternUtils.matchFunctionOperatorParameters(subtraction, left, right);
public Boolean visit(final Subtraction subtraction, final Map<String, Function> subFunctions) {
return left.match(subtraction.getParameter1(), subFunctions)
&& right.match(subtraction.getParameter2(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new Subtraction(
mathContext,
left.replace(mathContext, subFunctions),
right.replace(mathContext, subFunctions)
mathContext,
left.replace(mathContext, subFunctions),
right.replace(mathContext, subFunctions)
);
}

View File

@ -9,7 +9,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -25,16 +24,17 @@ public class SumPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Sum sum) {
return PatternUtils.matchFunctionOperatorParameters(sum, left, right);
public Boolean visit(final Sum sum, final Map<String, Function> subFunctions) {
return left.match(sum.getParameter1(), subFunctions)
&& right.match(sum.getParameter2(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new Sum(
mathContext,
left.replace(mathContext, subFunctions),
right.replace(mathContext, subFunctions)
mathContext,
left.replace(mathContext, subFunctions),
right.replace(mathContext, subFunctions)
);
}

View File

@ -9,7 +9,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -25,16 +24,17 @@ public class SumSubtractionPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final SumSubtraction sumSubtraction) {
return PatternUtils.matchFunctionOperatorParameters(sumSubtraction, left, right);
public Boolean visit(final SumSubtraction sumSubtraction, final Map<String, Function> subFunctions) {
return left.match(sumSubtraction.getParameter1(), subFunctions)
&& right.match(sumSubtraction.getParameter2(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new SumSubtraction(
mathContext,
left.replace(mathContext, subFunctions),
right.replace(mathContext, subFunctions)
mathContext,
left.replace(mathContext, subFunctions),
right.replace(mathContext, subFunctions)
);
}

View File

@ -8,7 +8,6 @@ import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
@ -22,15 +21,15 @@ public class TangentPattern extends VisitorPattern {
}
@Override
public Optional<Map<String, Function>> visit(final Tangent tangent) {
return argument.match(tangent.getParameter());
public Boolean visit(final Tangent tangent, final Map<String, Function> subFunctions) {
return argument.match(tangent.getParameter(), subFunctions);
}
@Override
public Function replace(final MathContext mathContext, final Map<String, Function> subFunctions) {
return new Tangent(
mathContext,
argument.replace(mathContext, subFunctions)
mathContext,
argument.replace(mathContext, subFunctions)
);
}

View File

@ -5,15 +5,17 @@ import it.cavallium.warppi.math.MathContext;
import it.cavallium.warppi.math.functions.Undefined;
import it.cavallium.warppi.math.rules.dsl.VisitorPattern;
import java.util.*;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
/**
* Matches and generates <code>Undefined</code>.
*/
public class UndefinedPattern extends VisitorPattern {
@Override
public Optional<Map<String, Function>> visit(Undefined undefined) {
return Optional.of(Collections.emptyMap());
public Boolean visit(final Undefined undefined, final Map<String, Function> subFunctions) {
return true;
}
@Override