summaryrefslogtreecommitdiff
path: root/BJC-Utils2/src
diff options
context:
space:
mode:
Diffstat (limited to 'BJC-Utils2/src')
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/IPair.java26
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/Pair.java21
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java18
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java84
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/experimental/Identity.java82
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/experimental/Lazy.java39
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/experimental/LazyPair.java317
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/experimental/Pair.java63
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java2
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java21
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java202
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java16
12 files changed, 762 insertions, 129 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java
index a20ff36..98f425f 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java
@@ -2,7 +2,6 @@ package bjc.utils.data;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
-import java.util.function.Function;
/**
* An interface representing a pair of values
@@ -14,26 +13,7 @@ import java.util.function.Function;
* @param <R>
* The type stored in the right side of the pair
*/
-public interface IPair<L, R> {
-
- /**
- * Create a new pair by applying the given functions to the left/right.
- * Does not change the internal contents of this pair.
- *
- * @param <L2>
- * The new left type of the pair
- * @param <R2>
- * The new right type of the pair
- *
- * @param leftTransformer
- * The function to apply to the left value.
- * @param rightTransformer
- * The function to apply to the right value.
- * @return A new pair containing the two modified values.
- */
- public <L2, R2> IPair<L2, R2> apply(Function<L, L2> leftTransformer,
- Function<R, R2> rightTransformer);
-
+public interface IPair<L, R> {
/**
* Apply a function to the two internal values that returns a new pair.
*
@@ -47,8 +27,8 @@ public interface IPair<L, R> {
* The function to use as a bind
* @return The new pair
*/
- public <L2, R2> IPair<L2, R2>
- bind(BiFunction<L, R, IPair<L2, R2>> binder);
+ public <L2, R2> IPair<L2, R2> bind(
+ BiFunction<L, R, IPair<L2, R2>> binder);
/**
* Execute an action with the values of this pair. Has no effect on the
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java
index 03f2eed..87727be 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java
@@ -2,7 +2,6 @@ package bjc.utils.data;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
-import java.util.function.Function;
/**
* Holds a pair of values of two different types.
@@ -50,24 +49,6 @@ public class Pair<L, R> implements IPair<L, R> {
/*
* (non-Javadoc)
*
- * @see bjc.utils.data.IPair#apply(java.util.function.Function,
- * java.util.function.Function)
- */
- @Override
- public <L2, R2> IPair<L2, R2> apply(Function<L, L2> leftTransformer,
- Function<R, R2> rightTransformer) {
- if (leftTransformer == null || rightTransformer == null) {
- throw new NullPointerException(
- "Transformers must be non-null");
- }
-
- return new Pair<>(leftTransformer.apply(leftValue),
- rightTransformer.apply(rightValue));
- }
-
- /*
- * (non-Javadoc)
- *
* @see bjc.utils.data.IPair#doWith(java.util.function.BiConsumer)
*/
@Override
@@ -110,7 +91,7 @@ public class Pair<L, R> implements IPair<L, R> {
} else {
rightValueString = "(null)";
}
-
+
return "pair[l=" + leftValueString + ", r=" + rightValueString
+ "]";
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java
index 2767897..7d1d7a0 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java
@@ -15,8 +15,11 @@ import java.util.function.UnaryOperator;
public interface IHolder<ContainedType> {
/**
* Bind a function across the value in this container
- * @param <BoundType> The type of value in this container
- * @param binder The function to bind to the value
+ *
+ * @param <BoundType>
+ * The type of value in this container
+ * @param binder
+ * The function to bind to the value
* @return A holder from binding the value
*/
public <BoundType> IHolder<BoundType> bind(
@@ -82,4 +85,15 @@ public interface IHolder<ContainedType> {
*/
public <UnwrappedType> UnwrappedType unwrap(
Function<ContainedType, UnwrappedType> unwrapper);
+
+ /**
+ * Replace the held value with a new one
+ *
+ * @param newValue
+ * The value to hold instead
+ * @return The holder itself
+ */
+ public default IHolder<ContainedType> replace(ContainedType newValue) {
+ return transform((oldValue) -> newValue);
+ }
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java
new file mode 100644
index 0000000..fb9648e
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java
@@ -0,0 +1,84 @@
+package bjc.utils.data.experimental;
+
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * Represents a pair of values
+ *
+ * @author ben
+ * @param <LeftType>
+ * The type of the left side of the pair
+ * @param <RightType>
+ * The type of the right side of the pair
+ *
+ */
+public interface IPair<LeftType, RightType> {
+ /**
+ * Bind a function to the left value in this pair
+ *
+ * @param <BoundLeft>
+ * The type of the bound value
+ * @param leftBinder
+ * The function to use to bind
+ * @return A pair with the left type bound
+ */
+ public <BoundLeft> IPair<BoundLeft, RightType> bindLeft(
+ Function<LeftType, IPair<BoundLeft, RightType>> leftBinder);
+
+ /**
+ * Bind a function to the right value in this pair
+ *
+ * @param <BoundRight>
+ * The type of the bound value
+ * @param rightBinder
+ * The function to use to bind
+ * @return A pair with the right type bound
+ */
+ public <BoundRight> IPair<LeftType, BoundRight> bindRight(
+ Function<RightType, IPair<LeftType, BoundRight>> rightBinder);
+
+ /**
+ * Bind a function across the values in this pair
+ *
+ * @param <BoundLeft>
+ * The type of the bound left
+ * @param <BoundRight>
+ * The type of the bound right
+ * @param binder
+ * The function to bind with
+ * @return The bound pair
+ */
+ public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind(
+ BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder);
+
+ /**
+ * Merge the two values in this pair into a single value
+ *
+ * @param <MergedType>
+ * The type of the single value
+ * @param merger
+ * The function to use for merging
+ * @return The pair, merged into a single value
+ */
+ public <MergedType> MergedType merge(
+ BiFunction<LeftType, RightType, MergedType> merger);
+
+ /**
+ * Get the value on the left side of the pair
+ *
+ * @return The value on the left side of the pair
+ */
+ public default LeftType getLeft() {
+ return merge((leftValue, rightValue) -> leftValue);
+ }
+
+ /**
+ * Get the value on the right side of the pair
+ *
+ * @return The value on the right side of the pair
+ */
+ public default RightType getRight() {
+ return merge((leftValue, rightValue) -> rightValue);
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Identity.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Identity.java
index 3cf0987..1780f2d 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Identity.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Identity.java
@@ -42,29 +42,32 @@ public class Identity<ContainedType> implements IHolder<ContainedType> {
return binder.apply(heldValue);
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
@Override
- public <MappedType> IHolder<MappedType> map(
- Function<ContainedType, MappedType> mapper) {
- return new Identity<>(mapper.apply(heldValue));
- }
-
- @Override
- public IHolder<ContainedType> transform(
- UnaryOperator<ContainedType> transformer) {
- heldValue = transformer.apply(heldValue);
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ } else if (obj == null) {
+ return false;
+ } else if (getClass() != obj.getClass()) {
+ return false;
+ }
- return this;
- }
+ Identity<?> other = (Identity<?>) obj;
- @Override
- public <UnwrappedType> UnwrappedType unwrap(
- Function<ContainedType, UnwrappedType> unwrapper) {
- return unwrapper.apply(heldValue);
- }
+ if (heldValue == null) {
+ if (other.heldValue != null) {
+ return false;
+ }
+ } else if (!heldValue.equals(other.heldValue)) {
+ return false;
+ }
- @Override
- public String toString() {
- return "holding[v=" + heldValue + "]";
+ return true;
}
/*
@@ -85,31 +88,28 @@ public class Identity<ContainedType> implements IHolder<ContainedType> {
return result;
}
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
@Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- } else if (obj == null) {
- return false;
- } else if (getClass() != obj.getClass()) {
- return false;
- }
+ public <MappedType> IHolder<MappedType> map(
+ Function<ContainedType, MappedType> mapper) {
+ return new Identity<>(mapper.apply(heldValue));
+ }
- Identity<?> other = (Identity<?>) obj;
+ @Override
+ public String toString() {
+ return "holding[v=" + heldValue + "]";
+ }
- if (heldValue == null) {
- if (other.heldValue != null) {
- return false;
- }
- } else if (!heldValue.equals(other.heldValue)) {
- return false;
- }
+ @Override
+ public IHolder<ContainedType> transform(
+ UnaryOperator<ContainedType> transformer) {
+ heldValue = transformer.apply(heldValue);
- return true;
+ return this;
+ }
+
+ @Override
+ public <UnwrappedType> UnwrappedType unwrap(
+ Function<ContainedType, UnwrappedType> unwrapper) {
+ return unwrapper.apply(heldValue);
}
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Lazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Lazy.java
index e919fec..0d6fcef 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Lazy.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Lazy.java
@@ -26,8 +26,7 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> {
private boolean holderBound;
- private IFunctionalList<UnaryOperator<BoundContainedType>> actions =
- new FunctionalList<>();
+ private IFunctionalList<UnaryOperator<BoundContainedType>> actions = new FunctionalList<>();
public BoundLazy(Supplier<IHolder<OldType>> supp,
Function<OldType, IHolder<BoundContainedType>> binder) {
@@ -38,8 +37,7 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> {
@Override
public <BoundType> IHolder<BoundType> bind(
Function<BoundContainedType, IHolder<BoundType>> bindr) {
- IFunctionalList<UnaryOperator<BoundContainedType>> pendingActions =
- new FunctionalList<>();
+ IFunctionalList<UnaryOperator<BoundContainedType>> pendingActions = new FunctionalList<>();
actions.forEach(pendingActions::add);
@@ -62,8 +60,7 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> {
@Override
public <MappedType> IHolder<MappedType> map(
Function<BoundContainedType, MappedType> mapper) {
- IFunctionalList<UnaryOperator<BoundContainedType>> pendingActions =
- new FunctionalList<>();
+ IFunctionalList<UnaryOperator<BoundContainedType>> pendingActions = new FunctionalList<>();
actions.forEach(pendingActions::add);
@@ -101,12 +98,19 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> {
return boundHolder.unwrap(unwrapper);
}
+ @Override
+ public String toString() {
+ if (holderBound) {
+ return boundHolder.toString();
+ }
+
+ return "(unmaterialized)";
+ }
}
private Supplier<ContainedType> valueSupplier;
- private IFunctionalList<UnaryOperator<ContainedType>> actions =
- new FunctionalList<>();
+ private IFunctionalList<UnaryOperator<ContainedType>> actions = new FunctionalList<>();
private boolean valueMaterialized;
@@ -146,8 +150,7 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> {
@Override
public <BoundType> IHolder<BoundType> bind(
Function<ContainedType, IHolder<BoundType>> binder) {
- IFunctionalList<UnaryOperator<ContainedType>> pendingActions =
- new FunctionalList<>();
+ IFunctionalList<UnaryOperator<ContainedType>> pendingActions = new FunctionalList<>();
actions.forEach(pendingActions::add);
@@ -167,8 +170,7 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> {
@Override
public <MappedType> IHolder<MappedType> map(
Function<ContainedType, MappedType> mapper) {
- IFunctionalList<UnaryOperator<ContainedType>> pendingActions =
- new FunctionalList<>();
+ IFunctionalList<UnaryOperator<ContainedType>> pendingActions = new FunctionalList<>();
actions.forEach(pendingActions::add);
@@ -210,4 +212,17 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> {
return unwrapper.apply(heldValue);
}
+
+ @Override
+ public String toString() {
+ if (valueMaterialized) {
+ if (actions.isEmpty()) {
+ return "value[v='" + heldValue + "']";
+ }
+
+ return "value[v='" + heldValue + "'] (has pending transforms)";
+ }
+
+ return "(unmaterialized)";
+ }
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/LazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/LazyPair.java
new file mode 100644
index 0000000..04a4b61
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/LazyPair.java
@@ -0,0 +1,317 @@
+package bjc.utils.data.experimental;
+
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * A lazy implementation of a pair
+ *
+ * @author ben
+ *
+ * @param <LeftType>
+ * The type on the left side of the pair
+ * @param <RightType>
+ * The type on the right side of the pair
+ */
+public class LazyPair<LeftType, RightType>
+ implements IPair<LeftType, RightType> {
+ private static class HalfBoundLazyPair<OldType, NewLeft, NewRight>
+ implements IPair<NewLeft, NewRight> {
+ private Supplier<OldType> oldSupplier;
+
+ private Function<OldType, IPair<NewLeft, NewRight>> binder;
+
+ private IPair<NewLeft, NewRight> boundPair;
+ private boolean pairBound;
+
+ public HalfBoundLazyPair(Supplier<OldType> oldSupp,
+ Function<OldType, IPair<NewLeft, NewRight>> bindr) {
+ oldSupplier = oldSupp;
+ binder = bindr;
+ }
+
+ @Override
+ public <BoundLeft> IPair<BoundLeft, NewRight> bindLeft(
+ Function<NewLeft, IPair<BoundLeft, NewRight>> leftBinder) {
+ Supplier<NewLeft> leftSupp = () -> {
+ IPair<NewLeft, NewRight> newPair = boundPair;
+
+ if (!pairBound) {
+ newPair = binder.apply(oldSupplier.get());
+ }
+
+ return newPair.getLeft();
+ };
+
+ return new HalfBoundLazyPair<>(leftSupp, leftBinder);
+ }
+
+ @Override
+ public <BoundRight> IPair<NewLeft, BoundRight> bindRight(
+ Function<NewRight, IPair<NewLeft, BoundRight>> rightBinder) {
+ Supplier<NewRight> rightSupp = () -> {
+ IPair<NewLeft, NewRight> newPair = boundPair;
+
+ if (!pairBound) {
+ newPair = binder.apply(oldSupplier.get());
+ }
+
+ return newPair.getRight();
+ };
+
+ return new HalfBoundLazyPair<>(rightSupp, rightBinder);
+ }
+
+ @Override
+ public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind(
+ BiFunction<NewLeft, NewRight, IPair<BoundLeft, BoundRight>> bindr) {
+ IHolder<IPair<NewLeft, NewRight>> newPair = new Identity<>(
+ boundPair);
+ IHolder<Boolean> newPairMade = new Identity<>(pairBound);
+
+ Supplier<NewLeft> leftSupp = () -> {
+ if (!newPairMade.getValue()) {
+ newPair.replace(binder.apply(oldSupplier.get()));
+ newPairMade.replace(true);
+ }
+
+ return newPair.unwrap((pair) -> pair.getLeft());
+ };
+
+ Supplier<NewRight> rightSupp = () -> {
+ if (!newPairMade.getValue()) {
+ newPair.replace(binder.apply(oldSupplier.get()));
+ newPairMade.replace(true);
+ }
+
+ return newPair.unwrap((pair) -> pair.getRight());
+ };
+
+ return new BoundLazyPair<>(leftSupp, rightSupp, bindr);
+ }
+
+ @Override
+ public <MergedType> MergedType merge(
+ BiFunction<NewLeft, NewRight, MergedType> merger) {
+ if (!pairBound) {
+ boundPair = binder.apply(oldSupplier.get());
+
+ pairBound = true;
+ }
+
+ return boundPair.merge(merger);
+ }
+ }
+
+ private static class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight>
+ implements IPair<NewLeft, NewRight> {
+ private Supplier<OldLeft> leftSupplier;
+ private Supplier<OldRight> rightSupplier;
+
+ private BiFunction<OldLeft, OldRight, IPair<NewLeft, NewRight>> binder;
+
+ private IPair<NewLeft, NewRight> boundPair;
+
+ private boolean pairBound;
+
+ public BoundLazyPair(Supplier<OldLeft> leftSupp,
+ Supplier<OldRight> rightSupp,
+ BiFunction<OldLeft, OldRight, IPair<NewLeft, NewRight>> bindr) {
+ leftSupplier = leftSupp;
+ rightSupplier = rightSupp;
+ binder = bindr;
+ }
+
+ @Override
+ public <BoundLeft> IPair<BoundLeft, NewRight> bindLeft(
+ Function<NewLeft, IPair<BoundLeft, NewRight>> leftBinder) {
+ Supplier<NewLeft> leftSupp = () -> {
+ IPair<NewLeft, NewRight> newPair = boundPair;
+
+ if (!pairBound) {
+ newPair = binder.apply(leftSupplier.get(),
+ rightSupplier.get());
+ }
+
+ return newPair.getLeft();
+ };
+
+ return new HalfBoundLazyPair<>(leftSupp, leftBinder);
+ }
+
+ @Override
+ public <BoundRight> IPair<NewLeft, BoundRight> bindRight(
+ Function<NewRight, IPair<NewLeft, BoundRight>> rightBinder) {
+ Supplier<NewRight> rightSupp = () -> {
+ IPair<NewLeft, NewRight> newPair = boundPair;
+
+ if (!pairBound) {
+ newPair = binder.apply(leftSupplier.get(),
+ rightSupplier.get());
+ }
+
+ return newPair.getRight();
+ };
+
+ return new HalfBoundLazyPair<>(rightSupp, rightBinder);
+ }
+
+ @Override
+ public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind(
+ BiFunction<NewLeft, NewRight, IPair<BoundLeft, BoundRight>> bindr) {
+ IHolder<IPair<NewLeft, NewRight>> newPair = new Identity<>(
+ boundPair);
+ IHolder<Boolean> newPairMade = new Identity<>(pairBound);
+
+ return new BoundLazyPair<>(() -> {
+ if (!newPairMade.getValue()) {
+ newPair.replace(binder.apply(leftSupplier.get(),
+ rightSupplier.get()));
+
+ newPairMade.replace(false);
+ }
+
+ return newPair.unwrap((pair) -> pair.getLeft());
+ }, () -> {
+ if (!newPairMade.getValue()) {
+ newPair.replace(binder.apply(leftSupplier.get(),
+ rightSupplier.get()));
+
+ newPairMade.replace(false);
+ }
+
+ return newPair.unwrap((pair) -> pair.getRight());
+ }, bindr);
+ }
+
+ @Override
+ public <MergedType> MergedType merge(
+ BiFunction<NewLeft, NewRight, MergedType> merger) {
+ if (!pairBound) {
+ boundPair = binder.apply(leftSupplier.get(),
+ rightSupplier.get());
+
+ pairBound = true;
+ }
+
+ return boundPair.merge(merger);
+ }
+ }
+
+ private LeftType leftValue;
+ private RightType rightValue;
+
+ private Supplier<LeftType> leftSupplier;
+ private Supplier<RightType> rightSupplier;
+
+ private boolean leftMaterialized;
+ private boolean rightMaterialized;
+
+ /**
+ * Create a new lazy pair, using the set value s
+ *
+ * @param leftVal
+ * The value for the left side of the pair
+ * @param rightVal
+ * The value for the right side of the pair
+ */
+ public LazyPair(LeftType leftVal, RightType rightVal) {
+ leftValue = leftVal;
+ rightValue = rightVal;
+
+ leftMaterialized = true;
+ rightMaterialized = true;
+ }
+
+ /**
+ * Create a new lazy pair from the given value sources
+ *
+ * @param leftSupp
+ * The source for a value on the left side of the pair
+ * @param rightSupp
+ * The source for a value on the right side of the pair
+ */
+ public LazyPair(Supplier<LeftType> leftSupp,
+ Supplier<RightType> rightSupp) {
+ leftSupplier = leftSupp;
+ rightSupplier = rightSupp;
+
+ leftMaterialized = false;
+ rightMaterialized = false;
+ }
+
+ @Override
+ public <BoundLeft> IPair<BoundLeft, RightType> bindLeft(
+ Function<LeftType, IPair<BoundLeft, RightType>> leftBinder) {
+ Supplier<LeftType> leftSupp = () -> {
+ if (leftMaterialized) {
+ return leftValue;
+ }
+
+ return leftSupplier.get();
+ };
+
+ return new HalfBoundLazyPair<>(leftSupp, leftBinder);
+ }
+
+ @Override
+ public <BoundRight> IPair<LeftType, BoundRight> bindRight(
+ Function<RightType, IPair<LeftType, BoundRight>> rightBinder) {
+ Supplier<RightType> rightSupp = () -> {
+ if (rightMaterialized) {
+ return rightValue;
+ }
+
+ return rightSupplier.get();
+ };
+
+ return new HalfBoundLazyPair<>(rightSupp, rightBinder);
+ }
+
+ @Override
+ public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind(
+ BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder) {
+ return new BoundLazyPair<>(leftSupplier, rightSupplier, binder);
+ }
+
+ @Override
+ public <MergedType> MergedType merge(
+ BiFunction<LeftType, RightType, MergedType> merger) {
+ if (!leftMaterialized) {
+ leftValue = leftSupplier.get();
+
+ leftMaterialized = true;
+ }
+
+ if (!rightMaterialized) {
+ rightValue = rightSupplier.get();
+
+ rightMaterialized = true;
+ }
+
+ return merger.apply(leftValue, rightValue);
+ }
+
+ @Override
+ public LeftType getLeft() {
+ if (!leftMaterialized) {
+ leftValue = leftSupplier.get();
+
+ leftMaterialized = true;
+ }
+
+ return leftValue;
+ }
+
+ @Override
+ public RightType getRight() {
+ if (!rightMaterialized) {
+ rightValue = rightSupplier.get();
+
+ rightMaterialized = true;
+ }
+
+ return rightValue;
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Pair.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Pair.java
new file mode 100644
index 0000000..87378d7
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Pair.java
@@ -0,0 +1,63 @@
+package bjc.utils.data.experimental;
+
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * A pair of values, with nothing special about them.
+ *
+ * @author ben
+ *
+ * @param <LeftType>
+ * The type of the left value
+ * @param <RightType>
+ * The type of the right value
+ */
+public class Pair<LeftType, RightType>
+ implements IPair<LeftType, RightType> {
+ private LeftType leftValue;
+ private RightType rightValue;
+
+ /**
+ * Create a new pair with both sides set to null
+ */
+ public Pair() {
+ }
+
+ /**
+ * Create a new pair with both sides set to the specified values
+ *
+ * @param left
+ * The value of the left side
+ * @param right
+ * The value of the right side
+ */
+ public Pair(LeftType left, RightType right) {
+ leftValue = left;
+ rightValue = right;
+ }
+
+ @Override
+ public <BoundLeft> IPair<BoundLeft, RightType> bindLeft(
+ Function<LeftType, IPair<BoundLeft, RightType>> leftBinder) {
+ return leftBinder.apply(leftValue);
+ }
+
+ @Override
+ public <BoundRight> IPair<LeftType, BoundRight> bindRight(
+ Function<RightType, IPair<LeftType, BoundRight>> rightBinder) {
+ return rightBinder.apply(rightValue);
+ }
+
+ @Override
+ public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind(
+ BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder) {
+ return binder.apply(leftValue, rightValue);
+ }
+
+ @Override
+ public <MergedType> MergedType merge(
+ BiFunction<LeftType, RightType, MergedType> merger) {
+ return merger.apply(leftValue, rightValue);
+ }
+} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java
index 85b7493..141d558 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java
@@ -171,7 +171,7 @@ public class LazyHolder<T> implements IHolder<T>, ILazy {
* The value held in the holder
*/
public LazyHolder(T value) {
- heldValue = value;
+ heldSource = () -> value;
}
@Override
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java
index 70f5478..dcaeeba 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java
@@ -2,7 +2,6 @@ package bjc.utils.data.lazy;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
-import java.util.function.Function;
import java.util.function.Supplier;
import bjc.utils.data.IHolder;
@@ -88,26 +87,6 @@ public class LazyPair<L, R> implements IPair<L, R>, ILazy {
/*
* (non-Javadoc)
*
- * @see bjc.utils.data.IPair#apply(java.util.function.Function,
- * java.util.function.Function)
- */
- @Override
- public <L2, R2> IPair<L2, R2> apply(Function<L, L2> leftTransform,
- Function<R, R2> rightTransform) {
- if (leftTransform == null || rightTransform == null) {
- throw new NullPointerException("Transforms must be non-null");
- }
-
- IHolder<IPair<L2, R2>> newPair = delegatePair
- .map((currentPair) -> currentPair.apply(leftTransform,
- rightTransform));
-
- return new LazyPair<>(newPair, materialized, true);
- }
-
- /*
- * (non-Javadoc)
- *
* @see bjc.utils.data.IPair#doWith(java.util.function.BiConsumer)
*/
@Override
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java
new file mode 100644
index 0000000..4bd3832
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java
@@ -0,0 +1,202 @@
+package bjc.utils.data.lazy;
+
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Supplier;
+
+import bjc.utils.data.GenHolder;
+import bjc.utils.data.IPair;
+import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IFunctionalList;
+
+/**
+ * New implementation of lazy pair not delegating to {@link LazyHolder}
+ *
+ * @author ben
+ * @param <L>
+ * The type on the left side of the pair
+ * @param <R>
+ * The type on the right side of the pair
+ *
+ */
+public class NewLazyPair<L, R> implements IPair<L, R>, ILazy {
+ private static class BoundLazyPair<OldL, OldR, NewL, NewR>
+ implements IPair<NewL, NewR> {
+ private Supplier<OldL> oldLeftSupplier;
+ private Supplier<OldR> oldRightSupplier;
+
+ private BiFunction<OldL, OldR, IPair<NewL, NewR>> newPairSupplier;
+
+ private IPair<NewL, NewR> newPair;
+
+ private boolean newPairMaterialized;
+
+ public BoundLazyPair(Supplier<OldL> leftSup,
+ Supplier<OldR> rightSup,
+ BiFunction<OldL, OldR, IPair<NewL, NewR>> binder) {
+ oldLeftSupplier = leftSup;
+ oldRightSupplier = rightSup;
+
+ newPairSupplier = binder;
+ }
+
+ @Override
+ public <L2, R2> IPair<L2, R2> bind(
+ BiFunction<NewL, NewR, IPair<L2, R2>> binder) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void doWith(BiConsumer<NewL, NewR> action) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public <E> E merge(BiFunction<NewL, NewR, E> merger) {
+ if (!newPairMaterialized) {
+ newPair = newPairSupplier.apply(oldLeftSupplier.get(),
+ oldRightSupplier.get());
+ }
+
+ return newPair.merge(merger);
+ }
+ }
+
+ private L leftValue;
+ private R rightValue;
+
+ private Supplier<R> rightValueSupplier;
+ private Supplier<L> leftValueSupplier;
+
+ private boolean rightMaterialized;
+ private boolean leftMaterialized;
+
+ private IFunctionalList<BiConsumer<L, R>> actions;
+
+ /**
+ * Create a new lazy pair
+ *
+ * @param leftVal
+ * The left value in the pair
+ * @param rightVal
+ * The right value in the pair
+ */
+ public NewLazyPair(L leftVal, R rightVal) {
+ leftValueSupplier = () -> leftVal;
+ rightValueSupplier = () -> rightVal;
+ }
+
+ /**
+ * Create a new lazy pair
+ *
+ * @param leftSupplier
+ * The supplier for the left value in the pair
+ * @param rightSupplier
+ * The supplier for the right value in the pair
+ */
+ public NewLazyPair(Supplier<L> leftSupplier,
+ Supplier<R> rightSupplier) {
+ leftValueSupplier = leftSupplier;
+ rightValueSupplier = rightSupplier;
+ }
+
+ @Override
+ public void applyPendingActions() {
+ if (!isMaterialized()) {
+ throw new UnsupportedOperationException(
+ "Can only apply actions to materialized values");
+ }
+
+ actions.forEach((action) -> {
+ action.accept(leftValue, rightValue);
+ });
+
+ actions = new FunctionalList<>();
+ }
+
+ private void applyPossiblyPendingActions(GenHolder<Boolean> hasActions,
+ IFunctionalList<BiConsumer<L, R>> pendingActions) {
+ if (hasActions.unwrap((val) -> val) == true) {
+ pendingActions.forEach((action) -> {
+ action.accept(leftValue, rightValue);
+ });
+
+ hasActions.transform((val) -> false);
+ }
+ }
+
+ @Override
+ public <L2, R2> IPair<L2, R2> bind(
+ BiFunction<L, R, IPair<L2, R2>> binder) {
+ GenHolder<Boolean> hasActions = new GenHolder<>(true);
+ IFunctionalList<BiConsumer<L, R>> pendingActions = new FunctionalList<>();
+
+ actions.forEach(pendingActions::add);
+
+ return new BoundLazyPair<>(() -> {
+ applyPossiblyPendingActions(hasActions, pendingActions);
+
+ return leftValue;
+ }, () -> {
+ applyPossiblyPendingActions(hasActions, pendingActions);
+
+ return rightValue;
+ }, binder);
+ }
+
+ @Override
+ public void doWith(BiConsumer<L, R> action) {
+ actions.add(action);
+ }
+
+ @Override
+ public boolean hasPendingActions() {
+ return !actions.isEmpty();
+ }
+
+ @Override
+ public boolean isMaterialized() {
+ if (leftValueSupplier == null) {
+ if (rightValueSupplier == null) {
+ return true;
+ }
+
+ return rightMaterialized;
+ }
+
+ if (rightValueSupplier == null) {
+ return leftMaterialized;
+ }
+
+ return leftMaterialized && rightMaterialized;
+ }
+
+ @Override
+ public void materialize() {
+ if (isMaterialized()) {
+ throw new UnsupportedOperationException(
+ "Cannot materialize lazy object twice");
+ }
+
+ if (leftValueSupplier != null) {
+ leftValue = leftValueSupplier.get();
+ }
+
+ if (rightValueSupplier != null) {
+ rightValue = rightValueSupplier.get();
+ }
+ }
+
+ @Override
+ public <E> E merge(BiFunction<L, R, E> merger) {
+ if (!isMaterialized()) {
+ materialize();
+ }
+
+ applyPendingActions();
+
+ return merger.apply(leftValue, rightValue);
+ }
+} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
index 68ec70e..3252351 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
@@ -7,6 +7,7 @@ import java.util.function.Function;
import java.util.function.Predicate;
import bjc.utils.data.GenHolder;
+import bjc.utils.data.IHolder;
import bjc.utils.data.IPair;
import bjc.utils.data.Pair;
import bjc.utils.funcdata.IFunctionalList;
@@ -45,8 +46,7 @@ public class TreeConstructor {
if (queuedASTs.size() < 2) {
throw new IllegalStateException(
"Attempted to parse binary operator without enough operands.\n"
- + "Problem operator is "
- + element
+ + "Problem operator is " + element
+ "\nPossible operand is: \n\t"
+ queuedASTs.peek());
}
@@ -63,13 +63,13 @@ public class TreeConstructor {
}
}
- private GenHolder<IPair<Deque<AST<T>>, AST<T>>> initialState;
+ private IHolder<IPair<Deque<AST<T>>, AST<T>>> initialState;
private Predicate<T> operatorPredicate;
private Predicate<T> isSpecialOperator;
private Function<Deque<AST<T>>, AST<T>> handleSpecialOperator;
public TokenTransformer(
- GenHolder<IPair<Deque<AST<T>>, AST<T>>> initialState,
+ IHolder<IPair<Deque<AST<T>>, AST<T>>> initialState,
Predicate<T> operatorPredicate,
Predicate<T> isSpecialOperator,
Function<Deque<AST<T>>, AST<T>> handleSpecialOperator) {
@@ -93,10 +93,8 @@ public class TreeConstructor {
});
initialState.transform((pair) -> {
- return pair.apply((Deque<AST<T>> queue) -> {
- return queue;
- }, (AST<T> currentAST) -> {
- return newAST;
+ return pair.bind((queue, currentAST) -> {
+ return new Pair<>(queue, newAST);
});
});
}
@@ -160,7 +158,7 @@ public class TreeConstructor {
"Special operator determiner must not be null");
}
- GenHolder<IPair<Deque<AST<T>>, AST<T>>> initialState = new GenHolder<>(
+ IHolder<IPair<Deque<AST<T>>, AST<T>>> initialState = new GenHolder<>(
new Pair<>(new LinkedList<>(), null));
tokens.forEach(