This is an automated email from the ASF dual-hosted git repository. okram pushed a commit to branch tp4 in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/tp4 by this push: new e9b14e6 have repeat().times() working. Created a new Traverser named CORTraverser which has coefficient, object, and repeat. Also support for unparameterized emit(). Getting really close. e9b14e6 is described below commit e9b14e65bb5b5f89732582fe307abdfdcc704d52 Author: Marko A. Rodriguez <okramma...@gmail.com> AuthorDate: Sun Mar 17 09:14:14 2019 -0600 have repeat().times() working. Created a new Traverser named CORTraverser which has coefficient, object, and repeat. Also support for unparameterized emit(). Getting really close. --- .../org/apache/tinkerpop/language/Traversal.java | 13 +++++++ .../apache/tinkerpop/language/TraversalSource.java | 2 ++ .../java/org/apache/tinkerpop/language/__.java | 4 +++ .../tinkerpop/machine/bytecode/Argument.java | 6 ++-- .../tinkerpop/machine/bytecode/BytecodeUtil.java | 7 ++++ .../apache/tinkerpop/machine/bytecode/Symbols.java | 9 ++++- .../tinkerpop/machine/coefficient/Coefficient.java | 4 +-- .../machine/coefficient/LongCoefficient.java | 8 ++--- .../machine/function/filter/HasKeyFilter.java | 2 +- .../machine/function/filter/HasKeyValueFilter.java | 2 +- .../machine/function/filter/IsFilter.java | 2 +- .../{filter/IsFilter.java => map/LoopsMap.java} | 21 ++++------- .../CoefficientVerificationStrategy.java} | 38 ++++++++------------ .../TraverserFactoryStrategy.java} | 31 ++++++---------- .../tinkerpop/machine/traverser/COPTraverser.java | 28 +++++---------- .../{COTraverser.java => CORTraverser.java} | 37 ++++++++----------- .../CORTraverserFactory.java} | 33 ++++++++--------- .../tinkerpop/machine/traverser/COTraverser.java | 36 +++++++++++++++++-- .../machine/traverser/EmptyTraverser.java | 14 ++++++++ .../tinkerpop/machine/traverser/Traverser.java | 23 +++++++++--- .../tinkerpop/machine/traverser/TraverserSet.java | 8 ++--- .../org/apache/tinkerpop/util/StringFactory.java | 5 +++ .../org/apache/tinkerpop/machine/beam/Beam.java | 2 +- .../apache/tinkerpop/machine/beam/RepeatEndFn.java | 16 +++++---- .../tinkerpop/machine/beam/RepeatStartFn.java | 10 +++--- .../apache/tinkerpop/machine/beam/BeamTest.java | 7 +++- .../apache/tinkerpop/machine/pipes/RepeatStep.java | 42 +++++++++++----------- .../apache/tinkerpop/machine/pipes/PipesTest.java | 8 ++++- 28 files changed, 240 insertions(+), 178 deletions(-) diff --git a/java/core/src/main/java/org/apache/tinkerpop/language/Traversal.java b/java/core/src/main/java/org/apache/tinkerpop/language/Traversal.java index 01740c3..ce9b788 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/language/Traversal.java +++ b/java/core/src/main/java/org/apache/tinkerpop/language/Traversal.java @@ -90,6 +90,10 @@ public class Traversal<C, S, E> implements Iterator<E> { return (Traversal) this; } + public Traversal<C, S, E> emit() { + return this.emit(__.constant(true)); + } + public Traversal<C, S, E> emit(final Traversal<C, E, ?> emitTraversal) { final Instruction<C> lastInstruction = this.bytecode.lastInstruction(); if (lastInstruction.op().equals(Symbols.REPEAT)) @@ -164,6 +168,11 @@ public class Traversal<C, S, E> implements Iterator<E> { return (Traversal) this; } + public Traversal<C, S, Integer> loops() { + this.bytecode.addInstruction(this.currentCoefficient, Symbols.LOOPS); + return (Traversal) this; + } + public <R> Traversal<C, S, R> map(final Traversal<C, E, R> mapTraversal) { this.bytecode.addInstruction(this.currentCoefficient, Symbols.MAP, mapTraversal.bytecode); return (Traversal) this; @@ -188,6 +197,10 @@ public class Traversal<C, S, E> implements Iterator<E> { return (Traversal) this; } + public Traversal<C, S, E> times(final int times) { + return this.until(__.<C, E>loops().is(times)); + } + public <R> Traversal<C, S, R> unfold() { this.bytecode.addInstruction(this.currentCoefficient, Symbols.UNFOLD); return (Traversal) this; diff --git a/java/core/src/main/java/org/apache/tinkerpop/language/TraversalSource.java b/java/core/src/main/java/org/apache/tinkerpop/language/TraversalSource.java index 04d558f..2e37fce 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/language/TraversalSource.java +++ b/java/core/src/main/java/org/apache/tinkerpop/language/TraversalSource.java @@ -23,6 +23,7 @@ import org.apache.tinkerpop.machine.bytecode.Symbols; import org.apache.tinkerpop.machine.coefficient.Coefficient; import org.apache.tinkerpop.machine.processor.ProcessorFactory; import org.apache.tinkerpop.machine.strategy.CoefficientStrategy; +import org.apache.tinkerpop.machine.strategy.CoefficientVerificationStrategy; import org.apache.tinkerpop.machine.strategy.Strategy; /** @@ -35,6 +36,7 @@ public class TraversalSource<C> { protected TraversalSource() { this.bytecode = new Bytecode<>(); this.bytecode.addSourceInstruction(Symbols.WITH_STRATEGY, CoefficientStrategy.class); + this.bytecode.addSourceInstruction(Symbols.WITH_STRATEGY, CoefficientVerificationStrategy.class); // TODO: remove when strategies full integrated } public TraversalSource<C> withCoefficient(final Class<? extends Coefficient<C>> coefficient) { diff --git a/java/core/src/main/java/org/apache/tinkerpop/language/__.java b/java/core/src/main/java/org/apache/tinkerpop/language/__.java index baa1671..c80580b 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/language/__.java +++ b/java/core/src/main/java/org/apache/tinkerpop/language/__.java @@ -53,6 +53,10 @@ public class __ { return __.<C, S>start().is(objectTraversal); } + public static <C, S> Traversal<C, S, Integer> loops() { + return __.<C, S>start().loops(); + } + public static <C, S extends Number> Traversal<C, S, S> sum() { return __.<C, S>start().sum(); } diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/bytecode/Argument.java b/java/core/src/main/java/org/apache/tinkerpop/machine/bytecode/Argument.java index ca51b74..bbae38d 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/bytecode/Argument.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/bytecode/Argument.java @@ -18,6 +18,8 @@ */ package org.apache.tinkerpop.machine.bytecode; +import org.apache.tinkerpop.machine.traverser.Traverser; + import java.io.Serializable; /** @@ -38,8 +40,8 @@ public final class Argument<E> implements Serializable { } - public final <C, S> E getArg(final S object) { - return this.isPrimitive ? this.arg : this.getCompilation().mapObject(object).object(); + public final <C, S> E getArg(final Traverser<C, S> traverser) { + return this.isPrimitive ? this.arg : this.<C, S>getCompilation().mapTraverser(traverser).object(); } public static <E> Argument<E> create(final Object arg) { diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/bytecode/BytecodeUtil.java b/java/core/src/main/java/org/apache/tinkerpop/machine/bytecode/BytecodeUtil.java index 581fc9d..4e9bc78 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/bytecode/BytecodeUtil.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/bytecode/BytecodeUtil.java @@ -33,6 +33,7 @@ import org.apache.tinkerpop.machine.function.flatmap.UnfoldFlatMap; import org.apache.tinkerpop.machine.function.initial.InjectInitial; import org.apache.tinkerpop.machine.function.map.ConstantMap; import org.apache.tinkerpop.machine.function.map.IncrMap; +import org.apache.tinkerpop.machine.function.map.LoopsMap; import org.apache.tinkerpop.machine.function.map.MapMap; import org.apache.tinkerpop.machine.function.map.PathMap; import org.apache.tinkerpop.machine.function.reduce.CountReduce; @@ -41,6 +42,7 @@ import org.apache.tinkerpop.machine.function.reduce.SumReduce; import org.apache.tinkerpop.machine.processor.ProcessorFactory; import org.apache.tinkerpop.machine.strategy.Strategy; import org.apache.tinkerpop.machine.traverser.COPTraverserFactory; +import org.apache.tinkerpop.machine.traverser.CORTraverserFactory; import org.apache.tinkerpop.machine.traverser.TraverserFactory; import java.lang.reflect.InvocationTargetException; @@ -122,9 +124,12 @@ public final class BytecodeUtil { } public static <C> Optional<TraverserFactory<C>> getTraverserFactory(final Bytecode<C> bytecode) { + // TODO: make this real for (final Instruction<C> instruction : bytecode.getInstructions()) { if (instruction.op().equals(Symbols.PATH)) return Optional.of(COPTraverserFactory.instance()); + else if (instruction.op().equals(Symbols.REPEAT)) + return Optional.of(CORTraverserFactory.instance()); } return Optional.of(COPTraverserFactory.instance()); } @@ -174,6 +179,8 @@ public final class BytecodeUtil { return new IsFilter<>(coefficient, labels, Argument.create(instruction.args()[0])); case Symbols.INCR: return new IncrMap<>(coefficient, labels); + case Symbols.LOOPS: + return new LoopsMap<>(coefficient, labels); case Symbols.MAP: return new MapMap<>(coefficient, labels, Compilation.compileOne(instruction.args()[0])); case Symbols.PATH: diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/bytecode/Symbols.java b/java/core/src/main/java/org/apache/tinkerpop/machine/bytecode/Symbols.java index 46afecd..952a382 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/bytecode/Symbols.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/bytecode/Symbols.java @@ -23,6 +23,10 @@ package org.apache.tinkerpop.machine.bytecode; */ public final class Symbols { + private Symbols() { + // static instance + } + public static enum Type { BARRIER, INITIAL, MAP, FLATMAP, FILTER, REDUCE, BRANCH } @@ -47,6 +51,7 @@ public final class Symbols { public static final String INCR = "incr"; public static final String INJECT = "inject"; public static final String IS = "is"; + public static final String LOOPS = "loops"; public static final String MAP = "map"; public static final String PATH = "path"; public static final String REPEAT = "repeat"; @@ -54,7 +59,7 @@ public final class Symbols { public static final String UNFOLD = "unfold"; public static final String UNION = "union"; - public Type getOpType(final String op) { + public static Type getOpType(final String op) { switch (op) { case BARRIER: return Type.BARRIER; @@ -82,6 +87,8 @@ public final class Symbols { return Type.INITIAL; case IS: return Type.FILTER; + case LOOPS: + return Type.MAP; case MAP: return Type.MAP; case PATH: diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java b/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java index 6f6c021..31484c7 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java @@ -25,9 +25,9 @@ import java.io.Serializable; */ public interface Coefficient<C> extends Cloneable, Serializable { - public Coefficient<C> sum(final C other); + public Coefficient<C> sum(final Coefficient<C> other); - public Coefficient<C> multiply(final C other); + public Coefficient<C> multiply(final Coefficient<C> other); public Coefficient<C> set(final C other); diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/LongCoefficient.java b/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/LongCoefficient.java index ba69a57..44d41aa 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/LongCoefficient.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/LongCoefficient.java @@ -34,14 +34,14 @@ public class LongCoefficient implements Coefficient<Long> { } @Override - public Coefficient<Long> sum(final Long other) { - this.value = this.value + other; + public Coefficient<Long> sum(final Coefficient<Long> other) { + this.value = this.value + other.value(); return this; } @Override - public Coefficient<Long> multiply(final Long other) { - this.value = this.value * other; + public Coefficient<Long> multiply(final Coefficient<Long> other) { + this.value = this.value * other.value(); return this; } diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyFilter.java b/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyFilter.java index ae8e501..9fbc915 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyFilter.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyFilter.java @@ -43,7 +43,7 @@ public final class HasKeyFilter<C, K, V> extends AbstractFunction<C> implements @Override public boolean test(final Traverser<C, Map<K, V>> traverser) { final Map<K, V> object = traverser.object(); - return object.containsKey(this.key.getArg(object)); + return object.containsKey(this.key.getArg(traverser)); } @Override diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyValueFilter.java b/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyValueFilter.java index 932e567..0ffe190 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyValueFilter.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyValueFilter.java @@ -45,7 +45,7 @@ public final class HasKeyValueFilter<C, K, V> extends AbstractFunction<C> implem @Override public boolean test(final Traverser<C, Map<K, V>> traverser) { final Map<K, V> object = traverser.object(); - return this.value.getArg(object).equals(object.get(this.key.getArg(object))); + return this.value.getArg(traverser).equals(object.get(this.key.getArg(traverser))); } @Override diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/IsFilter.java b/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/IsFilter.java index 6b2be92..c4c8138 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/IsFilter.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/IsFilter.java @@ -41,7 +41,7 @@ public final class IsFilter<C, S> extends AbstractFunction<C> implements FilterF @Override public boolean test(final Traverser<C, S> traverser) { - return traverser.object().equals(this.argument.getArg(traverser.object())); + return traverser.object().equals(this.argument.getArg(traverser)); } @Override diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/IsFilter.java b/java/core/src/main/java/org/apache/tinkerpop/machine/function/map/LoopsMap.java similarity index 60% copy from java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/IsFilter.java copy to java/core/src/main/java/org/apache/tinkerpop/machine/function/map/LoopsMap.java index 6b2be92..ec005cf 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/function/filter/IsFilter.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/function/map/LoopsMap.java @@ -16,36 +16,27 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.tinkerpop.machine.function.filter; +package org.apache.tinkerpop.machine.function.map; -import org.apache.tinkerpop.machine.bytecode.Argument; import org.apache.tinkerpop.machine.coefficient.Coefficient; import org.apache.tinkerpop.machine.function.AbstractFunction; -import org.apache.tinkerpop.machine.function.FilterFunction; +import org.apache.tinkerpop.machine.function.MapFunction; import org.apache.tinkerpop.machine.traverser.Traverser; -import org.apache.tinkerpop.util.StringFactory; import java.util.Set; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public final class IsFilter<C, S> extends AbstractFunction<C> implements FilterFunction<C, S> { +public class LoopsMap<C, S> extends AbstractFunction<C> implements MapFunction<C, S, Integer> { - private Argument<S> argument; - - public IsFilter(final Coefficient<C> coefficient, final Set<String> labels, final Argument<S> argument) { + public LoopsMap(final Coefficient<C> coefficient, final Set<String> labels) { super(coefficient, labels); - this.argument = argument; } @Override - public boolean test(final Traverser<C, S> traverser) { - return traverser.object().equals(this.argument.getArg(traverser.object())); + public Integer apply(final Traverser<C, S> traverser) { + return traverser.loops(); } - @Override - public String toString() { - return StringFactory.makeFunctionString(this, this.argument); - } } diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java b/java/core/src/main/java/org/apache/tinkerpop/machine/strategy/CoefficientVerificationStrategy.java similarity index 54% copy from java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java copy to java/core/src/main/java/org/apache/tinkerpop/machine/strategy/CoefficientVerificationStrategy.java index 6f6c021..b0128ea 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/strategy/CoefficientVerificationStrategy.java @@ -16,32 +16,24 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.tinkerpop.machine.coefficient; +package org.apache.tinkerpop.machine.strategy; -import java.io.Serializable; +import org.apache.tinkerpop.machine.bytecode.Bytecode; +import org.apache.tinkerpop.machine.bytecode.Instruction; +import org.apache.tinkerpop.machine.bytecode.Symbols; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public interface Coefficient<C> extends Cloneable, Serializable { - - public Coefficient<C> sum(final C other); - - public Coefficient<C> multiply(final C other); - - public Coefficient<C> set(final C other); - - public Coefficient<C> unity(); - - public Coefficient<C> zero(); - - public boolean isUnity(); - - public boolean isZero(); - - public C value(); - - public Long count(); - - public Coefficient<C> clone(); +public final class CoefficientVerificationStrategy implements Strategy { + + @Override + public <C> void apply(final Bytecode<C> bytecode) { + for (final Instruction<C> instruction : bytecode.getInstructions()) { + if (Symbols.getOpType(instruction.op()).equals(Symbols.Type.REDUCE)) { + if (!instruction.coefficient().isUnity()) + throw new IllegalStateException("Reduce functions can not have non-unity coefficients: " + instruction); + } + } + } } diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java b/java/core/src/main/java/org/apache/tinkerpop/machine/strategy/TraverserFactoryStrategy.java similarity index 63% copy from java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java copy to java/core/src/main/java/org/apache/tinkerpop/machine/strategy/TraverserFactoryStrategy.java index 6f6c021..9cd0542 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/strategy/TraverserFactoryStrategy.java @@ -16,32 +16,21 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.tinkerpop.machine.coefficient; +package org.apache.tinkerpop.machine.strategy; -import java.io.Serializable; +import org.apache.tinkerpop.machine.bytecode.Bytecode; +import org.apache.tinkerpop.machine.bytecode.BytecodeUtil; +import org.apache.tinkerpop.machine.traverser.TraverserFactory; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public interface Coefficient<C> extends Cloneable, Serializable { +public class TraverserFactoryStrategy implements Strategy { - public Coefficient<C> sum(final C other); + private TraverserFactory traverserFactory; - public Coefficient<C> multiply(final C other); - - public Coefficient<C> set(final C other); - - public Coefficient<C> unity(); - - public Coefficient<C> zero(); - - public boolean isUnity(); - - public boolean isZero(); - - public C value(); - - public Long count(); - - public Coefficient<C> clone(); + @Override + public <C> void apply(final Bytecode<C> bytecode) { + //if(BytecodeUtil.hasSourceInstruction()) + } } diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/COPTraverser.java b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/COPTraverser.java index 4810f24..33e0933 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/COPTraverser.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/COPTraverser.java @@ -25,15 +25,12 @@ import org.apache.tinkerpop.machine.function.ReduceFunction; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public class COPTraverser<C, S> implements Traverser<C, S> { +public class COPTraverser<C, S> extends COTraverser<C, S> { - private Coefficient<C> coefficient; - private S object; private BasicPath path = new BasicPath(); COPTraverser(final Coefficient<C> coefficient, final S object) { - this.coefficient = coefficient; - this.object = object; + super(coefficient, object); } public Coefficient<C> coefficient() { @@ -53,7 +50,7 @@ public class COPTraverser<C, S> implements Traverser<C, S> { final COPTraverser<C, E> clone = new COPTraverser<>( function instanceof ReduceFunction ? function.coefficient().clone().unity() : - function.coefficient().clone().multiply(this.coefficient().value()), newObject); + function.coefficient().clone().multiply(this.coefficient()), newObject); clone.path = function instanceof ReduceFunction ? new BasicPath() : new BasicPath(this.path); clone.path.add(function.labels(), newObject); return clone; @@ -70,21 +67,12 @@ public class COPTraverser<C, S> implements Traverser<C, S> { } @Override - public String toString() { - return this.object.toString(); - } - - @Override public COPTraverser<C, S> clone() { - try { - final COPTraverser<C, S> clone = (COPTraverser<C, S>) super.clone(); - clone.object = this.object; - clone.coefficient = this.coefficient.clone(); - clone.path = new BasicPath(this.path); - return clone; - } catch (final CloneNotSupportedException e) { - throw new RuntimeException(e.getMessage(), e); - } + final COPTraverser<C, S> clone = (COPTraverser<C, S>) super.clone(); + clone.object = this.object; + clone.coefficient = this.coefficient.clone(); + clone.path = new BasicPath(this.path); + return clone; } } diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/COTraverser.java b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/CORTraverser.java similarity index 56% copy from java/core/src/main/java/org/apache/tinkerpop/machine/traverser/COTraverser.java copy to java/core/src/main/java/org/apache/tinkerpop/machine/traverser/CORTraverser.java index 2e56865..fe07165 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/COTraverser.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/CORTraverser.java @@ -24,44 +24,35 @@ import org.apache.tinkerpop.machine.function.CFunction; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public class COTraverser<C, S> implements Traverser<C, S> { +public class CORTraverser<C, S> extends COTraverser<C, S> { - private Coefficient<C> coefficient; - private final S object; + private short loops = 0; - COTraverser(final Coefficient<C> coefficient, final S object) { - this.coefficient = coefficient; - this.object = object; + public CORTraverser(final Coefficient<C> coefficient, final S object) { + super(coefficient, object); } @Override - public Coefficient<C> coefficient() { - return this.coefficient; + public void incrLoops() { + this.loops++; } @Override - public S object() { - return this.object; + public int loops() { + return this.loops; } @Override - public Path path() { - return EmptyPath.instance(); + public void resetLoops() { + this.loops = 0; } @Override public <E> Traverser<C, E> split(final CFunction<C> function, final E object) { - return new COTraverser<>(this.coefficient.clone().multiply(function.coefficient().value()), object); + final CORTraverser<C,E> clone = (CORTraverser<C,E>) this.clone(); + clone.object = object; + return clone; } - @Override - public Traverser<C, S> clone() { - try { - final COTraverser<C, S> clone = (COTraverser<C, S>) super.clone(); - clone.coefficient = this.coefficient.clone(); - return clone; - } catch (final CloneNotSupportedException e) { - throw new RuntimeException(e.getMessage(), e); - } - } + } diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/CORTraverserFactory.java similarity index 59% copy from java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java copy to java/core/src/main/java/org/apache/tinkerpop/machine/traverser/CORTraverserFactory.java index 6f6c021..c53123d 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/coefficient/Coefficient.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/CORTraverserFactory.java @@ -16,32 +16,27 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.tinkerpop.machine.coefficient; +package org.apache.tinkerpop.machine.traverser; -import java.io.Serializable; +import org.apache.tinkerpop.machine.coefficient.Coefficient; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public interface Coefficient<C> extends Cloneable, Serializable { +public class CORTraverserFactory<C> implements TraverserFactory<C> { - public Coefficient<C> sum(final C other); + private static final CORTraverserFactory INSTANCE = new CORTraverserFactory(); - public Coefficient<C> multiply(final C other); + private CORTraverserFactory() { + // static instance + } - public Coefficient<C> set(final C other); + @Override + public <S> Traverser<C, S> create(final Coefficient<C> coefficient, final S object) { + return new CORTraverser<>(coefficient.clone(), object); + } - public Coefficient<C> unity(); - - public Coefficient<C> zero(); - - public boolean isUnity(); - - public boolean isZero(); - - public C value(); - - public Long count(); - - public Coefficient<C> clone(); + public static <C> CORTraverserFactory<C> instance() { + return INSTANCE; + } } diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/COTraverser.java b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/COTraverser.java index 2e56865..9616f29 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/COTraverser.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/COTraverser.java @@ -20,14 +20,15 @@ package org.apache.tinkerpop.machine.traverser; import org.apache.tinkerpop.machine.coefficient.Coefficient; import org.apache.tinkerpop.machine.function.CFunction; +import org.apache.tinkerpop.util.StringFactory; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ public class COTraverser<C, S> implements Traverser<C, S> { - private Coefficient<C> coefficient; - private final S object; + protected Coefficient<C> coefficient; + protected S object; COTraverser(final Coefficient<C> coefficient, final S object) { this.coefficient = coefficient; @@ -50,8 +51,37 @@ public class COTraverser<C, S> implements Traverser<C, S> { } @Override + public void incrLoops() { + } + + @Override + public int loops() { + return 0; + } + + @Override + public void resetLoops() { + + } + + @Override public <E> Traverser<C, E> split(final CFunction<C> function, final E object) { - return new COTraverser<>(this.coefficient.clone().multiply(function.coefficient().value()), object); + return new COTraverser<>(this.coefficient.clone().multiply(function.coefficient()), object); + } + + @Override + public int hashCode() { + return this.object.hashCode(); + } + + @Override + public boolean equals(final Object other) { + return other instanceof COTraverser && this.object.equals(((COTraverser) other).object); + } + + @Override + public String toString() { + return StringFactory.makeTraverserString(this); } @Override diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/EmptyTraverser.java b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/EmptyTraverser.java index 0e6c48c..77a074d 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/EmptyTraverser.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/EmptyTraverser.java @@ -48,6 +48,20 @@ public final class EmptyTraverser<C, S> implements Traverser<C, S> { } @Override + public void incrLoops() { + } + + @Override + public int loops() { + return 0; + } + + @Override + public void resetLoops() { + + } + + @Override public <E> Traverser<C, E> split(CFunction<C> function, E object) { return INSTANCE; } diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/Traverser.java b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/Traverser.java index 40901ae..d0330e8 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/Traverser.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/Traverser.java @@ -24,6 +24,7 @@ import org.apache.tinkerpop.machine.function.FilterFunction; import org.apache.tinkerpop.machine.function.FlatMapFunction; import org.apache.tinkerpop.machine.function.MapFunction; import org.apache.tinkerpop.machine.function.ReduceFunction; +import org.apache.tinkerpop.machine.function.branch.RepeatBranch; import org.apache.tinkerpop.util.IteratorUtils; import java.io.Serializable; @@ -40,10 +41,16 @@ public interface Traverser<C, S> extends Serializable, Cloneable { public Path path(); + public void incrLoops(); + + public int loops(); + + public void resetLoops(); + public default boolean filter(final FilterFunction<C, S> function) { if (function.test(this)) { this.path().addLabels(function.labels()); - this.coefficient().multiply(function.coefficient().value()); + this.coefficient().multiply(function.coefficient()); return true; } else { return false; @@ -58,9 +65,17 @@ public interface Traverser<C, S> extends Serializable, Cloneable { return IteratorUtils.map(function.apply(this), e -> this.split(function, e)); } - /*public default <C,S> Traverser<C,S> repeatLoop(final RepeatBranch<C,S> repeatBranch) { - // set loops - }*/ + public default Traverser<C, S> repeatDone(final RepeatBranch<C, S> repeatBranch) { + final Traverser<C, S> traverser = this.split(repeatBranch, this.object()); + traverser.resetLoops(); + return traverser; + } + + public default Traverser<C, S> repeatLoop(final RepeatBranch<C, S> repeatBranch) { + Traverser<C, S> traverser = this.clone(); + traverser.incrLoops(); + return traverser; + } public default <E> Traverser<C, E> reduce(final ReduceFunction<C, S, E> function, final E reducedValue) { return this.split(function, reducedValue); diff --git a/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/TraverserSet.java b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/TraverserSet.java index e4dbe8a..f4139a3 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/TraverserSet.java +++ b/java/core/src/main/java/org/apache/tinkerpop/machine/traverser/TraverserSet.java @@ -77,7 +77,7 @@ public final class TraverserSet<C, S> extends AbstractSet<Traverser<C, S>> imple this.map.put(traverser, traverser); return true; } else { - existing.coefficient().sum(traverser.coefficient().value()); + existing.coefficient().sum(traverser.coefficient()); return false; } } @@ -132,8 +132,8 @@ public final class TraverserSet<C, S> extends AbstractSet<Traverser<C, S>> imple return this.map.values().toString(); } - /*public void sort(final Comparator<COPTraverser<S>> comparator) { - final List<COPTraverser<C, S>> list = new ArrayList<>(this.map.size()); + /*public void sort(final Comparator<Traverser<S>> comparator) { + final List<Traverser<C, S>> list = new ArrayList<>(this.map.size()); IteratorUtils.removeOnNext(this.map.values().iterator()).forEachRemaining(list::add); Collections.sort(list, comparator); this.map.reset(); @@ -141,7 +141,7 @@ public final class TraverserSet<C, S> extends AbstractSet<Traverser<C, S>> imple } public void shuffle() { - final List<COPTraverser<C, S>> list = new ArrayList<>(this.map.size()); + final List<Traverser<C, S>> list = new ArrayList<>(this.map.size()); IteratorUtils.removeOnNext(this.map.values().iterator()).forEachRemaining(list::add); Collections.shuffle(list); this.map.reset(); diff --git a/java/core/src/main/java/org/apache/tinkerpop/util/StringFactory.java b/java/core/src/main/java/org/apache/tinkerpop/util/StringFactory.java index 76f2f54..e2f2ffa 100644 --- a/java/core/src/main/java/org/apache/tinkerpop/util/StringFactory.java +++ b/java/core/src/main/java/org/apache/tinkerpop/util/StringFactory.java @@ -21,6 +21,7 @@ package org.apache.tinkerpop.util; import org.apache.tinkerpop.machine.bytecode.Instruction; import org.apache.tinkerpop.machine.bytecode.SourceInstruction; import org.apache.tinkerpop.machine.function.CFunction; +import org.apache.tinkerpop.machine.traverser.Traverser; /** * @author Marko A. Rodriguez (http://markorodriguez.com) @@ -80,4 +81,8 @@ public final class StringFactory { name = name + "@" + function.labels(); return name; } + + public static String makeTraverserString(final Traverser<?, ?> traverser) { + return "|" + traverser.coefficient() + "|" + traverser.object(); + } } diff --git a/java/machine/beam/src/main/java/org/apache/tinkerpop/machine/beam/Beam.java b/java/machine/beam/src/main/java/org/apache/tinkerpop/machine/beam/Beam.java index f84da29..5e0dcab 100644 --- a/java/machine/beam/src/main/java/org/apache/tinkerpop/machine/beam/Beam.java +++ b/java/machine/beam/src/main/java/org/apache/tinkerpop/machine/beam/Beam.java @@ -40,7 +40,7 @@ import java.util.List; */ public class Beam<C, S, E> implements Processor<C, S, E> { - public static final int MAX_REPETIONS = 10; // TODO: this needs to be a dynamic configuration + public static final int MAX_REPETIONS = 15; // TODO: this needs to be a dynamic configuration private final Pipeline pipeline; public static List<Traverser> OUTPUT = new ArrayList<>(); // FIX THIS! diff --git a/java/machine/beam/src/main/java/org/apache/tinkerpop/machine/beam/RepeatEndFn.java b/java/machine/beam/src/main/java/org/apache/tinkerpop/machine/beam/RepeatEndFn.java index b053c2b..7aac435 100644 --- a/java/machine/beam/src/main/java/org/apache/tinkerpop/machine/beam/RepeatEndFn.java +++ b/java/machine/beam/src/main/java/org/apache/tinkerpop/machine/beam/RepeatEndFn.java @@ -29,6 +29,7 @@ import org.apache.tinkerpop.machine.traverser.Traverser; */ public class RepeatEndFn<C, S> extends AbstractFn<C, S, S> { + private final RepeatBranch<C, S> repeatBranch; private final int untilLocation; private final int emitLocation; private final Compilation<C, S, ?> untilCompilation; @@ -41,6 +42,7 @@ public class RepeatEndFn<C, S> extends AbstractFn<C, S, S> { final TupleTag<Traverser<C, S>> repeatDone, final TupleTag<Traverser<C, S>> repeatLoop) { super(repeatBranch); + this.repeatBranch = repeatBranch; this.untilLocation = repeatBranch.getUntilLocation(); this.untilCompilation = repeatBranch.getUntil(); this.emitLocation = repeatBranch.getEmitLocation(); @@ -53,20 +55,20 @@ public class RepeatEndFn<C, S> extends AbstractFn<C, S, S> { public void processElement(final @DoFn.Element Traverser<C, S> traverser, final MultiOutputReceiver out) { if (3 == this.untilLocation) { if (this.untilCompilation.filterTraverser(traverser.clone())) { - out.get(this.repeatDone).output(traverser.clone()); + out.get(this.repeatDone).output(traverser.repeatDone(this.repeatBranch)); } else if (4 == this.emitLocation && this.emitCompilation.filterTraverser(traverser.clone())) { - out.get(this.repeatDone).output(traverser.clone()); - out.get(this.repeatLoop).output(traverser.clone()); + out.get(this.repeatDone).output(traverser.repeatDone(this.repeatBranch)); + out.get(this.repeatLoop).output(traverser.repeatLoop(this.repeatBranch)); } else { - out.get(this.repeatLoop).output(traverser.clone()); + out.get(this.repeatLoop).output(traverser.repeatLoop(this.repeatBranch)); } } else if (3 == this.emitLocation) { if (this.emitCompilation.filterTraverser(traverser.clone())) - out.get(this.repeatDone).output(traverser.clone()); + out.get(this.repeatDone).output(traverser.repeatDone(this.repeatBranch)); if (4 == this.untilLocation && this.untilCompilation.filterTraverser(traverser.clone())) - out.get(this.repeatDone).output(traverser.clone()); + out.get(this.repeatDone).output(traverser.repeatDone(this.repeatBranch)); else - out.get(this.repeatLoop).output(traverser.clone()); + out.get(this.repeatLoop).output(traverser.repeatLoop(this.repeatBranch)); } } } diff --git a/java/machine/beam/src/main/java/org/apache/tinkerpop/machine/beam/RepeatStartFn.java b/java/machine/beam/src/main/java/org/apache/tinkerpop/machine/beam/RepeatStartFn.java index 6a9fa23..44f948d 100644 --- a/java/machine/beam/src/main/java/org/apache/tinkerpop/machine/beam/RepeatStartFn.java +++ b/java/machine/beam/src/main/java/org/apache/tinkerpop/machine/beam/RepeatStartFn.java @@ -29,6 +29,7 @@ import org.apache.tinkerpop.machine.traverser.Traverser; */ public class RepeatStartFn<C, S> extends AbstractFn<C, S, S> { + private final RepeatBranch<C, S> repeatBranch; private final int untilLocation; private final int emitLocation; private final Compilation<C, S, ?> untilCompilation; @@ -41,6 +42,7 @@ public class RepeatStartFn<C, S> extends AbstractFn<C, S, S> { final TupleTag<Traverser<C, S>> repeatDone, final TupleTag<Traverser<C, S>> repeatLoop) { super(repeatBranch); + this.repeatBranch = repeatBranch; this.untilLocation = repeatBranch.getUntilLocation(); this.untilCompilation = repeatBranch.getUntil(); this.emitLocation = repeatBranch.getEmitLocation(); @@ -53,18 +55,18 @@ public class RepeatStartFn<C, S> extends AbstractFn<C, S, S> { public void processElement(final @DoFn.Element Traverser<C, S> traverser, final MultiOutputReceiver out) { if (1 == this.untilLocation) { if (this.untilCompilation.filterTraverser(traverser.clone())) { - out.get(this.repeatDone).output(traverser.clone()); + out.get(this.repeatDone).output(traverser.repeatDone(this.repeatBranch)); } else if (2 == this.emitLocation && this.emitCompilation.filterTraverser(traverser.clone())) { - out.get(this.repeatDone).output(traverser.clone()); + out.get(this.repeatDone).output(traverser.repeatDone(this.repeatBranch)); out.get(this.repeatLoop).output(traverser.clone()); } else { out.get(this.repeatLoop).output(traverser.clone()); } } else if (1 == this.emitLocation) { if (this.emitCompilation.filterTraverser(traverser.clone())) - out.get(this.repeatDone).output(traverser.clone()); + out.get(this.repeatDone).output(traverser.repeatDone(this.repeatBranch)); if (2 == this.untilLocation && this.untilCompilation.filterTraverser(traverser.clone())) - out.get(this.repeatDone).output(traverser.clone()); + out.get(this.repeatDone).output(traverser.repeatDone(this.repeatBranch)); else out.get(this.repeatLoop).output(traverser.clone()); } diff --git a/java/machine/beam/src/test/java/org/apache/tinkerpop/machine/beam/BeamTest.java b/java/machine/beam/src/test/java/org/apache/tinkerpop/machine/beam/BeamTest.java index 5ced659..24e5866 100644 --- a/java/machine/beam/src/test/java/org/apache/tinkerpop/machine/beam/BeamTest.java +++ b/java/machine/beam/src/test/java/org/apache/tinkerpop/machine/beam/BeamTest.java @@ -42,7 +42,12 @@ public class BeamTest { .withProcessor(BeamProcessor.class) .withStrategy(IdentityStrategy.class); - Traversal<Long, ?, ?> traversal = g.inject(Arrays.asList(1L, 1L)).<Long>unfold().map(incr()).repeat(incr()).until(__.is(__.<Long, Long, Long>constant(8L).incr().incr())).sum(); + Traversal<Long, ?, ?> traversal = g.inject(Arrays.asList(1L, 1L)).<Long>unfold().map(incr()).c(4L).repeat(incr()).until(__.is(__.<Long, Long, Long>constant(8L).incr().incr())).sum(); + System.out.println(TraversalUtil.getBytecode(traversal)); + System.out.println(traversal); + System.out.println(traversal.toList()); + System.out.println("\n----------\n"); + traversal = g.inject(1L).times(10).repeat(__.incr()).emit(); System.out.println(TraversalUtil.getBytecode(traversal)); System.out.println(traversal); System.out.println(traversal.toList()); diff --git a/java/machine/pipes/src/main/java/org/apache/tinkerpop/machine/pipes/RepeatStep.java b/java/machine/pipes/src/main/java/org/apache/tinkerpop/machine/pipes/RepeatStep.java index 215637c..8340408 100644 --- a/java/machine/pipes/src/main/java/org/apache/tinkerpop/machine/pipes/RepeatStep.java +++ b/java/machine/pipes/src/main/java/org/apache/tinkerpop/machine/pipes/RepeatStep.java @@ -28,6 +28,7 @@ import org.apache.tinkerpop.machine.traverser.TraverserSet; */ final class RepeatStep<C, S> extends AbstractStep<C, S, S> { + private final RepeatBranch<C, S> repeatBranch; private final int untilLocation; private final int emitLocation; private final Compilation<C, S, ?> untilCompilation; @@ -38,15 +39,16 @@ final class RepeatStep<C, S> extends AbstractStep<C, S, S> { private final boolean hasStartPredicates; private final boolean hasEndPredicates; - RepeatStep(final Step<C, ?, S> previousStep, final RepeatBranch<C, S> repeatFunction) { - super(previousStep, repeatFunction); - this.untilCompilation = repeatFunction.getUntil(); - this.emitCompilation = repeatFunction.getEmit(); - this.repeat = repeatFunction.getRepeat(); - this.untilLocation = repeatFunction.getUntilLocation(); - this.emitLocation = repeatFunction.getEmitLocation(); - this.hasStartPredicates = repeatFunction.hasStartPredicates(); - this.hasEndPredicates = repeatFunction.hasEndPredicates(); + RepeatStep(final Step<C, ?, S> previousStep, final RepeatBranch<C, S> repeatBranch) { + super(previousStep, repeatBranch); + this.repeatBranch = repeatBranch; + this.untilCompilation = repeatBranch.getUntil(); + this.emitCompilation = repeatBranch.getEmit(); + this.repeat = repeatBranch.getRepeat(); + this.untilLocation = repeatBranch.getUntilLocation(); + this.emitLocation = repeatBranch.getEmitLocation(); + this.hasStartPredicates = repeatBranch.hasStartPredicates(); + this.hasEndPredicates = repeatBranch.hasEndPredicates(); } @Override @@ -68,15 +70,15 @@ final class RepeatStep<C, S> extends AbstractStep<C, S, S> { if (this.untilCompilation.filterTraverser(traverser.clone())) { this.outputTraversers.add(traverser); } else if (2 == this.emitLocation && this.emitCompilation.filterTraverser(traverser.clone())) { - this.outputTraversers.add(traverser); + this.outputTraversers.add(traverser.repeatDone(this.repeatBranch)); this.repeat.addTraverser(traverser); } else this.repeat.addTraverser(traverser); } else if (1 == this.emitLocation) { if (this.emitCompilation.filterTraverser(traverser.clone())) - this.outputTraversers.add(traverser); + this.outputTraversers.add(traverser.repeatDone(this.repeatBranch)); if (2 == this.untilLocation && this.untilCompilation.filterTraverser(traverser.clone())) - this.outputTraversers.add(traverser); + this.outputTraversers.add(traverser.repeatDone(this.repeatBranch)); else this.repeat.addTraverser(traverser); } @@ -93,22 +95,22 @@ final class RepeatStep<C, S> extends AbstractStep<C, S, S> { if (this.hasEndPredicates) { if (3 == this.untilLocation) { if (this.untilCompilation.filterTraverser(traverser.clone())) { - this.outputTraversers.add(traverser); + this.outputTraversers.add(traverser.repeatDone(this.repeatBranch)); } else if (4 == this.emitLocation && this.emitCompilation.filterTraverser(traverser.clone())) { - this.outputTraversers.add(traverser); - this.inputTraversers.add(traverser); + this.outputTraversers.add(traverser.repeatDone(this.repeatBranch)); + this.inputTraversers.add(traverser.repeatLoop(this.repeatBranch)); } else - this.inputTraversers.add(traverser); + this.inputTraversers.add(traverser.repeatLoop(this.repeatBranch)); } else if (3 == this.emitLocation) { if (this.emitCompilation.filterTraverser(traverser.clone())) - this.outputTraversers.add(traverser); + this.outputTraversers.add(traverser.repeatDone(this.repeatBranch)); if (4 == this.untilLocation && this.untilCompilation.filterTraverser(traverser.clone())) - this.outputTraversers.add(traverser); + this.outputTraversers.add(traverser.repeatDone(this.repeatBranch)); else - this.inputTraversers.add(traverser); + this.inputTraversers.add(traverser.repeatLoop(this.repeatBranch)); } } else { - this.inputTraversers.add(traverser); + this.inputTraversers.add(traverser.repeatLoop(this.repeatBranch)); } } } diff --git a/java/machine/pipes/src/test/java/org/apache/tinkerpop/machine/pipes/PipesTest.java b/java/machine/pipes/src/test/java/org/apache/tinkerpop/machine/pipes/PipesTest.java index 00b3b32..186a69d 100644 --- a/java/machine/pipes/src/test/java/org/apache/tinkerpop/machine/pipes/PipesTest.java +++ b/java/machine/pipes/src/test/java/org/apache/tinkerpop/machine/pipes/PipesTest.java @@ -23,6 +23,7 @@ import org.apache.tinkerpop.language.Traversal; import org.apache.tinkerpop.language.TraversalSource; import org.apache.tinkerpop.language.TraversalUtil; import org.apache.tinkerpop.language.__; +import org.apache.tinkerpop.machine.bytecode.BytecodeUtil; import org.apache.tinkerpop.machine.coefficient.LongCoefficient; import org.apache.tinkerpop.machine.strategy.IdentityStrategy; import org.junit.jupiter.api.Test; @@ -43,7 +44,12 @@ public class PipesTest { .withProcessor(PipesProcessor.class) .withStrategy(IdentityStrategy.class); - Traversal<Long, ?, ?> traversal = g.inject(Arrays.asList(1L, 1L)).<Long>unfold().map(incr()).repeat(incr()).until(__.is(__.<Long, Long, Long>constant(8L).incr().incr())).sum(); + Traversal<Long, ?, ?> traversal = g.inject(Arrays.asList(1L, 1L)).<Long>unfold().map(incr()).c(4L).repeat(incr()).until(__.is(__.<Long, Long, Long>constant(8L).incr().incr())).sum(); + System.out.println(TraversalUtil.getBytecode(traversal)); + System.out.println(traversal); + System.out.println(traversal.toList()); + System.out.println("\n----------\n"); + traversal = g.inject(1L).times(10).repeat(__.incr()).emit(); System.out.println(TraversalUtil.getBytecode(traversal)); System.out.println(traversal); System.out.println(traversal.toList());