You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2018/07/17 17:14:19 UTC

[01/11] tinkerpop git commit: TINKERPOP-967 Support nested-repeat() structures

Repository: tinkerpop
Updated Branches:
  refs/heads/master ea6884a38 -> a546d2600


TINKERPOP-967 Support nested-repeat() structures

Implementation of a loop counter stack and set of nested loop traversers as described in TINKERPOP-967.

Added NESTED_LOOP (NL) supporting traversers alongside each SINGLE_LOOP supporting traverser and
included these in the DefaultTraverserGeneratorFactory.

Added new Traversers and dependencies into GryoVersion.

Added extra functionality tests into RepeatTest and DefaultTraverserGeneratorFactoryTest to check that
the nested loops work as exected and that the Traversers are correctly selected respectively.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/320c1436
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/320c1436
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/320c1436

Branch: refs/heads/master
Commit: 320c14365f9a77a6942d8c5a6e997560634cf855
Parents: d3b6a34
Author: GCHQResearcher1337 <39...@users.noreply.github.com>
Authored: Mon Jun 4 10:35:29 2018 +0100
Committer: GCHQResearcher1337 <39...@users.noreply.github.com>
Committed: Mon Jun 11 10:14:22 2018 +0100

----------------------------------------------------------------------
 .../B_LP_NL_O_P_S_SE_SL_Traverser.java          | 104 ++++++++++++++++++
 .../B_LP_NL_O_P_S_SE_SL_TraverserGenerator.java |  58 ++++++++++
 .../traverser/B_LP_NL_O_S_SE_SL_Traverser.java  | 104 ++++++++++++++++++
 .../B_LP_NL_O_S_SE_SL_TraverserGenerator.java   |  58 ++++++++++
 .../traverser/B_NL_O_S_SE_SL_Traverser.java     | 104 ++++++++++++++++++
 .../B_NL_O_S_SE_SL_TraverserGenerator.java      |  56 ++++++++++
 .../LP_NL_O_OB_P_S_SE_SL_Traverser.java         | 105 +++++++++++++++++++
 ...LP_NL_O_OB_P_S_SE_SL_TraverserGenerator.java |  60 +++++++++++
 .../traverser/LP_NL_O_OB_S_SE_SL_Traverser.java | 105 +++++++++++++++++++
 .../LP_NL_O_OB_S_SE_SL_TraverserGenerator.java  |  59 +++++++++++
 .../traverser/NL_O_OB_S_SE_SL_Traverser.java    | 105 +++++++++++++++++++
 .../NL_O_OB_S_SE_SL_TraverserGenerator.java     |  58 ++++++++++
 .../util/DefaultTraverserGeneratorFactory.java  |  26 ++++-
 .../traverser/util/LabelledCounter.java         |  72 +++++++++++++
 .../gremlin/structure/io/gryo/GryoVersion.java  |  35 ++++++-
 .../DefaultTraverserGeneratorFactoryTest.java   |  10 ++
 gremlin-test/features/branch/Repeat.feature     |  48 +++++++++
 .../traversal/step/branch/RepeatTest.java       |  91 ++++++++++++++++
 18 files changed, 1254 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
new file mode 100644
index 0000000..3412965
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
+
+import java.util.Stack;
+
+public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser<T> {
+
+    protected Stack<LabelledCounter> nestedLoops;
+
+    protected B_LP_NL_O_P_S_SE_SL_Traverser() {
+    }
+
+    public B_LP_NL_O_P_S_SE_SL_Traverser(final T t, final Step<T, ?> step, final long initialBulk) {
+        super(t, step, initialBulk);
+        this.nestedLoops = new Stack<>();
+    }
+
+    /////////////////
+
+    @Override
+    public int loops() {
+        return this.nestedLoops.size() > 0 ? this.nestedLoops.peek().count() : 0;
+    }
+
+    @Override
+    public void incrLoops(final String stepLabel) {
+        // If we encounter a new stack label then grow the stack otherwise increment the loop count
+        if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
+            this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
+        }
+        else {
+            this.nestedLoops.peek().increment();
+        }
+    }
+
+    @Override
+    public void resetLoops() {
+        // Protect against reset without increment during RepeatStep setup
+        if (this.nestedLoops.size() > 0) {
+            this.nestedLoops.pop();
+        }
+    }
+
+    /////////////////
+
+    @Override
+    public <R> Admin<R> split(final R r, final Step<T, R> step) {
+        final B_LP_NL_O_P_S_SE_SL_Traverser<R> clone = (B_LP_NL_O_P_S_SE_SL_Traverser<R>) super.split(r, step);
+        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        return clone;
+    }
+
+    @Override
+    public Admin<T> split() {
+        final B_LP_NL_O_P_S_SE_SL_Traverser<T> clone = (B_LP_NL_O_P_S_SE_SL_Traverser<T>) super.split();
+        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        return clone;
+    }
+
+    @Override
+    public void merge(final Admin<?> other) {
+        super.merge(other);
+    }
+
+    /////////////////
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof B_LP_NL_O_P_S_SE_SL_Traverser)) return false;
+        if (!super.equals(o)) return false;
+
+        B_LP_NL_O_P_S_SE_SL_Traverser<?> that = (B_LP_NL_O_P_S_SE_SL_Traverser<?>) o;
+
+        return nestedLoops.equals(that.nestedLoops);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + nestedLoops.hashCode();
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_TraverserGenerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_TraverserGenerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_TraverserGenerator.java
new file mode 100644
index 0000000..a593932
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_TraverserGenerator.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+public final class B_LP_NL_O_P_S_SE_SL_TraverserGenerator implements TraverserGenerator {
+
+    private static final B_LP_NL_O_P_S_SE_SL_TraverserGenerator INSTANCE = new B_LP_NL_O_P_S_SE_SL_TraverserGenerator();
+
+    private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(
+            TraverserRequirement.BULK,
+            TraverserRequirement.LABELED_PATH,
+            TraverserRequirement.NESTED_LOOP,
+            TraverserRequirement.OBJECT,
+            TraverserRequirement.PATH,
+            TraverserRequirement.SACK,
+            TraverserRequirement.SIDE_EFFECTS,
+            TraverserRequirement.SINGLE_LOOP);
+
+    private B_LP_NL_O_P_S_SE_SL_TraverserGenerator() {
+    }
+
+    @Override
+    public <S> Traverser.Admin<S> generate(final S start, final Step<S, ?> startStep, final long initialBulk) {
+        return new B_LP_NL_O_P_S_SE_SL_Traverser<>(start, startStep, initialBulk);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getProvidedRequirements() {
+        return REQUIREMENTS;
+    }
+
+    public static B_LP_NL_O_P_S_SE_SL_TraverserGenerator instance() {
+        return INSTANCE;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
new file mode 100644
index 0000000..250a1fd
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
+
+import java.util.Stack;
+
+public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T> {
+
+    protected Stack<LabelledCounter> nestedLoops;
+
+    protected B_LP_NL_O_S_SE_SL_Traverser() {
+    }
+
+    public B_LP_NL_O_S_SE_SL_Traverser(final T t, final Step<T, ?> step, final long initialBulk) {
+        super(t, step, initialBulk);
+        this.nestedLoops = new Stack<>();
+    }
+
+    /////////////////
+
+    @Override
+    public int loops() {
+        return this.nestedLoops.size() > 0 ? this.nestedLoops.peek().count() : 0;
+    }
+
+    @Override
+    public void incrLoops(final String stepLabel) {
+        // If we encounter a new stack label then grow the stack otherwise increment the loop count
+        if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
+            this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
+        }
+        else {
+            this.nestedLoops.peek().increment();
+        }
+    }
+
+    @Override
+    public void resetLoops() {
+        // Protect against reset without increment during RepeatStep setup
+        if (this.nestedLoops.size() > 0) {
+            this.nestedLoops.pop();
+        }
+    }
+
+    /////////////////
+
+    @Override
+    public <R> Admin<R> split(final R r, final Step<T, R> step) {
+        final B_LP_NL_O_S_SE_SL_Traverser<R> clone = (B_LP_NL_O_S_SE_SL_Traverser<R>) super.split(r, step);
+        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        return clone;
+    }
+
+    @Override
+    public Admin<T> split() {
+        final B_LP_NL_O_S_SE_SL_Traverser<T> clone = (B_LP_NL_O_S_SE_SL_Traverser<T>) super.split();
+        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        return clone;
+    }
+
+    @Override
+    public void merge(final Admin<?> other) {
+        super.merge(other);
+    }
+
+    /////////////////
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof B_LP_NL_O_S_SE_SL_Traverser)) return false;
+        if (!super.equals(o)) return false;
+
+        B_LP_NL_O_S_SE_SL_Traverser<?> that = (B_LP_NL_O_S_SE_SL_Traverser<?>) o;
+
+        return nestedLoops.equals(that.nestedLoops);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + nestedLoops.hashCode();
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_TraverserGenerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_TraverserGenerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_TraverserGenerator.java
new file mode 100644
index 0000000..2b0c466
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_TraverserGenerator.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+public final class B_LP_NL_O_S_SE_SL_TraverserGenerator implements TraverserGenerator {
+
+    private static final B_LP_NL_O_S_SE_SL_TraverserGenerator INSTANCE = new B_LP_NL_O_S_SE_SL_TraverserGenerator();
+
+    private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(
+            TraverserRequirement.BULK,
+            TraverserRequirement.LABELED_PATH,
+            TraverserRequirement.NESTED_LOOP,
+            TraverserRequirement.OBJECT,
+            TraverserRequirement.SACK,
+            TraverserRequirement.SIDE_EFFECTS,
+            TraverserRequirement.SINGLE_LOOP,
+            TraverserRequirement.NESTED_LOOP);
+
+    private B_LP_NL_O_S_SE_SL_TraverserGenerator() {
+    }
+
+    @Override
+    public <S> Traverser.Admin<S> generate(final S start, final Step<S, ?> startStep, final long initialBulk) {
+        return new B_LP_NL_O_S_SE_SL_Traverser<>(start, startStep, initialBulk);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getProvidedRequirements() {
+        return REQUIREMENTS;
+    }
+
+    public static B_LP_NL_O_S_SE_SL_TraverserGenerator instance() {
+        return INSTANCE;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
new file mode 100644
index 0000000..3018e22
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
+
+import java.util.Stack;
+
+public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
+
+    protected Stack<LabelledCounter> nestedLoops;
+
+    protected B_NL_O_S_SE_SL_Traverser() {
+    }
+
+    public B_NL_O_S_SE_SL_Traverser(final T t, final Step<T, ?> step, final long initialBulk) {
+        super(t, step, initialBulk);
+        this.nestedLoops = new Stack<>();
+    }
+
+    /////////////////
+
+    @Override
+    public int loops() {
+        return this.nestedLoops.size() > 0 ? this.nestedLoops.peek().count() : 0;
+    }
+
+    @Override
+    public void incrLoops(final String stepLabel) {
+        // If we encounter a new stack label then grow the stack otherwise increment the loop count
+        if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
+            this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
+        }
+        else {
+            this.nestedLoops.peek().increment();
+        }
+    }
+
+    @Override
+    public void resetLoops() {
+        // Protect against reset without increment during RepeatStep setup
+        if (this.nestedLoops.size() > 0) {
+            this.nestedLoops.pop();
+        }
+    }
+
+    /////////////////
+
+    @Override
+    public <R> Admin<R> split(final R r, final Step<T, R> step) {
+        final B_NL_O_S_SE_SL_Traverser<R> clone = (B_NL_O_S_SE_SL_Traverser<R>) super.split(r, step);
+        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        return clone;
+    }
+
+    @Override
+    public Admin<T> split() {
+        final B_NL_O_S_SE_SL_Traverser<T> clone = (B_NL_O_S_SE_SL_Traverser<T>) super.split();
+        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        return clone;
+    }
+
+    @Override
+    public void merge(final Admin<?> other) {
+        super.merge(other);
+    }
+
+    /////////////////
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof B_NL_O_S_SE_SL_Traverser)) return false;
+        if (!super.equals(o)) return false;
+
+        B_NL_O_S_SE_SL_Traverser<?> that = (B_NL_O_S_SE_SL_Traverser<?>) o;
+
+        return nestedLoops.equals(that.nestedLoops);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + nestedLoops.hashCode();
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_TraverserGenerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_TraverserGenerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_TraverserGenerator.java
new file mode 100644
index 0000000..4df27c5
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_TraverserGenerator.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+public final class B_NL_O_S_SE_SL_TraverserGenerator implements TraverserGenerator {
+
+    private static final B_NL_O_S_SE_SL_TraverserGenerator INSTANCE = new B_NL_O_S_SE_SL_TraverserGenerator();
+
+    private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(
+            TraverserRequirement.BULK,
+            TraverserRequirement.NESTED_LOOP,
+            TraverserRequirement.OBJECT,
+            TraverserRequirement.SACK,
+            TraverserRequirement.SIDE_EFFECTS,
+            TraverserRequirement.SINGLE_LOOP);
+
+    private B_NL_O_S_SE_SL_TraverserGenerator() {
+    }
+
+    @Override
+    public <S> Traverser.Admin<S> generate(final S start, final Step<S, ?> startStep, final long initialBulk) {
+        return new B_NL_O_S_SE_SL_Traverser<>(start, startStep, initialBulk);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getProvidedRequirements() {
+        return REQUIREMENTS;
+    }
+
+    public static B_NL_O_S_SE_SL_TraverserGenerator instance() {
+        return INSTANCE;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
new file mode 100644
index 0000000..3417864
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
+
+import java.util.Stack;
+
+public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Traverser<T> {
+
+    protected Stack<LabelledCounter> nestedLoops;
+
+    protected LP_NL_O_OB_P_S_SE_SL_Traverser() {
+    }
+
+    public LP_NL_O_OB_P_S_SE_SL_Traverser(final T t, final Step<T, ?> step) {
+        super(t, step);
+        this.nestedLoops = new Stack<>();
+    }
+
+    /////////////////
+
+    @Override
+    public int loops() {
+        return this.nestedLoops.size() > 0 ? this.nestedLoops.peek().count() : 0;
+    }
+
+    @Override
+    public void incrLoops(final String stepLabel) {
+        // If we encounter a new stack label then grow the stack otherwise increment the loop count
+        if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
+            this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
+        }
+        else {
+            this.nestedLoops.peek().increment();
+        }
+    }
+
+    @Override
+    public void resetLoops() {
+        // Protect against reset without increment during RepeatStep setup
+        if (this.nestedLoops.size() > 0) {
+            this.nestedLoops.pop();
+        }
+    }
+
+    /////////////////
+
+    @Override
+    public <R> Admin<R> split(final R r, final Step<T, R> step) {
+        final LP_NL_O_OB_P_S_SE_SL_Traverser<R> clone = (LP_NL_O_OB_P_S_SE_SL_Traverser<R>) super.split(r, step);
+        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        return clone;
+    }
+
+    @Override
+    public Admin<T> split() {
+        final LP_NL_O_OB_P_S_SE_SL_Traverser<T> clone = (LP_NL_O_OB_P_S_SE_SL_Traverser<T>) super.split();
+        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        return clone;
+    }
+
+    @Override
+    public void merge(final Admin<?> other) {
+        super.merge(other);
+    }
+
+    /////////////////
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof LP_NL_O_OB_P_S_SE_SL_Traverser)) return false;
+        if (!super.equals(o)) return false;
+
+        LP_NL_O_OB_P_S_SE_SL_Traverser<?> that = (LP_NL_O_OB_P_S_SE_SL_Traverser<?>) o;
+
+        return nestedLoops.equals(that.nestedLoops);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + nestedLoops.hashCode();
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_TraverserGenerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_TraverserGenerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_TraverserGenerator.java
new file mode 100644
index 0000000..20eb2ca
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_TraverserGenerator.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+public final class LP_NL_O_OB_P_S_SE_SL_TraverserGenerator implements TraverserGenerator {
+
+    private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(
+            TraverserRequirement.LABELED_PATH,
+            TraverserRequirement.NESTED_LOOP,
+            TraverserRequirement.OBJECT,
+            TraverserRequirement.ONE_BULK,
+            TraverserRequirement.PATH,
+            TraverserRequirement.SACK,
+            TraverserRequirement.SIDE_EFFECTS,
+            TraverserRequirement.SINGLE_LOOP);
+
+
+    private static final LP_NL_O_OB_P_S_SE_SL_TraverserGenerator INSTANCE = new LP_NL_O_OB_P_S_SE_SL_TraverserGenerator();
+
+    private LP_NL_O_OB_P_S_SE_SL_TraverserGenerator() {
+    }
+
+    @Override
+    public <S> Traverser.Admin<S> generate(final S start, final Step<S, ?> startStep, final long initialBulk) {
+        return new LP_NL_O_OB_P_S_SE_SL_Traverser<>(start, startStep);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getProvidedRequirements() {
+        return REQUIREMENTS;
+    }
+
+    public static LP_NL_O_OB_P_S_SE_SL_TraverserGenerator instance() {
+        return INSTANCE;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
new file mode 100644
index 0000000..facd4f9
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
+
+import java.util.Stack;
+
+public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T> {
+
+    protected Stack<LabelledCounter> nestedLoops;
+
+    protected LP_NL_O_OB_S_SE_SL_Traverser() {
+    }
+
+    public LP_NL_O_OB_S_SE_SL_Traverser(final T t, final Step<T, ?> step) {
+        super(t, step);
+        this.nestedLoops = new Stack<>();
+    }
+
+    /////////////////
+
+    @Override
+    public int loops() {
+        return this.nestedLoops.size() > 0 ? this.nestedLoops.peek().count() : 0;
+    }
+
+    @Override
+    public void incrLoops(final String stepLabel) {
+        // If we encounter a new stack label then grow the stack otherwise increment the loop count
+        if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
+            this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
+        }
+        else {
+            this.nestedLoops.peek().increment();
+        }
+    }
+
+    @Override
+    public void resetLoops() {
+        // Protect against reset without increment during RepeatStep setup
+        if (this.nestedLoops.size() > 0) {
+            this.nestedLoops.pop();
+        }
+    }
+
+    /////////////////
+
+    @Override
+    public <R> Admin<R> split(final R r, final Step<T, R> step) {
+        final LP_NL_O_OB_S_SE_SL_Traverser<R> clone = (LP_NL_O_OB_S_SE_SL_Traverser<R>) super.split(r, step);
+        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        return clone;
+    }
+
+    @Override
+    public Admin<T> split() {
+        final LP_NL_O_OB_S_SE_SL_Traverser<T> clone = (LP_NL_O_OB_S_SE_SL_Traverser<T>) super.split();
+        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        return clone;
+    }
+
+    @Override
+    public void merge(final Admin<?> other) {
+        super.merge(other);
+    }
+
+    /////////////////
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof LP_NL_O_OB_S_SE_SL_Traverser)) return false;
+        if (!super.equals(o)) return false;
+
+        LP_NL_O_OB_S_SE_SL_Traverser<?> that = (LP_NL_O_OB_S_SE_SL_Traverser<?>) o;
+
+        return nestedLoops.equals(that.nestedLoops);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + nestedLoops.hashCode();
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_TraverserGenerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_TraverserGenerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_TraverserGenerator.java
new file mode 100644
index 0000000..06466a5
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_TraverserGenerator.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+public final class LP_NL_O_OB_S_SE_SL_TraverserGenerator implements TraverserGenerator {
+
+    private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(
+            TraverserRequirement.LABELED_PATH,
+            TraverserRequirement.NESTED_LOOP,
+            TraverserRequirement.OBJECT,
+            TraverserRequirement.ONE_BULK,
+            TraverserRequirement.SACK,
+            TraverserRequirement.SIDE_EFFECTS,
+            TraverserRequirement.SINGLE_LOOP);
+
+
+    private static final LP_NL_O_OB_S_SE_SL_TraverserGenerator INSTANCE = new LP_NL_O_OB_S_SE_SL_TraverserGenerator();
+
+    private LP_NL_O_OB_S_SE_SL_TraverserGenerator() {
+    }
+
+    @Override
+    public <S> Traverser.Admin<S> generate(final S start, final Step<S, ?> startStep, final long initialBulk) {
+        return new LP_NL_O_OB_S_SE_SL_Traverser<>(start, startStep);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getProvidedRequirements() {
+        return REQUIREMENTS;
+    }
+
+    public static LP_NL_O_OB_S_SE_SL_TraverserGenerator instance() {
+        return INSTANCE;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
new file mode 100644
index 0000000..d73dd19
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
+
+import java.util.Stack;
+
+public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
+
+    protected Stack<LabelledCounter> nestedLoops;
+
+
+    protected NL_O_OB_S_SE_SL_Traverser() {
+    }
+
+    public NL_O_OB_S_SE_SL_Traverser(final T t, final Step<T, ?> step) {
+        super(t, step);
+    }
+
+    /////////////////
+
+    @Override
+    public int loops() {
+        return this.nestedLoops.size() > 0 ? this.nestedLoops.peek().count() : 0;
+    }
+
+    @Override
+    public void incrLoops(final String stepLabel) {
+        // If we encounter a new stack label then grow the stack otherwise increment the loop count
+        if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
+            this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
+        }
+        else {
+            this.nestedLoops.peek().increment();
+        }
+    }
+
+    @Override
+    public void resetLoops() {
+        // Protect against reset without increment during RepeatStep setup
+        if (this.nestedLoops.size() > 0) {
+            this.nestedLoops.pop();
+        }
+    }
+
+    /////////////////
+
+    @Override
+    public <R> Admin<R> split(final R r, final Step<T, R> step) {
+        final NL_O_OB_S_SE_SL_Traverser<R> clone = (NL_O_OB_S_SE_SL_Traverser<R>) super.split(r, step);
+        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        return clone;
+    }
+
+    @Override
+    public Admin<T> split() {
+        final NL_O_OB_S_SE_SL_Traverser<T> clone = (NL_O_OB_S_SE_SL_Traverser<T>) super.split();
+        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        return clone;
+    }
+
+    @Override
+    public void merge(final Admin<?> other) {
+        super.merge(other);
+    }
+
+    /////////////////
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof NL_O_OB_S_SE_SL_Traverser)) return false;
+        if (!super.equals(o)) return false;
+
+        NL_O_OB_S_SE_SL_Traverser<?> that = (NL_O_OB_S_SE_SL_Traverser<?>) o;
+
+        return nestedLoops.equals(that.nestedLoops);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + nestedLoops.hashCode();
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_TraverserGenerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_TraverserGenerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_TraverserGenerator.java
new file mode 100644
index 0000000..dd413ac
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_TraverserGenerator.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+public final class NL_O_OB_S_SE_SL_TraverserGenerator implements TraverserGenerator {
+
+    private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(
+            TraverserRequirement.NESTED_LOOP,
+            TraverserRequirement.OBJECT,
+            TraverserRequirement.ONE_BULK,
+            TraverserRequirement.SACK,
+            TraverserRequirement.SIDE_EFFECTS,
+            TraverserRequirement.SINGLE_LOOP);
+
+
+    private static final NL_O_OB_S_SE_SL_TraverserGenerator INSTANCE = new NL_O_OB_S_SE_SL_TraverserGenerator();
+
+    private NL_O_OB_S_SE_SL_TraverserGenerator() {
+    }
+
+    @Override
+    public <S> Traverser.Admin<S> generate(final S start, final Step<S, ?> startStep, final long initialBulk) {
+        return new NL_O_OB_S_SE_SL_Traverser<>(start, startStep);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getProvidedRequirements() {
+        return REQUIREMENTS;
+    }
+
+    public static NL_O_OB_S_SE_SL_TraverserGenerator instance() {
+        return INSTANCE;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactory.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactory.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactory.java
index 932791e..05a3f3a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactory.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactory.java
@@ -18,18 +18,22 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.traverser.util;
 
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_P_S_SE_SL_TraverserGenerator;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_NL_O_P_S_SE_SL_TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_S_SE_SL_TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_S_SE_SL_TraverserGenerator;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_NL_O_S_SE_SL_TraverserGenerator;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_NL_O_S_SE_SL_TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_O_OB_P_S_SE_SL_TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_O_OB_S_SE_SL_TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.O_OB_S_SE_SL_TraverserGenerator;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.NL_O_OB_S_SE_SL_TraverserGenerator;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_NL_O_OB_S_SE_SL_TraverserGenerator;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_NL_O_OB_P_S_SE_SL_TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserGeneratorFactory;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 
 import java.util.Set;
 
@@ -53,11 +57,20 @@ public class DefaultTraverserGeneratorFactory implements TraverserGeneratorFacto
             if (O_OB_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
                 return O_OB_S_SE_SL_TraverserGenerator.instance();
 
+            if (NL_O_OB_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
+                return NL_O_OB_S_SE_SL_TraverserGenerator.instance();
+
             if (LP_O_OB_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
                 return LP_O_OB_S_SE_SL_TraverserGenerator.instance();
 
+            if (LP_NL_O_OB_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
+                return LP_NL_O_OB_S_SE_SL_TraverserGenerator.instance();
+
             if (LP_O_OB_P_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
                 return LP_O_OB_P_S_SE_SL_TraverserGenerator.instance();
+
+            if (LP_NL_O_OB_P_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
+                return LP_NL_O_OB_P_S_SE_SL_TraverserGenerator.instance();
         } else {
             if (B_O_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
                 return B_O_TraverserGenerator.instance();
@@ -65,11 +78,20 @@ public class DefaultTraverserGeneratorFactory implements TraverserGeneratorFacto
             if (B_O_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
                 return B_O_S_SE_SL_TraverserGenerator.instance();
 
+            if (B_NL_O_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
+                return B_NL_O_S_SE_SL_TraverserGenerator.instance();
+
             if (B_LP_O_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
                 return B_LP_O_S_SE_SL_TraverserGenerator.instance();
 
+            if (B_LP_NL_O_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
+                return B_LP_NL_O_S_SE_SL_TraverserGenerator.instance();
+
             if (B_LP_O_P_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
                 return B_LP_O_P_S_SE_SL_TraverserGenerator.instance();
+
+            if (B_LP_NL_O_P_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
+                return B_LP_NL_O_P_S_SE_SL_TraverserGenerator.instance();
         }
 
         throw new IllegalStateException("The provided traverser generator factory does not support the requirements of the traversal: " + this.getClass().getCanonicalName() + requirements);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
new file mode 100644
index 0000000..bc07487
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.traverser.util;
+
+import org.apache.commons.lang.mutable.MutableShort;
+
+import java.io.Serializable;
+
+/**
+ * Class to track a count associated with a Label
+ */
+public class LabelledCounter implements Serializable {
+
+    private String label;
+
+    private MutableShort count;
+
+    public LabelledCounter(String label, short initialCount) {
+        if (label == null) {
+            throw new NullPointerException("Label is null");
+        }
+        this.label = label;
+        this.count = new MutableShort(initialCount);
+    }
+
+    public boolean hasLabel(String label){
+        return this.label.equals(label);
+    }
+
+    public int count() {
+        return this.count.intValue();
+    }
+
+    public void increment() {
+        this.count.increment();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof LabelledCounter)) return false;
+
+        LabelledCounter that = (LabelledCounter) o;
+
+        if (!label.equals(that.label)) return false;
+        return count.equals(that.count);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = label.hashCode();
+        result = 31 * result + count.hashCode();
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
index 6bb7b34..fb2cffa 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
@@ -65,12 +65,18 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Repe
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_P_S_SE_SL_Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_NL_O_P_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_S_SE_SL_Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_NL_O_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_S_SE_SL_Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_NL_O_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_O_OB_P_S_SE_SL_Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_NL_O_OB_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_O_OB_S_SE_SL_Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_NL_O_OB_P_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.O_OB_S_SE_SL_Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.NL_O_OB_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.O_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.ProjectedTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.IndexedTraverserSet;
@@ -109,6 +115,9 @@ import org.apache.tinkerpop.shaded.kryo.ClassResolver;
 import org.apache.tinkerpop.shaded.kryo.KryoSerializable;
 import org.apache.tinkerpop.shaded.kryo.serializers.JavaSerializer;
 import org.javatuples.Pair;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
+import org.apache.commons.lang.mutable.MutableShort;
+import java.util.Stack;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -294,6 +303,7 @@ public enum GryoVersion {
             add(GryoTypeReg.of(O_OB_S_SE_SL_Traverser.class, 89));
             add(GryoTypeReg.of(LP_O_OB_S_SE_SL_Traverser.class, 90));
             add(GryoTypeReg.of(LP_O_OB_P_S_SE_SL_Traverser.class, 91));
+
             add(GryoTypeReg.of(ProjectedTraverser.class, 168));
             add(GryoTypeReg.of(DefaultRemoteTraverser.class, 123, new GryoSerializersV3d0.DefaultRemoteTraverserSerializer()));
 
@@ -373,7 +383,18 @@ public enum GryoVersion {
             add(GryoTypeReg.of(RangeGlobalStep.RangeBiOperator.class, 114));
             add(GryoTypeReg.of(OrderGlobalStep.OrderBiOperator.class, 118));
             add(GryoTypeReg.of(ProfileStep.ProfileBiOperator.class, 119));
-            add(GryoTypeReg.of(IndexedTraverserSet.VertexIndexedTraverserSet.class, 173));                 // ***LAST ID***
+            add(GryoTypeReg.of(IndexedTraverserSet.VertexIndexedTraverserSet.class, 173));
+
+            add(GryoTypeReg.of(B_LP_NL_O_P_S_SE_SL_Traverser.class, 174));
+            add(GryoTypeReg.of(B_NL_O_S_SE_SL_Traverser.class, 175));
+            add(GryoTypeReg.of(B_LP_NL_O_S_SE_SL_Traverser.class, 176));
+            add(GryoTypeReg.of(NL_O_OB_S_SE_SL_Traverser.class, 177));
+            add(GryoTypeReg.of(LP_NL_O_OB_S_SE_SL_Traverser.class, 178));
+            add(GryoTypeReg.of(LP_NL_O_OB_P_S_SE_SL_Traverser.class, 179));
+            add(GryoTypeReg.of(LabelledCounter.class, 180));
+            add(GryoTypeReg.of(MutableShort.class, 181));
+            add(GryoTypeReg.of(Stack.class, 182));                         // ***LAST ID***
+
 
             // placeholder serializers for classes that don't live here in core. this will allow them to be used if
             // present  or ignored if the class isn't available. either way the registration numbers are held as
@@ -552,7 +573,17 @@ public enum GryoVersion {
             add(GryoTypeReg.of(MatchStep.CountMatchAlgorithm.class, 160));
             add(GryoTypeReg.of(MatchStep.GreedyMatchAlgorithm.class, 167));
             // skip 171, 172 to sync with tp33
-            add(GryoTypeReg.of(IndexedTraverserSet.VertexIndexedTraverserSet.class, 173));                 // ***LAST ID***
+            add(GryoTypeReg.of(IndexedTraverserSet.VertexIndexedTraverserSet.class, 173));
+
+            add(GryoTypeReg.of(B_LP_NL_O_P_S_SE_SL_Traverser.class, 174));
+            add(GryoTypeReg.of(B_NL_O_S_SE_SL_Traverser.class, 175));
+            add(GryoTypeReg.of(B_LP_NL_O_S_SE_SL_Traverser.class, 176));
+            add(GryoTypeReg.of(NL_O_OB_S_SE_SL_Traverser.class, 177));
+            add(GryoTypeReg.of(LP_NL_O_OB_S_SE_SL_Traverser.class, 178));
+            add(GryoTypeReg.of(LP_NL_O_OB_P_S_SE_SL_Traverser.class, 179));
+            add(GryoTypeReg.of(LabelledCounter.class, 180));
+            add(GryoTypeReg.of(MutableShort.class, 181));
+            add(GryoTypeReg.of(Stack.class, 182));                         // ***LAST ID***
         }};
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactoryTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactoryTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactoryTest.java
index 60f3880..fbdabcc 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactoryTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactoryTest.java
@@ -25,8 +25,10 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_P_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_S_SE_SL_Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_NL_O_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_O_OB_P_S_SE_SL_Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_NL_O_OB_P_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_O_OB_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.O_OB_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
@@ -56,6 +58,10 @@ public class DefaultTraverserGeneratorFactoryTest {
         traversal.applyStrategies();
         assertEquals(B_O_S_SE_SL_Traverser.class, traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l).getClass());
         //
+        traversal = traversalSource.V().repeat(__.repeat(__.out())).times(10).asAdmin();
+        traversal.applyStrategies();
+        assertEquals(B_NL_O_S_SE_SL_Traverser.class, traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l).getClass());
+        //
         traversal = traversalSource.V().out().sack().asAdmin();
         traversal.applyStrategies();
         assertEquals(B_O_S_SE_SL_Traverser.class, traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l).getClass());
@@ -79,6 +85,10 @@ public class DefaultTraverserGeneratorFactoryTest {
         traversal = traversalSource.withBulk(false).V().out().path().asAdmin();
         traversal.applyStrategies();
         assertEquals(LP_O_OB_P_S_SE_SL_Traverser.class, traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l).getClass());
+        //
+        traversal = traversalSource.withBulk(false).V().repeat(__.repeat(__.out())).times(10).path().asAdmin();
+        traversal.applyStrategies();
+        assertEquals(LP_NL_O_OB_P_S_SE_SL_Traverser.class, traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l).getClass());
 
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-test/features/branch/Repeat.feature
----------------------------------------------------------------------
diff --git a/gremlin-test/features/branch/Repeat.feature b/gremlin-test/features/branch/Repeat.feature
index 6175519..b176477 100644
--- a/gremlin-test/features/branch/Repeat.feature
+++ b/gremlin-test/features/branch/Repeat.feature
@@ -244,3 +244,51 @@ Feature: Step - repeat()
       | loop |
       | loop  |
       | loop  |
+
+Scenario: g_V_repeatXout_repeatXoutX_timesX1XX_timesX1X_limitX1X_path_by_name
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().repeat(__.out().repeat(__.out()).times(1)).times(1).limit(1).path().by("name")
+      """
+    When iterated next
+    Then the result should be unordered
+      | result |
+      | marko |
+      | josh |
+      | ripple |
+
+Scenario: g_V_repeatXoutXknowsXX_untilXrepeatXoutXcreatedXX_emitXhasXname_lopXXX_path_byXnameX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().repeat(__.out("knows")).until(__.repeat(__.out("created")).emit(__.has("name", "lop"))).path().by("name")
+      """
+    When iterated next
+    Then the result should be unordered
+      | result |
+      | marko |
+      | josh |
+
+Scenario: g_V_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang
+  Given the modern graph
+  And the traversal of
+    """
+    g.V().repeat(__.repeat(__.out("created")).until(__.has("name", "ripple"))).emit().values("lang")
+    """
+  When iterated to list
+  Then the result should be unordered
+    | result |
+    | java |
+
+Scenario: g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang
+  Given the modern graph
+  And the traversal of
+    """
+    g.V().until(__.constant(true)).repeat(__.repeat(__.out("created")).until(__.has("name", "ripple"))).emit().values("lang")
+    """
+  When iterated to list
+  Then the result should be unordered
+    | result |
+    | java |
+    | java |

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/320c1436/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
index 6d90687..d8da3fb 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.MapHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
@@ -98,6 +99,16 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Path> get_g_V_hasXname_markoX_repeatXoutE_inV_simplePathX_untilXhasXname_rippleXX_path_byXnameX_byXlabelX();
 
+    // NESTED LOOP
+
+    public abstract Traversal<Vertex, Path> get_g_V_repeatXout_repeatXoutX_timesX1XX_timesX1X_limitX1X_path_by_name();
+
+    public abstract Traversal<Vertex, Path> get_g_V_repeatXoutXknowsXX_untilXrepeatXoutXcreatedXX_emitXhasXname_lopXXX_path_byXnameX();
+
+    public abstract Traversal<Vertex, String> get_g_V_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang();
+
+    public abstract Traversal<Vertex, String> get_g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_repeatXoutX_timesX2X_emit_path() {
@@ -310,6 +321,65 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
         assertEquals("ripple", path.get(4));
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_repeatXout_repeatXoutX_timesX1XX_timesX1X_limitX1X_path_by_name() {
+        // This traversal gets optimised by the RepeatUnrollStrategy
+        final Traversal<Vertex, Path> traversal_unrolled = get_g_V_repeatXout_repeatXoutX_timesX1XX_timesX1X_limitX1X_path_by_name();
+        final Path path_original = traversal_unrolled.next();
+
+        g = g.withoutStrategies(RepeatUnrollStrategy.class);
+
+        final Traversal<Vertex, Path> traversal = get_g_V_repeatXout_repeatXoutX_timesX1XX_timesX1X_limitX1X_path_by_name();
+        printTraversalForm(traversal);
+        final Path path = traversal.next();
+        assertFalse(traversal.hasNext());
+        assertEquals(3, path.size());
+        assertEquals("marko", path.get(0));
+        assertEquals("josh", path.get(1));
+        assertEquals("ripple", path.get(2));
+
+        assertEquals(path, path_original);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_repeatXoutXknowsXX_untilXrepeatXoutXcreatedXX_emitXhasXname_lopXXX_path_byXnameX() {
+        final Traversal<Vertex, Path> traversal = get_g_V_repeatXoutXknowsXX_untilXrepeatXoutXcreatedXX_emitXhasXname_lopXXX_path_byXnameX();
+        printTraversalForm(traversal);
+        final Path path = traversal.next();
+        assertFalse(traversal.hasNext());
+        assertEquals(2, path.size());
+        assertEquals("marko", path.get(0));
+        assertEquals("josh", path.get(1));
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang() {
+        final Traversal<Vertex, String> traversal = get_g_V_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang();
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        String lang = traversal.next();
+        assertEquals(lang, "java");
+        assertFalse(traversal.hasNext());
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang() {
+        final Traversal<Vertex, String> traversal = get_g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang();
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        String lang = traversal.next();
+        assertEquals(lang, "java");
+        assertTrue(traversal.hasNext());
+        lang = traversal.next();
+        assertEquals(lang, "java");
+        assertFalse(traversal.hasNext());
+    }
+
+
     public static class Traversals extends RepeatTest {
 
         @Override
@@ -386,5 +456,26 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
         public Traversal<Vertex, Path> get_g_V_hasXloop_name_loopX_repeatXinX_timesX5X_path_by_name() {
             return g.V().has("loops","name","loop").repeat(__.in()).times(5).path().by("name");
         }
+
+        @Override
+        public Traversal<Vertex, Path> get_g_V_repeatXout_repeatXoutX_timesX1XX_timesX1X_limitX1X_path_by_name() {
+            // NB We need to prevent the RepeatUnrollStrategy from applying to properly exercise this test as this traversal can be simplified
+            return g.V().repeat(out().repeat(out()).times(1)).times(1).limit(1).path().by("name");
+        }
+
+        @Override
+        public Traversal<Vertex, Path> get_g_V_repeatXoutXknowsXX_untilXrepeatXoutXcreatedXX_emitXhasXname_lopXXX_path_byXnameX() {
+            return g.V().repeat(out("knows")).until(__.repeat(out("created")).emit(__.has("name", "lop"))).path().by("name");
+        }
+
+        @Override
+        public Traversal<Vertex, String> get_g_V_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang() {
+            return g.V().repeat(__.repeat(out("created")).until(__.has("name", "ripple"))).emit().values("lang");
+        }
+
+        @Override
+        public Traversal<Vertex, String> get_g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang() {
+            return g.V().until(__.constant(true)).repeat(__.repeat(out("created")).until(__.has("name", "ripple"))).emit().values("lang");
+        }
     }
 }


[10/11] tinkerpop git commit: Merge branch 'pr-876'

Posted by sp...@apache.org.
Merge branch 'pr-876'


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/fe104acc
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/fe104acc
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/fe104acc

Branch: refs/heads/master
Commit: fe104acc1a3212c04cd78eeb3c924ba2ab8efd09
Parents: ea6884a d5de5d8
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Jul 17 11:11:49 2018 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Jul 17 11:11:49 2018 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   1 +
 docs/src/reference/the-traversal.asciidoc       |  17 ++
 docs/src/upgrade/release-3.4.x.asciidoc         |  16 ++
 .../gremlin/process/traversal/Traverser.java    |  23 ++-
 .../traversal/dsl/graph/GraphTraversal.java     |  32 +++-
 .../gremlin/process/traversal/dsl/graph/__.java |  14 ++
 .../traversal/step/branch/RepeatStep.java       |  24 ++-
 .../process/traversal/step/map/LoopsStep.java   |  26 ++-
 .../optimization/RepeatUnrollStrategy.java      |   5 +-
 .../B_LP_NL_O_P_S_SE_SL_Traverser.java          | 156 +++++++++++++++
 .../B_LP_NL_O_P_S_SE_SL_TraverserGenerator.java |  58 ++++++
 .../traverser/B_LP_NL_O_S_SE_SL_Traverser.java  | 155 +++++++++++++++
 .../B_LP_NL_O_S_SE_SL_TraverserGenerator.java   |  58 ++++++
 .../traverser/B_NL_O_S_SE_SL_Traverser.java     | 158 +++++++++++++++
 .../B_NL_O_S_SE_SL_TraverserGenerator.java      |  56 ++++++
 .../traverser/B_O_S_SE_SL_Traverser.java        |  26 ++-
 .../LP_NL_O_OB_P_S_SE_SL_Traverser.java         | 156 +++++++++++++++
 ...LP_NL_O_OB_P_S_SE_SL_TraverserGenerator.java |  60 ++++++
 .../traverser/LP_NL_O_OB_S_SE_SL_Traverser.java | 156 +++++++++++++++
 .../LP_NL_O_OB_S_SE_SL_TraverserGenerator.java  |  59 ++++++
 .../traverser/NL_O_OB_S_SE_SL_Traverser.java    | 156 +++++++++++++++
 .../NL_O_OB_S_SE_SL_TraverserGenerator.java     |  58 ++++++
 .../traverser/O_OB_S_SE_SL_Traverser.java       |  26 ++-
 .../traversal/traverser/ProjectedTraverser.java |  14 +-
 .../traverser/util/AbstractTraverser.java       |  13 +-
 .../util/DefaultTraverserGeneratorFactory.java  |  26 ++-
 .../traverser/util/EmptyTraverser.java          |  12 +-
 .../traverser/util/LabelledCounter.java         |  83 ++++++++
 .../gremlin/structure/io/gryo/GryoVersion.java  |  35 +++-
 .../traversal/step/branch/RepeatStepTest.java   |   4 +-
 .../optimization/RepeatUnrollStrategyTest.java  |   7 +
 .../DefaultTraverserGeneratorFactoryTest.java   |  10 +
 .../Process/Traversal/GraphTraversal.cs         |  18 ++
 .../src/Gremlin.Net/Process/Traversal/__.cs     |  16 ++
 gremlin-test/features/branch/Repeat.feature     | 110 +++++++++++
 .../traversal/step/branch/RepeatTest.java       | 191 +++++++++++++++++++
 36 files changed, 2003 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fe104acc/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --cc CHANGELOG.asciidoc
index 7e3b705,4dc106d..ff3d9b5
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@@ -36,11 -36,11 +36,12 @@@ This release also includes changes fro
  * Allowed `GraphProvider` to expose a cached `Graph.Feature` object so that the test suite could re-use them to speed test runs.
  * Fixed a bug in `ReducingBarrierStep`, that returned the provided seed value despite no elements being available.
  * Changed the order of `select()` scopes. The order is now: maps, side-effects, paths.
 -* Removed previously deprecated Credentials DSL infrastructure.
  * Moved `TraversalEngine` to `gremlin-test` as it has long been only used in testing infrastructure.
+ * Nested loop support added allowing `repeat()` steps to be nested.
  * Events from `EventStrategy` raised from "new" mutations will now return a `KeyedVertexProperty` or `KeyedProperty` as is appropriate.
  * `MutationListener#vertexPropertyChanged(Vertex, VertexProperty, Object, Object...)` no longer has a default implementation.
 +* Removed previously deprecated methods in `SubgraphStrategy` and `PartitionStrategy` builders.
 +* Removed previously deprecated Credentials DSL infrastructure.
  * Removed previously deprecated `MutationListener#vertexPropertyChanged(Vertex, Property, Object, Object...)`.
  * Removed previously deprecated `OpSelectorHandler` constructor.
  * Removed previously deprecated `close()` from `GremlinGroovyScriptEngine` which no longer implements `AutoCloseable`.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fe104acc/docs/src/upgrade/release-3.4.x.asciidoc
----------------------------------------------------------------------


[11/11] tinkerpop git commit: Finalized some variables CTR

Posted by sp...@apache.org.
Finalized some variables CTR


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/a546d260
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/a546d260
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/a546d260

Branch: refs/heads/master
Commit: a546d260073e7c39435dbb367fa326c3e5fe5658
Parents: fe104ac
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Jul 17 13:13:53 2018 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Jul 17 13:13:53 2018 -0400

----------------------------------------------------------------------
 .../process/traversal/dsl/graph/GraphTraversal.java |  2 +-
 .../gremlin/process/traversal/dsl/graph/__.java     |  2 +-
 .../process/traversal/step/map/LoopsStep.java       |  4 ++--
 .../traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java    | 16 ++++++++--------
 .../traverser/B_LP_NL_O_S_SE_SL_Traverser.java      | 16 ++++++++--------
 .../traverser/B_NL_O_S_SE_SL_Traverser.java         | 16 ++++++++--------
 .../traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java   | 16 ++++++++--------
 .../traverser/LP_NL_O_OB_S_SE_SL_Traverser.java     | 16 ++++++++--------
 .../traverser/NL_O_OB_S_SE_SL_Traverser.java        | 16 ++++++++--------
 .../traversal/traverser/ProjectedTraverser.java     |  2 +-
 .../traversal/traverser/util/LabelledCounter.java   |  2 +-
 11 files changed, 54 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a546d260/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 0a7eb95..63aa65d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -658,7 +658,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
      * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#loops-step" target="_blank">Reference Documentation - Loops Step</a>
      * @since 3.4.0
      */
-    public default GraphTraversal<S, Integer> loops(String loopName) {
+    public default GraphTraversal<S, Integer> loops(final String loopName) {
         this.asAdmin().getBytecode().addStep(Symbols.loops, loopName);
         return this.asAdmin().addStep(new LoopsStep<>(this.asAdmin(), loopName));
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a546d260/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index ae5c829..02eee79 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -326,7 +326,7 @@ public class __ {
     /**
      * @see GraphTraversal#loops(String)
      */
-    public static <A> GraphTraversal<A, Integer> loops(String loopName) {
+    public static <A> GraphTraversal<A, Integer> loops(final String loopName) {
         return __.<A>start().loops(loopName);
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a546d260/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
index 0a9167c..11d8729 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
@@ -39,12 +39,12 @@ public final class LoopsStep<S> extends MapStep<S, Integer> {
     }
 
     @Override
-    public boolean equals(Object o) {
+    public boolean equals(final Object o) {
         if (this == o) return true;
         if (!(o instanceof LoopsStep)) return false;
         if (!super.equals(o)) return false;
 
-        LoopsStep<?> loopsStep = (LoopsStep<?>) o;
+        final LoopsStep<?> loopsStep = (LoopsStep<?>) o;
 
         return loopName != null ? loopName.equals(loopsStep.loopName) : loopsStep.loopName == null;
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a546d260/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
index 04ba98a..1af9dbe 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
@@ -60,7 +60,7 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
     @Override
     public void initialiseLoops(final String stepLabel, final String loopName) {
         if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) {
-            LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
+            final LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
             this.nestedLoops.push(lc);
             if (loopName != null)
                 this.loopNames.put(loopName, lc);
@@ -89,11 +89,11 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
         if (this.loopNames != null) {
             clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
-            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            final Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
             while (loopNamesIterator.hasNext()) {
-                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+                final ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
 
-                int idx = this.nestedLoops.indexOf(pair.getValue());
+                final int idx = this.nestedLoops.indexOf(pair.getValue());
                 if (idx != -1)
                     clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
             }
@@ -112,11 +112,11 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
         if (this.loopNames != null) {
             clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
-            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            final Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
             while (loopNamesIterator.hasNext()) {
-                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+                final ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
 
-                int idx = this.nestedLoops.indexOf(pair.getValue());
+                final int idx = this.nestedLoops.indexOf(pair.getValue());
                 if (idx != -1)
                     clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
             }
@@ -138,7 +138,7 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
         if (!(o instanceof B_LP_NL_O_P_S_SE_SL_Traverser)) return false;
         if (!super.equals(o)) return false;
 
-        B_LP_NL_O_P_S_SE_SL_Traverser<?> that = (B_LP_NL_O_P_S_SE_SL_Traverser<?>) o;
+        final B_LP_NL_O_P_S_SE_SL_Traverser<?> that = (B_LP_NL_O_P_S_SE_SL_Traverser<?>) o;
 
         if (!this.nestedLoops.equals(that.nestedLoops)) return false;
         return this.loopNames != null ? this.loopNames.equals(that.loopNames) : that.loopNames == null;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a546d260/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
index 8ddd9fc..59287ac 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
@@ -59,7 +59,7 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
     @Override
     public void initialiseLoops(final String stepLabel, final String loopName) {
         if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) {
-            LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
+            final LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
             this.nestedLoops.push(lc);
             if (loopName != null)
                 this.loopNames.put(loopName, lc);
@@ -88,11 +88,11 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
         if (this.loopNames != null) {
             clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
-            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            final Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
             while (loopNamesIterator.hasNext()) {
-                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+                final ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
 
-                int idx = this.nestedLoops.indexOf(pair.getValue());
+                final int idx = this.nestedLoops.indexOf(pair.getValue());
                 if (idx != -1)
                     clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
             }
@@ -111,11 +111,11 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
         if (this.loopNames != null) {
             clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
-            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            final Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
             while (loopNamesIterator.hasNext()) {
-                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+                final ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
 
-                int idx = this.nestedLoops.indexOf(pair.getValue());
+                final int idx = this.nestedLoops.indexOf(pair.getValue());
                 if (idx != -1)
                     clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
             }
@@ -137,7 +137,7 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
         if (!(o instanceof B_LP_NL_O_S_SE_SL_Traverser)) return false;
         if (!super.equals(o)) return false;
 
-        B_LP_NL_O_S_SE_SL_Traverser<?> that = (B_LP_NL_O_S_SE_SL_Traverser<?>) o;
+        final B_LP_NL_O_S_SE_SL_Traverser<?> that = (B_LP_NL_O_S_SE_SL_Traverser<?>) o;
 
         if (!this.nestedLoops.equals(that.nestedLoops)) return false;
         return this.loopNames != null ? this.loopNames.equals(that.loopNames) : that.loopNames == null;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a546d260/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
index 0eee799..20ed1be 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
@@ -60,7 +60,7 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
     @Override
     public void initialiseLoops(final String stepLabel, final String loopName) {
         if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) {
-            LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
+            final LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
             this.nestedLoops.push(lc);
             if (loopName != null)
                 this.loopNames.put(loopName, lc);
@@ -90,11 +90,11 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
         if (this.loopNames != null) {
             clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
-            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            final Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
             while (loopNamesIterator.hasNext()) {
-                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+                final ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
 
-                int idx = this.nestedLoops.indexOf(pair.getValue());
+                final int idx = this.nestedLoops.indexOf(pair.getValue());
                 if (idx != -1)
                     clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
             }
@@ -114,11 +114,11 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
         if (this.loopNames != null) {
             clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
-            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            final Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
             while (loopNamesIterator.hasNext()) {
-                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+                final ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
 
-                int idx = this.nestedLoops.indexOf(pair.getValue());
+                final int idx = this.nestedLoops.indexOf(pair.getValue());
                 if (idx != -1)
                     clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
             }
@@ -140,7 +140,7 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
         if (!(o instanceof B_NL_O_S_SE_SL_Traverser)) return false;
         if (!super.equals(o)) return false;
 
-        B_NL_O_S_SE_SL_Traverser<?> that = (B_NL_O_S_SE_SL_Traverser<?>) o;
+        final B_NL_O_S_SE_SL_Traverser<?> that = (B_NL_O_S_SE_SL_Traverser<?>) o;
 
         if (!this.nestedLoops.equals(that.nestedLoops)) return false;
         return this.loopNames != null ? this.loopNames.equals(that.loopNames) : that.loopNames == null;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a546d260/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
index c7b42c6..3cb1dd3 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
@@ -60,7 +60,7 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
     @Override
     public void initialiseLoops(final String stepLabel, final String loopName) {
         if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) {
-            LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
+            final LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
             this.nestedLoops.push(lc);
             if (loopName != null)
                 this.loopNames.put(loopName, lc);
@@ -89,11 +89,11 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
         if (this.loopNames != null) {
             clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
-            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            final Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
             while (loopNamesIterator.hasNext()) {
-                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+                final ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
 
-                int idx = this.nestedLoops.indexOf(pair.getValue());
+                final int idx = this.nestedLoops.indexOf(pair.getValue());
                 if (idx != -1)
                     clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
             }
@@ -112,11 +112,11 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
         if (this.loopNames != null) {
             clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
-            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            final Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
             while (loopNamesIterator.hasNext()) {
-                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+                final ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
 
-                int idx = this.nestedLoops.indexOf(pair.getValue());
+                final int idx = this.nestedLoops.indexOf(pair.getValue());
                 if (idx != -1)
                     clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
             }
@@ -138,7 +138,7 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
         if (!(o instanceof LP_NL_O_OB_P_S_SE_SL_Traverser)) return false;
         if (!super.equals(o)) return false;
 
-        LP_NL_O_OB_P_S_SE_SL_Traverser<?> that = (LP_NL_O_OB_P_S_SE_SL_Traverser<?>) o;
+        final LP_NL_O_OB_P_S_SE_SL_Traverser<?> that = (LP_NL_O_OB_P_S_SE_SL_Traverser<?>) o;
 
         if (!this.nestedLoops.equals(that.nestedLoops)) return false;
         return this.loopNames != null ? this.loopNames.equals(that.loopNames) : that.loopNames == null;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a546d260/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
index 7e61841..a9cd7fb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
@@ -60,7 +60,7 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
     @Override
     public void initialiseLoops(final String stepLabel, final String loopName) {
         if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) {
-            LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
+            final LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
             this.nestedLoops.push(lc);
             if (loopName != null)
                 this.loopNames.put(loopName, lc);
@@ -89,11 +89,11 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
         if (this.loopNames != null) {
             clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
-            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            final Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
             while (loopNamesIterator.hasNext()) {
-                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+                final ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
 
-                int idx = this.nestedLoops.indexOf(pair.getValue());
+                final int idx = this.nestedLoops.indexOf(pair.getValue());
                 if (idx != -1)
                     clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
             }
@@ -112,11 +112,11 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
         if (this.loopNames != null) {
             clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
-            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            final Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
             while (loopNamesIterator.hasNext()) {
-                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+                final ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
 
-                int idx = this.nestedLoops.indexOf(pair.getValue());
+                final int idx = this.nestedLoops.indexOf(pair.getValue());
                 if (idx != -1)
                     clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
             }
@@ -138,7 +138,7 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
         if (!(o instanceof LP_NL_O_OB_S_SE_SL_Traverser)) return false;
         if (!super.equals(o)) return false;
 
-        LP_NL_O_OB_S_SE_SL_Traverser<?> that = (LP_NL_O_OB_S_SE_SL_Traverser<?>) o;
+        final LP_NL_O_OB_S_SE_SL_Traverser<?> that = (LP_NL_O_OB_S_SE_SL_Traverser<?>) o;
 
         if (!this.nestedLoops.equals(that.nestedLoops)) return false;
         return this.loopNames != null ? this.loopNames.equals(that.loopNames) : that.loopNames == null;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a546d260/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
index 9bbd94a..72f43fe 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
@@ -60,7 +60,7 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
     @Override
     public void initialiseLoops(final String stepLabel, final String loopName) {
         if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) {
-            LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
+            final LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
             this.nestedLoops.push(lc);
             if (loopName != null)
                 this.loopNames.put(loopName, lc);
@@ -89,11 +89,11 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
         if (this.loopNames != null) {
             clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
-            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            final Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
             while (loopNamesIterator.hasNext()) {
-                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+                final ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
 
-                int idx = this.nestedLoops.indexOf(pair.getValue());
+                final int idx = this.nestedLoops.indexOf(pair.getValue());
                 if (idx != -1)
                     clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
             }
@@ -112,11 +112,11 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
         if (this.loopNames != null) {
             clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
-            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            final Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
             while (loopNamesIterator.hasNext()) {
-                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+                final ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
 
-                int idx = this.nestedLoops.indexOf(pair.getValue());
+                final int idx = this.nestedLoops.indexOf(pair.getValue());
                 if (idx != -1)
                     clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
             }
@@ -138,7 +138,7 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
         if (!(o instanceof NL_O_OB_S_SE_SL_Traverser)) return false;
         if (!super.equals(o)) return false;
 
-        NL_O_OB_S_SE_SL_Traverser<?> that = (NL_O_OB_S_SE_SL_Traverser<?>) o;
+        final NL_O_OB_S_SE_SL_Traverser<?> that = (NL_O_OB_S_SE_SL_Traverser<?>) o;
 
         if (!this.nestedLoops.equals(that.nestedLoops)) return false;
         return this.loopNames != null ? this.loopNames.equals(that.loopNames) : that.loopNames == null;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a546d260/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
index ad3712b..7cef844 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
@@ -172,7 +172,7 @@ public final class ProjectedTraverser<T, P> implements Traverser.Admin<T> {
     }
 
     @Override
-    public int loops(String loopName) {
+    public int loops(final String loopName) {
         return this.baseTraverser.loops(loopName);
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a546d260/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
index 0021699..d607361 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
@@ -64,7 +64,7 @@ public class LabelledCounter implements Serializable, Cloneable {
     }
 
     @Override
-    public boolean equals(Object o) {
+    public boolean equals(final Object o) {
         if (this == o) return true;
         if (!(o instanceof LabelledCounter)) return false;
 


[07/11] tinkerpop git commit: Changed from supplying the step label on increment to initialising a looping construct with the stepLabel.

Posted by sp...@apache.org.
Changed from supplying the step label on increment to initialising a looping construct with the stepLabel.

Added initialiseLoops method and removed stepLabel parameter from incrLoops.
Modified Looping Traversers and Base Traversers with the new methods.
Added NestedLoop test that requires loop to be set up before the increment is called.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/0b46fcd7
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/0b46fcd7
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/0b46fcd7

Branch: refs/heads/master
Commit: 0b46fcd75c538acc6c5df83c446e9455fdd6775d
Parents: 8a26b3a
Author: GCHQResearcher1337 <39...@users.noreply.github.com>
Authored: Fri Jul 6 15:43:06 2018 +0100
Committer: GCHQResearcher1337 <39...@users.noreply.github.com>
Committed: Fri Jul 6 15:57:44 2018 +0100

----------------------------------------------------------------------
 .../gremlin/process/traversal/Traverser.java    | 12 ++++++---
 .../traversal/step/branch/RepeatStep.java       |  9 ++++---
 .../B_LP_NL_O_P_S_SE_SL_Traverser.java          | 27 +++++++++-----------
 .../traverser/B_LP_NL_O_S_SE_SL_Traverser.java  | 27 +++++++++-----------
 .../traverser/B_NL_O_S_SE_SL_Traverser.java     | 27 +++++++++-----------
 .../traverser/B_O_S_SE_SL_Traverser.java        |  2 +-
 .../LP_NL_O_OB_P_S_SE_SL_Traverser.java         | 27 +++++++++-----------
 .../traverser/LP_NL_O_OB_S_SE_SL_Traverser.java | 25 ++++++++----------
 .../traverser/NL_O_OB_S_SE_SL_Traverser.java    | 27 +++++++++-----------
 .../traverser/O_OB_S_SE_SL_Traverser.java       |  2 +-
 .../traversal/traverser/ProjectedTraverser.java |  9 +++++--
 .../traverser/util/AbstractTraverser.java       |  8 +++++-
 .../traverser/util/EmptyTraverser.java          |  7 ++++-
 .../traverser/util/LabelledCounter.java         |  5 ++++
 gremlin-test/features/branch/Repeat.feature     | 12 +++++++++
 .../traversal/step/branch/RepeatTest.java       | 20 +++++++++++++++
 16 files changed, 143 insertions(+), 103 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
index 93ebe7d..5fed40b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
@@ -213,14 +213,18 @@ public interface Traverser<T> extends Serializable, Comparable<Traverser<T>>, Cl
         public void set(final T t);
 
         /**
-         * Increment the number of times the traverser has gone through a looping section of traversal.
+         * Initialise a loop by setting up the looping construct.
          * The step label is important to create a stack of loop counters when within a nested context.
          * If the provided label is not the same as the current label on the stack, add a new loop counter.
-         * If the provided label is the same as the current label on the stack, increment the loop counter.
          *
-         * @param stepLabel the label of the step that is doing the incrementing
+         * @param stepLabel the label of the step that is being set-up.
+         */
+        public void initialiseLoops(final String stepLabel);
+
+        /**
+         * Increment the number of times the traverser has gone through a looping section of traversal.
          */
-        public void incrLoops(final String stepLabel);
+        public void incrLoops();
 
         /**
          * Set the number of times the traverser has gone through a loop back to 0.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
index bf2c203..ad949f8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
@@ -189,6 +189,7 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
                 return this.repeatTraversal.getEndStep();
             } else {
                 final Traverser.Admin<S> start = this.starts.next();
+                start.initialiseLoops(this.getId());
                 if (doUntil(start, true)) {
                     start.resetLoops();
                     return IteratorUtils.of(start);
@@ -210,12 +211,12 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
 
         final Traverser.Admin<S> start = this.starts.next();
         if (doUntil(start, true)) {
-            start.resetLoops();
             start.setStepId(this.getNextStep().getId());
             start.addLabels(this.labels);
             return IteratorUtils.of(start);
         } else {
             start.setStepId(this.repeatTraversal.getStartStep().getId());
+            start.initialiseLoops(start.getStepId());
             if (doEmit(start, true)) {
                 final Traverser.Admin<S> emitSplit = start.split();
                 emitSplit.resetLoops();
@@ -278,7 +279,7 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
             final RepeatStep<S> repeatStep = (RepeatStep<S>) this.getTraversal().getParent();
             while (true) {
                 final Traverser.Admin<S> start = this.starts.next();
-                start.incrLoops(this.getId());
+                start.incrLoops();
                 if (repeatStep.doUntil(start, false)) {
                     start.resetLoops();
                     return IteratorUtils.of(start);
@@ -300,7 +301,7 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
         protected Iterator<Traverser.Admin<S>> computerAlgorithm() throws NoSuchElementException {
             final RepeatStep<S> repeatStep = (RepeatStep<S>) this.getTraversal().getParent();
             final Traverser.Admin<S> start = this.starts.next();
-            start.incrLoops(repeatStep.getId());
+            start.incrLoops();
             if (repeatStep.doUntil(start, false)) {
                 start.resetLoops();
                 start.setStepId(repeatStep.getNextStep().getId());
@@ -320,4 +321,4 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
         }
     }
 
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
index b837642..380eb9f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
@@ -39,26 +39,23 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
 
     @Override
     public int loops() {
-        return this.nestedLoops.size() > 0 ? this.nestedLoops.peek().count() : 0;
+        return this.nestedLoops.peek().count();
     }
 
     @Override
-    public void incrLoops(final String stepLabel) {
-        // If we encounter a new step label then grow the stack otherwise increment the loop count
-        if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
-            this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
-        }
-        else {
-            this.nestedLoops.peek().increment();
-        }
+    public void initialiseLoops(final String stepLabel) {
+        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel))
+            this.nestedLoops.push(new LabelledCounter(stepLabel, (short)0));
+    }
+
+    @Override
+    public void incrLoops() {
+        this.nestedLoops.peek().increment();
     }
 
     @Override
     public void resetLoops() {
-        // Protect against reset without increment during RepeatStep setup
-        if (this.nestedLoops.size() > 0) {
-            this.nestedLoops.pop();
-        }
+        this.nestedLoops.pop();
     }
 
     /////////////////
@@ -68,7 +65,7 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
         final B_LP_NL_O_P_S_SE_SL_Traverser<R> clone = (B_LP_NL_O_P_S_SE_SL_Traverser<R>) super.split(r, step);
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
-            clone.nestedLoops.add((LabelledCounter) lc.clone());
+            clone.nestedLoops.push((LabelledCounter) lc.clone());
         return clone;
     }
 
@@ -77,7 +74,7 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
         final B_LP_NL_O_P_S_SE_SL_Traverser<T> clone = (B_LP_NL_O_P_S_SE_SL_Traverser<T>) super.split();
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
-            clone.nestedLoops.add((LabelledCounter) lc.clone());
+            clone.nestedLoops.push((LabelledCounter) lc.clone());
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
index a4bc1bd..aa3e9b0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
@@ -39,26 +39,23 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
 
     @Override
     public int loops() {
-        return this.nestedLoops.size() > 0 ? this.nestedLoops.peek().count() : 0;
+        return this.nestedLoops.peek().count();
     }
 
     @Override
-    public void incrLoops(final String stepLabel) {
-        // If we encounter a new step label then grow the stack otherwise increment the loop count
-        if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
-            this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
-        }
-        else {
-            this.nestedLoops.peek().increment();
-        }
+    public void initialiseLoops(final String stepLabel) {
+        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel))
+            this.nestedLoops.push(new LabelledCounter(stepLabel, (short)0));
+    }
+
+    @Override
+    public void incrLoops() {
+        this.nestedLoops.peek().increment();
     }
 
     @Override
     public void resetLoops() {
-        // Protect against reset without increment during RepeatStep setup
-        if (this.nestedLoops.size() > 0) {
-            this.nestedLoops.pop();
-        }
+        this.nestedLoops.pop();
     }
 
     /////////////////
@@ -68,7 +65,7 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
         final B_LP_NL_O_S_SE_SL_Traverser<R> clone = (B_LP_NL_O_S_SE_SL_Traverser<R>) super.split(r, step);
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
-            clone.nestedLoops.add((LabelledCounter) lc.clone());
+            clone.nestedLoops.push((LabelledCounter) lc.clone());
         return clone;
     }
 
@@ -77,7 +74,7 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
         final B_LP_NL_O_S_SE_SL_Traverser<T> clone = (B_LP_NL_O_S_SE_SL_Traverser<T>) super.split();
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
-            clone.nestedLoops.add((LabelledCounter) lc.clone());
+            clone.nestedLoops.push((LabelledCounter) lc.clone());
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
index 369448e..8d5d7dd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
@@ -39,26 +39,23 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
 
     @Override
     public int loops() {
-        return this.nestedLoops.size() > 0 ? this.nestedLoops.peek().count() : 0;
+        return this.nestedLoops.peek().count();
     }
 
     @Override
-    public void incrLoops(final String stepLabel) {
-        // If we encounter a new step label then grow the stack otherwise increment the loop count
-        if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
-            this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
-        }
-        else {
-            this.nestedLoops.peek().increment();
-        }
+    public void initialiseLoops(final String stepLabel) {
+        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel))
+            this.nestedLoops.push(new LabelledCounter(stepLabel, (short)0));
+    }
+
+    @Override
+    public void incrLoops() {
+        this.nestedLoops.peek().increment();
     }
 
     @Override
     public void resetLoops() {
-        // Protect against reset without increment during RepeatStep setup
-        if (this.nestedLoops.size() > 0) {
-            this.nestedLoops.pop();
-        }
+        this.nestedLoops.pop();
     }
 
     /////////////////
@@ -68,7 +65,7 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
         final B_NL_O_S_SE_SL_Traverser<R> clone = (B_NL_O_S_SE_SL_Traverser<R>) super.split(r, step);
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
-            clone.nestedLoops.add((LabelledCounter) lc.clone());
+            clone.nestedLoops.push((LabelledCounter) lc.clone());
         return clone;
     }
 
@@ -77,7 +74,7 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
         final B_NL_O_S_SE_SL_Traverser<T> clone = (B_NL_O_S_SE_SL_Traverser<T>) super.split();
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
-            clone.nestedLoops.add((LabelledCounter) lc.clone());
+            clone.nestedLoops.push((LabelledCounter) lc.clone());
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
index 0409cd7..d184b7e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
@@ -64,7 +64,7 @@ public class B_O_S_SE_SL_Traverser<T> extends B_O_Traverser<T> {
     }
 
     @Override
-    public void incrLoops(final String stepLabel) {
+    public void incrLoops() {
         this.loops++;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
index 2409e4a..7fcaa2a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
@@ -40,26 +40,23 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
 
     @Override
     public int loops() {
-        return this.nestedLoops.size() > 0 ? this.nestedLoops.peek().count() : 0;
+        return this.nestedLoops.peek().count();
     }
 
     @Override
-    public void incrLoops(final String stepLabel) {
-        // If we encounter a new step label then grow the stack otherwise increment the loop count
-        if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
-            this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
-        }
-        else {
-            this.nestedLoops.peek().increment();
-        }
+    public void initialiseLoops(final String stepLabel) {
+        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel))
+            this.nestedLoops.push(new LabelledCounter(stepLabel, (short)0));
+    }
+
+    @Override
+    public void incrLoops() {
+        this.nestedLoops.peek().increment();
     }
 
     @Override
     public void resetLoops() {
-        // Protect against reset without increment during RepeatStep setup
-        if (this.nestedLoops.size() > 0) {
-            this.nestedLoops.pop();
-        }
+        this.nestedLoops.pop();
     }
 
     /////////////////
@@ -69,7 +66,7 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
         final LP_NL_O_OB_P_S_SE_SL_Traverser<R> clone = (LP_NL_O_OB_P_S_SE_SL_Traverser<R>) super.split(r, step);
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
-            clone.nestedLoops.add((LabelledCounter) lc.clone());
+            clone.nestedLoops.push((LabelledCounter) lc.clone());
         return clone;
     }
 
@@ -78,7 +75,7 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
         final LP_NL_O_OB_P_S_SE_SL_Traverser<T> clone = (LP_NL_O_OB_P_S_SE_SL_Traverser<T>) super.split();
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
-            clone.nestedLoops.add((LabelledCounter) lc.clone());
+            clone.nestedLoops.push((LabelledCounter) lc.clone());
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
index 65fda97..92eb991 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
@@ -44,22 +44,19 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
     }
 
     @Override
-    public void incrLoops(final String stepLabel) {
-        // If we encounter a new step label then grow the stack otherwise increment the loop count
-        if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
-            this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
-        }
-        else {
-            this.nestedLoops.peek().increment();
-        }
+    public void initialiseLoops(final String stepLabel) {
+        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel))
+            this.nestedLoops.push(new LabelledCounter(stepLabel, (short)0));
+    }
+
+    @Override
+    public void incrLoops() {
+        this.nestedLoops.peek().increment();
     }
 
     @Override
     public void resetLoops() {
-        // Protect against reset without increment during RepeatStep setup
-        if (this.nestedLoops.size() > 0) {
-            this.nestedLoops.pop();
-        }
+        this.nestedLoops.pop();
     }
 
     /////////////////
@@ -69,7 +66,7 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
         final LP_NL_O_OB_S_SE_SL_Traverser<R> clone = (LP_NL_O_OB_S_SE_SL_Traverser<R>) super.split(r, step);
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
-            clone.nestedLoops.add((LabelledCounter) lc.clone());
+            clone.nestedLoops.push((LabelledCounter) lc.clone());
         return clone;
     }
 
@@ -78,7 +75,7 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
         final LP_NL_O_OB_S_SE_SL_Traverser<T> clone = (LP_NL_O_OB_S_SE_SL_Traverser<T>) super.split();
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
-            clone.nestedLoops.add((LabelledCounter) lc.clone());
+            clone.nestedLoops.push((LabelledCounter) lc.clone());
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
index 3975758..31e93fe 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
@@ -40,26 +40,23 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
 
     @Override
     public int loops() {
-        return this.nestedLoops.size() > 0 ? this.nestedLoops.peek().count() : 0;
+        return this.nestedLoops.peek().count();
     }
 
     @Override
-    public void incrLoops(final String stepLabel) {
-        // If we encounter a new step label then grow the stack otherwise increment the loop count
-        if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
-            this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
-        }
-        else {
-            this.nestedLoops.peek().increment();
-        }
+    public void initialiseLoops(final String stepLabel) {
+        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel))
+            this.nestedLoops.push(new LabelledCounter(stepLabel, (short)0));
+    }
+
+    @Override
+    public void incrLoops() {
+        this.nestedLoops.peek().increment();
     }
 
     @Override
     public void resetLoops() {
-        // Protect against reset without increment during RepeatStep setup
-        if (this.nestedLoops.size() > 0) {
-            this.nestedLoops.pop();
-        }
+        this.nestedLoops.pop();
     }
 
     /////////////////
@@ -69,7 +66,7 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
         final NL_O_OB_S_SE_SL_Traverser<R> clone = (NL_O_OB_S_SE_SL_Traverser<R>) super.split(r, step);
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
-            clone.nestedLoops.add((LabelledCounter) lc.clone());
+            clone.nestedLoops.push((LabelledCounter) lc.clone());
         return clone;
     }
 
@@ -78,7 +75,7 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
         final NL_O_OB_S_SE_SL_Traverser<T> clone = (NL_O_OB_S_SE_SL_Traverser<T>) super.split();
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
-            clone.nestedLoops.add((LabelledCounter) lc.clone());
+            clone.nestedLoops.push((LabelledCounter) lc.clone());
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java
index d81a564..e35716d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java
@@ -74,7 +74,7 @@ public class O_OB_S_SE_SL_Traverser<T> extends O_Traverser<T> {
     }
 
     @Override
-    public void incrLoops(final String stepLabel) {
+    public void incrLoops() {
         this.loops++;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
index 602f88f..b624eef 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
@@ -91,8 +91,13 @@ public final class ProjectedTraverser<T, P> implements Traverser.Admin<T> {
     }
 
     @Override
-    public void incrLoops(final String stepLabel) {
-        this.baseTraverser.incrLoops(stepLabel);
+    public void initialiseLoops(final String stepLabel) {
+        this.baseTraverser.initialiseLoops(stepLabel);
+    }
+
+    @Override
+    public void incrLoops() {
+        this.baseTraverser.incrLoops();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
index 50a206b..9d52fea 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
@@ -98,8 +98,14 @@ public abstract class AbstractTraverser<T> implements Traverser<T>, Traverser.Ad
         this.t = t;
     }
 
+
+    @Override
+    public void initialiseLoops(final String stepLabel) {
+
+    }
+
     @Override
-    public void incrLoops(final String stepLabel) {
+    public void incrLoops() {
 
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
index 7c99cb5..4f4ca0a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
@@ -70,7 +70,12 @@ public final class EmptyTraverser<T> implements Traverser<T>, Traverser.Admin<T>
     }
 
     @Override
-    public void incrLoops(final String stepLabel) {
+    public void initialiseLoops(final String stepLabel) {
+
+    }
+
+    @Override
+    public void incrLoops() {
 
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
index a5214d2..0e2130a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
@@ -58,6 +58,11 @@ public class LabelledCounter implements Serializable, Cloneable {
     }
 
     @Override
+    public String toString(){
+        return "Step Label: " + label + " Counter: " + count.toString();
+    }
+
+    @Override
     public boolean equals(final Object o) {
         if (this == o) return true;
         if (!(o instanceof LabelledCounter)) return false;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-test/features/branch/Repeat.feature
----------------------------------------------------------------------
diff --git a/gremlin-test/features/branch/Repeat.feature b/gremlin-test/features/branch/Repeat.feature
index c38fa1b..695ca1f 100644
--- a/gremlin-test/features/branch/Repeat.feature
+++ b/gremlin-test/features/branch/Repeat.feature
@@ -306,3 +306,15 @@ Scenario: g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsX
         | josh |
         | lop |
         | ripple |
+
+Scenario: g_VX1X_repeatXrepeatXunionXout_uses_out_traversesXX_whereXloops_isX0X_timesX1X_timeX2X_name
+    Given the crew graph
+    And using the parameter v1Id defined as "v[marko].id"
+    And the traversal of
+      """
+      g.V(v1Id).repeat(__.repeat(__.union(__.out("uses"), __.out("traverses")).where(__.loops().is(0))).times(1)).times(2).values("name")
+      """
+    When iterated to list
+      Then the result should be unordered
+        | result |
+        | tinkergraph |

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0b46fcd7/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
index 80c9332..b454c8c 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
@@ -37,6 +37,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.CREW;
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.SINK;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.both;
@@ -111,6 +112,8 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, String> get_g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values(final Object v3Id);
 
+    public abstract Traversal<Vertex, String> get_g_VX1X_repeatXrepeatXunionXout_uses_out_traversesXX_whereXloops_isX0X_timesX1X_timeX2X_name(final Object v1Id);
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_repeatXoutX_timesX2X_emit_path() {
@@ -397,6 +400,18 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
         assertFalse(traversal.hasNext());
     }
 
+    @Test
+    @LoadGraphWith(CREW)
+    public void g_VX1X_repeatXrepeatXunionXout_uses_out_traversesXX_whereXloops_isX0X_timesX1X_timeX2X_name() {
+        final Traversal<Vertex, String> traversal = get_g_VX1X_repeatXrepeatXunionXout_uses_out_traversesXX_whereXloops_isX0X_timesX1X_timeX2X_name(convertToVertexId("marko"));
+
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        String name = traversal.next();
+        assertEquals(name, "tinkergraph");
+
+        assertFalse(traversal.hasNext());
+    }
 
     public static class Traversals extends RepeatTest {
 
@@ -500,5 +515,10 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
         public Traversal<Vertex, String> get_g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values(final Object v3Id) {
             return g.V(v3Id).repeat( __.both("created")).until(loops().is(40)).emit(__.repeat(__.in("knows")).emit(loops().is(1))).dedup().values("name");
         }
+
+        @Override
+        public Traversal<Vertex, String> get_g_VX1X_repeatXrepeatXunionXout_uses_out_traversesXX_whereXloops_isX0X_timesX1X_timeX2X_name(final Object v1Id) {
+            return g.V(v1Id).repeat(__.repeat(__.union(out("uses"), out("traverses")).where(__.loops().is(0))).times(1)).times(2).values("name");
+        }
     }
 }


[09/11] tinkerpop git commit: Corrections to include hashCode(), use of primitive short and to docs

Posted by sp...@apache.org.
Corrections to include hashCode(), use of primitive short and to docs

Added missing fields to hashCode() in RepeatStep, B_O_S_SE_SL_Traverser and O_OB_S_SE_SL_Traverser and implemented hashCode() for LoopsStep.
Added missing tests to RepeatStepTest.
Correction to documentation to make sure sample query matches given description and some formatting of traversals.
Use primtive short in LabelledCounter rather than MutableShort.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/d5de5d82
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/d5de5d82
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/d5de5d82

Branch: refs/heads/master
Commit: d5de5d8281e86ae6495024d8430d3e85b15fcf9e
Parents: a80eb84
Author: GCHQResearcher1337 <39...@users.noreply.github.com>
Authored: Fri Jul 13 18:54:35 2018 +0100
Committer: GCHQResearcher1337 <39...@users.noreply.github.com>
Committed: Fri Jul 13 18:59:36 2018 +0100

----------------------------------------------------------------------
 docs/src/reference/the-traversal.asciidoc       | 10 ++++++--
 .../traversal/dsl/graph/GraphTraversal.java     |  4 ++--
 .../traversal/step/branch/RepeatStep.java       |  2 ++
 .../process/traversal/step/map/LoopsStep.java   | 19 ++++++++++++++++
 .../traverser/B_O_S_SE_SL_Traverser.java        |  9 ++++----
 .../traverser/O_OB_S_SE_SL_Traverser.java       | 10 +++++---
 .../traverser/util/LabelledCounter.java         | 24 +++++++++-----------
 .../gremlin/structure/io/gryo/GryoVersion.java  | 11 ++++-----
 .../traversal/step/branch/RepeatStepTest.java   |  4 +++-
 gremlin-test/features/branch/Repeat.feature     |  4 ++--
 .../traversal/step/branch/RepeatTest.java       | 10 ++++----
 11 files changed, 68 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d5de5d82/docs/src/reference/the-traversal.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index b565bae..1fb8abd 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -2129,8 +2129,14 @@ Therefore, the traverser has seen the vertices: lop, vadas, josh, ripple, and lo
 
 [gremlin-groovy,modern]
 ----
-g.V(1).repeat(out("knows")).until(__.repeat(out("created")).emit(__.has("name", "lop"))) <1>
-g.V(6).repeat('a', both('created')).emit(repeat('b', __.both('knows')).until(or(loops().is(2), loops('b').is(loops('a')))).hasId(2)).dedup() <2>
+g.V(1).
+  repeat(out("knows")).
+    until(repeat(out("created")).emit(has("name", "lop"))) <1>
+g.V(6).
+  repeat('a', both('created').simplePath()).
+    emit(repeat('b', both('knows')).
+           until(loops('b').as('b').where(loops('a').as('b'))).
+  hasId(2)).dedup() <2>
 ----
 
 <1> Starting from vertex 1, keep going taking outgoing 'knows' edges until the vertex was created by 'lop'.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d5de5d82/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 8684bfa..0a7eb95 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -2290,7 +2290,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     }
 
     /**
-     * This step is used for looping over a some traversal given some break predicate.
+     * This step is used for looping over a traversal given some break predicate.
      *
      * @param repeatTraversal the traversal to repeat over
      * @return the traversal with the appended {@link RepeatStep}
@@ -2303,7 +2303,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     }
 
     /**
-     * This step is used for looping over a some traversal given some break predicate.
+     * This step is used for looping over a traversal given some break predicate and with a specified loop name.
      *
      * @param repeatTraversal the traversal to repeat over
      * @param loopName The name given to the loop

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d5de5d82/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
index b95f1cd..f62b22c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
@@ -178,6 +178,8 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
         int result = super.hashCode() ^ this.repeatTraversal.hashCode();
         result ^= Boolean.hashCode(this.untilFirst);
         result ^= Boolean.hashCode(this.emitFirst) << 1;
+        if (this.loopName != null)
+            result ^= this.loopName.hashCode();
         if (this.untilTraversal != null)
             result ^= this.untilTraversal.hashCode();
         if (this.emitTraversal != null)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d5de5d82/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
index e95f26e..0a9167c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
@@ -37,4 +37,23 @@ public final class LoopsStep<S> extends MapStep<S, Integer> {
     protected Integer map(final Traverser.Admin<S> traverser) {
         return traverser.loops(this.loopName);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof LoopsStep)) return false;
+        if (!super.equals(o)) return false;
+
+        LoopsStep<?> loopsStep = (LoopsStep<?>) o;
+
+        return loopName != null ? loopName.equals(loopsStep.loopName) : loopsStep.loopName == null;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (loopName != null ? loopName.hashCode() : 0);
+        return result;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d5de5d82/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
index a6385a6..33c5520 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
@@ -18,12 +18,11 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.traverser;
 
-
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 
-import java.util.Random;
+import java.util.Objects;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -132,11 +131,13 @@ public class B_O_S_SE_SL_Traverser<T> extends B_O_Traverser<T> {
 
     @Override
     public int hashCode() {
-        return carriesUnmergeableSack() ? System.identityHashCode(this) : (super.hashCode() ^ this.loops);
+        return carriesUnmergeableSack() ? System.identityHashCode(this) : (super.hashCode() ^ this.loops ^ Objects.hashCode(this.loopName));
     }
 
     protected final boolean equals(final B_O_S_SE_SL_Traverser other) {
-        return super.equals(other) && other.loops == this.loops && !carriesUnmergeableSack();
+        return super.equals(other) && other.loops == this.loops
+                && (this.loopName != null ? this.loopName.equals(other.loopName) : other.loopName == null)
+                && !carriesUnmergeableSack();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d5de5d82/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java
index 6001a7b..601bcda 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java
@@ -23,6 +23,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 
+import java.util.Objects;
+
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
@@ -154,13 +156,15 @@ public class O_OB_S_SE_SL_Traverser<T> extends O_Traverser<T> {
 
     @Override
     public int hashCode() {
-        return carriesUnmergeableSack() ? System.identityHashCode(this) : (super.hashCode() ^ this.loops);
+        return carriesUnmergeableSack() ? System.identityHashCode(this) : (super.hashCode() ^ this.loops ^ Objects.hashCode(this.loopName));
     }
 
     protected  final boolean equals(final O_OB_S_SE_SL_Traverser other) {
-        return super.equals(other) && other.loops == this.loops && other.future.equals(this.future) &&
-                !carriesUnmergeableSack();
+        return super.equals(other) && other.loops == this.loops && other.future.equals(this.future)
+                && (this.loopName != null ? this.loopName.equals(other.loopName) : other.loopName == null)
+                && !carriesUnmergeableSack();
     }
+
     @Override
     public boolean equals(final Object object) {
         return object instanceof O_OB_S_SE_SL_Traverser && this.equals((O_OB_S_SE_SL_Traverser) object);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d5de5d82/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
index 8be43e3..0021699 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
@@ -19,8 +19,6 @@
 
 package org.apache.tinkerpop.gremlin.process.traversal.traverser.util;
 
-import org.apache.commons.lang.mutable.MutableShort;
-
 import java.io.Serializable;
 
 /**
@@ -29,7 +27,7 @@ import java.io.Serializable;
 public class LabelledCounter implements Serializable, Cloneable {
 
     private final String label;
-    private final MutableShort count = new MutableShort();
+    private short count = 0;
 
     protected LabelledCounter() {
         label = "";
@@ -40,7 +38,7 @@ public class LabelledCounter implements Serializable, Cloneable {
             throw new NullPointerException("Label is null");
         }
         this.label = label;
-        this.count.setValue(initialCount);
+        this.count = initialCount;
     }
 
     public boolean hasLabel(final String label){
@@ -48,38 +46,38 @@ public class LabelledCounter implements Serializable, Cloneable {
     }
 
     public int count() {
-        return this.count.intValue();
+        return this.count;
     }
 
     public void increment() {
-        this.count.increment();
+        this.count++;
     }
 
     @Override
     public Object clone() {
-        return new LabelledCounter(this.label, this.count.shortValue());
+        return new LabelledCounter(this.label, this.count);
     }
 
     @Override
     public String toString(){
-        return "Step Label: " + label + " Counter: " + count.toString();
+        return "Step Label: " + this.label + " Counter: " + Short.toString(this.count);
     }
 
     @Override
-    public boolean equals(final Object o) {
+    public boolean equals(Object o) {
         if (this == o) return true;
         if (!(o instanceof LabelledCounter)) return false;
 
         LabelledCounter that = (LabelledCounter) o;
 
-        if (!this.label.equals(that.label)) return false;
-        return this.count.equals(that.count);
+        if (count != that.count) return false;
+        return label != null ? label.equals(that.label) : that.label == null;
     }
 
     @Override
     public int hashCode() {
-        int result = this.label.hashCode();
-        result = 31 * result + this.count.hashCode();
+        int result = label != null ? label.hashCode() : 0;
+        result = 31 * result + (int) count;
         return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d5de5d82/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
index 6935549..e7dfd93 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
@@ -116,7 +116,6 @@ import org.apache.tinkerpop.shaded.kryo.KryoSerializable;
 import org.apache.tinkerpop.shaded.kryo.serializers.JavaSerializer;
 import org.javatuples.Pair;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
-import org.apache.commons.lang.mutable.MutableShort;
 import org.apache.commons.collections.map.ReferenceMap;
 import java.util.Stack;
 
@@ -393,9 +392,8 @@ public enum GryoVersion {
             add(GryoTypeReg.of(LP_NL_O_OB_S_SE_SL_Traverser.class, 178));
             add(GryoTypeReg.of(LP_NL_O_OB_P_S_SE_SL_Traverser.class, 179));
             add(GryoTypeReg.of(LabelledCounter.class, 180));
-            add(GryoTypeReg.of(MutableShort.class, 181));
-            add(GryoTypeReg.of(Stack.class, 182));
-            add(GryoTypeReg.of(ReferenceMap.class, 183));                        // ***LAST ID***
+            add(GryoTypeReg.of(Stack.class, 181));
+            add(GryoTypeReg.of(ReferenceMap.class, 182));                        // ***LAST ID***
 
 
             // placeholder serializers for classes that don't live here in core. this will allow them to be used if
@@ -584,9 +582,8 @@ public enum GryoVersion {
             add(GryoTypeReg.of(LP_NL_O_OB_S_SE_SL_Traverser.class, 178));
             add(GryoTypeReg.of(LP_NL_O_OB_P_S_SE_SL_Traverser.class, 179));
             add(GryoTypeReg.of(LabelledCounter.class, 180));
-            add(GryoTypeReg.of(MutableShort.class, 181));
-            add(GryoTypeReg.of(Stack.class, 182));
-            add(GryoTypeReg.of(ReferenceMap.class, 183));                        // ***LAST ID***
+            add(GryoTypeReg.of(Stack.class, 181));
+            add(GryoTypeReg.of(ReferenceMap.class, 182));                        // ***LAST ID***
         }};
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d5de5d82/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStepTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStepTest.java
index 6c86c27..1c6ae64 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStepTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStepTest.java
@@ -39,7 +39,9 @@ public class RepeatStepTest extends StepTest {
                 __.repeat(out()).times(3),
                 __.repeat(out().as("x")).times(3),
                 __.out().emit().repeat(out()).times(3),
-                __.repeat(out()).until(hasLabel("x"))
+                __.repeat(out()).until(hasLabel("x")),
+                __.repeat("a", __.out()).times(3),
+                __.repeat(out().repeat(out()).times(1)).times(1).limit(1)
         );
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d5de5d82/gremlin-test/features/branch/Repeat.feature
----------------------------------------------------------------------
diff --git a/gremlin-test/features/branch/Repeat.feature b/gremlin-test/features/branch/Repeat.feature
index b5dc6ce..33470d0 100644
--- a/gremlin-test/features/branch/Repeat.feature
+++ b/gremlin-test/features/branch/Repeat.feature
@@ -343,12 +343,12 @@ Scenario: g_V_repeatXa_outXknows_repeatXb_outXcreatedX_filterXloops_isX0XX_emit_
     | java |
     | java |
 
-Scenario: g_VX6X_repeatXa_bothXcreatedXX_emitXrepeatXb_bothXknowsXX_untilXorXloops_isX2X_loopsXbX_isXloopsXaXXXX_hasXname_vadasXX_dedup_name
+Scenario: g_VX6X_repeatXa_bothXcreatedX_simplePathX_emitXrepeatXb_bothXknowsXX_untilXloopsXbX_asXb_whereXloopsXaX_asXbX_hasXname_vadasXX_dedup_name
   Given the modern graph
   And using the parameter v6Id defined as "v[peter].id"
   And the traversal of
     """
-    g.V(v6Id).repeat("a", __.both("created")).emit(__.repeat("b", __.both("knows")).until(__.or(__.loops().is(2), __.loops("b").is(__.loops("a")))).has("name", "vadas")).dedup().values("name")
+    g.V(v6Id).repeat("a", __.both("created").simplePath()).emit(__.repeat("b", __.both("knows")).until(__.loops("b").as("b").where(__.loops("a").as("b"))).has("name", "vadas")).dedup().values("name")
     """
   When iterated to list
   Then the result should be unordered

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d5de5d82/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
index a43534c..e833acf 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
@@ -120,7 +120,7 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, String> get_g_V_emit_repeatXa_outXknows_filterXloops_isX0XX_lang();
 
-    public abstract Traversal<Vertex, String> get_g_VX6X_repeatXa_bothXcreatedXX_emitXrepeatXb_bothXknowsXX_untilXorXloops_isX2X_loopsXbX_isXloopsXaXXXX_hasXname_vadasXX_dedup_name(final Object v6Id);
+    public abstract Traversal<Vertex, String> get_g_VX6X_repeatXa_bothXcreatedX_simplePathX_emitXrepeatXb_bothXknowsXX_untilXloopsXbX_asXb_whereXloopsXaX_asXbX_hasXname_vadasXX_dedup_name(final Object v6Id);
 
     @Test
     @LoadGraphWith(MODERN)
@@ -446,8 +446,8 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_VX6X_repeatXa_bothXcreatedXX_emitXrepeatXb_bothXknowsXX_untilXorXloops_isX2X_loopsXbX_isXloopsXaXXXX_hasXname_vadasXX_dedup_name() {
-        final Traversal<Vertex, String> traversal = get_g_VX6X_repeatXa_bothXcreatedXX_emitXrepeatXb_bothXknowsXX_untilXorXloops_isX2X_loopsXbX_isXloopsXaXXXX_hasXname_vadasXX_dedup_name(convertToVertexId("peter"));
+    public void g_VX6X_repeatXa_bothXcreatedX_simplePathX_emitXrepeatXb_bothXknowsXX_untilXloopsXbX_asXb_whereXloopsXaX_asXbX_hasXname_vadasXX_dedup_name() {
+        final Traversal<Vertex, String> traversal = get_g_VX6X_repeatXa_bothXcreatedX_simplePathX_emitXrepeatXb_bothXknowsXX_untilXloopsXbX_asXb_whereXloopsXaX_asXbX_hasXname_vadasXX_dedup_name(convertToVertexId("peter"));
         printTraversalForm(traversal);
         assertTrue(traversal.hasNext());
         String name = traversal.next();
@@ -569,8 +569,8 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
         }
 
         @Override
-        public Traversal<Vertex, String> get_g_VX6X_repeatXa_bothXcreatedXX_emitXrepeatXb_bothXknowsXX_untilXorXloops_isX2X_loopsXbX_isXloopsXaXXXX_hasXname_vadasXX_dedup_name(final Object v6Id) {
-            return g.V(v6Id).repeat("a", both("created")).emit(__.repeat("b", __.both("knows")).until(__.or(loops().is(2), loops("b").is(loops("a")))).has("name", "vadas")).dedup().values("name");
+        public Traversal<Vertex, String> get_g_VX6X_repeatXa_bothXcreatedX_simplePathX_emitXrepeatXb_bothXknowsXX_untilXloopsXbX_asXb_whereXloopsXaX_asXbX_hasXname_vadasXX_dedup_name(final Object v6Id) {
+            return g.V(v6Id).repeat("a", both("created").simplePath()).emit(__.repeat("b", __.both("knows")).until(loops("b").as("b").where(loops("a").as("b"))).has("name", "vadas")).dedup().values("name");
         }
 
         @Override


[05/11] tinkerpop git commit: Correction to Nested Loop Traverser split function

Posted by sp...@apache.org.
Correction to Nested Loop Traverser split function

Added clone() method to LabelledCounter implementing the Cloneable interface.
Deep clone the loop stack when spliting a Nested Loop Traverer.
Added test which fails without this fix.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/3974b071
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/3974b071
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/3974b071

Branch: refs/heads/master
Commit: 3974b071d595b2f98b0d8e7080b1c5cbf6221949
Parents: ad35a6a
Author: GCHQResearcher1337 <39...@users.noreply.github.com>
Authored: Thu Jun 28 09:11:49 2018 +0100
Committer: GCHQResearcher1337 <39...@users.noreply.github.com>
Committed: Sat Jun 30 09:44:43 2018 +0100

----------------------------------------------------------------------
 .../B_LP_NL_O_P_S_SE_SL_Traverser.java          |  8 +++++--
 .../traverser/B_LP_NL_O_S_SE_SL_Traverser.java  |  8 +++++--
 .../traverser/B_NL_O_S_SE_SL_Traverser.java     |  8 +++++--
 .../LP_NL_O_OB_P_S_SE_SL_Traverser.java         |  8 +++++--
 .../traverser/LP_NL_O_OB_S_SE_SL_Traverser.java |  8 +++++--
 .../traverser/NL_O_OB_S_SE_SL_Traverser.java    |  8 +++++--
 .../traverser/util/LabelledCounter.java         |  7 +++++-
 gremlin-test/features/branch/Repeat.feature     | 14 ++++++++++++
 .../traversal/step/branch/RepeatTest.java       | 23 ++++++++++++++++++++
 9 files changed, 79 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
index c45e9a8..b837642 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
@@ -66,14 +66,18 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
     @Override
     public <R> Admin<R> split(final R r, final Step<T, R> step) {
         final B_LP_NL_O_P_S_SE_SL_Traverser<R> clone = (B_LP_NL_O_P_S_SE_SL_Traverser<R>) super.split(r, step);
-        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        clone.nestedLoops = new Stack<>();
+        for(LabelledCounter lc : this.nestedLoops)
+            clone.nestedLoops.add((LabelledCounter) lc.clone());
         return clone;
     }
 
     @Override
     public Admin<T> split() {
         final B_LP_NL_O_P_S_SE_SL_Traverser<T> clone = (B_LP_NL_O_P_S_SE_SL_Traverser<T>) super.split();
-        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        clone.nestedLoops = new Stack<>();
+        for(LabelledCounter lc : this.nestedLoops)
+            clone.nestedLoops.add((LabelledCounter) lc.clone());
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
index 3959dd7..a4bc1bd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
@@ -66,14 +66,18 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
     @Override
     public <R> Admin<R> split(final R r, final Step<T, R> step) {
         final B_LP_NL_O_S_SE_SL_Traverser<R> clone = (B_LP_NL_O_S_SE_SL_Traverser<R>) super.split(r, step);
-        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        clone.nestedLoops = new Stack<>();
+        for(LabelledCounter lc : this.nestedLoops)
+            clone.nestedLoops.add((LabelledCounter) lc.clone());
         return clone;
     }
 
     @Override
     public Admin<T> split() {
         final B_LP_NL_O_S_SE_SL_Traverser<T> clone = (B_LP_NL_O_S_SE_SL_Traverser<T>) super.split();
-        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        clone.nestedLoops = new Stack<>();
+        for(LabelledCounter lc : this.nestedLoops)
+            clone.nestedLoops.add((LabelledCounter) lc.clone());
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
index 11ce7fa..369448e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
@@ -66,14 +66,18 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
     @Override
     public <R> Admin<R> split(final R r, final Step<T, R> step) {
         final B_NL_O_S_SE_SL_Traverser<R> clone = (B_NL_O_S_SE_SL_Traverser<R>) super.split(r, step);
-        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        clone.nestedLoops = new Stack<>();
+        for(LabelledCounter lc : this.nestedLoops)
+            clone.nestedLoops.add((LabelledCounter) lc.clone());
         return clone;
     }
 
     @Override
     public Admin<T> split() {
         final B_NL_O_S_SE_SL_Traverser<T> clone = (B_NL_O_S_SE_SL_Traverser<T>) super.split();
-        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        clone.nestedLoops = new Stack<>();
+        for(LabelledCounter lc : this.nestedLoops)
+            clone.nestedLoops.add((LabelledCounter) lc.clone());
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
index f8b814f..2409e4a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
@@ -67,14 +67,18 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
     @Override
     public <R> Admin<R> split(final R r, final Step<T, R> step) {
         final LP_NL_O_OB_P_S_SE_SL_Traverser<R> clone = (LP_NL_O_OB_P_S_SE_SL_Traverser<R>) super.split(r, step);
-        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        clone.nestedLoops = new Stack<>();
+        for(LabelledCounter lc : this.nestedLoops)
+            clone.nestedLoops.add((LabelledCounter) lc.clone());
         return clone;
     }
 
     @Override
     public Admin<T> split() {
         final LP_NL_O_OB_P_S_SE_SL_Traverser<T> clone = (LP_NL_O_OB_P_S_SE_SL_Traverser<T>) super.split();
-        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        clone.nestedLoops = new Stack<>();
+        for(LabelledCounter lc : this.nestedLoops)
+            clone.nestedLoops.add((LabelledCounter) lc.clone());
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
index 9649f80..65fda97 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
@@ -67,14 +67,18 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
     @Override
     public <R> Admin<R> split(final R r, final Step<T, R> step) {
         final LP_NL_O_OB_S_SE_SL_Traverser<R> clone = (LP_NL_O_OB_S_SE_SL_Traverser<R>) super.split(r, step);
-        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        clone.nestedLoops = new Stack<>();
+        for(LabelledCounter lc : this.nestedLoops)
+            clone.nestedLoops.add((LabelledCounter) lc.clone());
         return clone;
     }
 
     @Override
     public Admin<T> split() {
         final LP_NL_O_OB_S_SE_SL_Traverser<T> clone = (LP_NL_O_OB_S_SE_SL_Traverser<T>) super.split();
-        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        clone.nestedLoops = new Stack<>();
+        for(LabelledCounter lc : this.nestedLoops)
+            clone.nestedLoops.add((LabelledCounter) lc.clone());
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
index 2734d51..3975758 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
@@ -67,14 +67,18 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
     @Override
     public <R> Admin<R> split(final R r, final Step<T, R> step) {
         final NL_O_OB_S_SE_SL_Traverser<R> clone = (NL_O_OB_S_SE_SL_Traverser<R>) super.split(r, step);
-        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        clone.nestedLoops = new Stack<>();
+        for(LabelledCounter lc : this.nestedLoops)
+            clone.nestedLoops.add((LabelledCounter) lc.clone());
         return clone;
     }
 
     @Override
     public Admin<T> split() {
         final NL_O_OB_S_SE_SL_Traverser<T> clone = (NL_O_OB_S_SE_SL_Traverser<T>) super.split();
-        clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone();
+        clone.nestedLoops = new Stack<>();
+        for(LabelledCounter lc : this.nestedLoops)
+            clone.nestedLoops.add((LabelledCounter) lc.clone());
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
index fe76891..a5214d2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
@@ -26,7 +26,7 @@ import java.io.Serializable;
 /**
  * Class to track a count associated with a Label
  */
-public class LabelledCounter implements Serializable {
+public class LabelledCounter implements Serializable, Cloneable {
 
     private final String label;
 
@@ -53,6 +53,11 @@ public class LabelledCounter implements Serializable {
     }
 
     @Override
+    public Object clone() {
+        return new LabelledCounter(this.label, this.count.shortValue());
+    }
+
+    @Override
     public boolean equals(final Object o) {
         if (this == o) return true;
         if (!(o instanceof LabelledCounter)) return false;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-test/features/branch/Repeat.feature
----------------------------------------------------------------------
diff --git a/gremlin-test/features/branch/Repeat.feature b/gremlin-test/features/branch/Repeat.feature
index b176477..c38fa1b 100644
--- a/gremlin-test/features/branch/Repeat.feature
+++ b/gremlin-test/features/branch/Repeat.feature
@@ -292,3 +292,17 @@ Scenario: g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_r
     | result |
     | java |
     | java |
+
+Scenario: g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values
+    Given the modern graph
+    And using the parameter v3Id defined as "v[lop].id"
+    And the traversal of
+      """
+      g.V(v3Id).repeat(__.both("created")).until(__.loops().is(40)).emit(__.repeat(__.in("knows")).emit(__.loops().is(1))).dedup().values("name")
+      """
+    When iterated to list
+      Then the result should be unordered
+        | result |
+        | josh |
+        | lop |
+        | ripple |

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
index d8da3fb..80c9332 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
@@ -109,6 +109,8 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, String> get_g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang();
 
+    public abstract Traversal<Vertex, String> get_g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values(final Object v3Id);
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_repeatXoutX_timesX2X_emit_path() {
@@ -379,6 +381,22 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
         assertFalse(traversal.hasNext());
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values() {
+        final Traversal<Vertex, String> traversal = get_g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values(convertToVertexId("lop"));
+
+        printTraversalForm(traversal);
+        for (String res :   new String[]{"josh","lop", "ripple"})
+        {
+            assertTrue(traversal.hasNext());
+            String lang = traversal.next();
+            assertEquals(lang, res);
+        }
+
+        assertFalse(traversal.hasNext());
+    }
+
 
     public static class Traversals extends RepeatTest {
 
@@ -477,5 +495,10 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
         public Traversal<Vertex, String> get_g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang() {
             return g.V().until(__.constant(true)).repeat(__.repeat(out("created")).until(__.has("name", "ripple"))).emit().values("lang");
         }
+
+        @Override
+        public Traversal<Vertex, String> get_g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values(final Object v3Id) {
+            return g.V(v3Id).repeat( __.both("created")).until(loops().is(40)).emit(__.repeat(__.in("knows")).emit(loops().is(1))).dedup().values("name");
+        }
     }
 }


[03/11] tinkerpop git commit: Nested Loop info added line to CHANGELOG and to release upgrade notes

Posted by sp...@apache.org.
Nested Loop info added line to CHANGELOG and to release upgrade notes


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/27da9b77
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/27da9b77
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/27da9b77

Branch: refs/heads/master
Commit: 27da9b7788d44ebc68e2af993aa2f3eeaafec357
Parents: a97d3ed
Author: GCHQResearcher1337 <39...@users.noreply.github.com>
Authored: Wed Jun 13 12:29:37 2018 +0100
Committer: GCHQResearcher1337 <39...@users.noreply.github.com>
Committed: Wed Jun 13 12:29:37 2018 +0100

----------------------------------------------------------------------
 CHANGELOG.asciidoc                      |  1 +
 docs/src/upgrade/release-3.4.x.asciidoc | 16 ++++++++++++++++
 2 files changed, 17 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/27da9b77/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index e886107..55ab169 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -37,6 +37,7 @@ This release also includes changes from <<release-3-3-3, 3.3.3>>.
 * Changed the order of `select()` scopes. The order is now: maps, side-effects, paths.
 * Removed previously deprecated Credentials DSL infrastructure.
 * Moved `TraversalEngine` to `gremlin-test` as it has long been only used in testing infrastructure.
+* Nested loop support added allowing `repeat()` steps to be nested.
 * Removed previously deprecated `OpSelectorHandler` constructor.
 * Removed previously deprecated `close()` from `GremlinGroovyScriptEngine` which no longer implements `AutoCloseable`.
 * Removed previously deprecated `getGraphInputFormat()` and `getGraphOutputFormat()` from `HadoopConfiguration`.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/27da9b77/docs/src/upgrade/release-3.4.x.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.4.x.asciidoc b/docs/src/upgrade/release-3.4.x.asciidoc
index 851d458..887ac38 100644
--- a/docs/src/upgrade/release-3.4.x.asciidoc
+++ b/docs/src/upgrade/release-3.4.x.asciidoc
@@ -113,6 +113,22 @@ gremlin> g.V().values('name').max()
 ==>vadas
 ----
 
+==== Nested loop support
+
+Traversals now support nesting of `repeat()` loops.
+
+These can now be used to repeat another traversal while in a looped context, either inside the body of a `repeat()` or in its step modifiers (`until()` or `emit()`).
+
+[source,groovy]
+----
+gremlin> g.V().repeat(__.in('traverses').repeat(__.in('develops')).emit()).emit().values('name')
+==>stephen
+==>matthias
+==>marko
+----
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-967[TINKERPOP-967]
+
 ==== Deprecation Removal
 
 The following deprecated classes, methods or fields have been removed in this version:


[02/11] tinkerpop git commit: Added final to parameters and style tweaks

Posted by sp...@apache.org.
Added final to parameters and style tweaks

Added missing final keywords to LabelledCounter.

Added 'this.' to generated code.

Corrected 'stack label' to 'step label' in comments.

Minor correction in comment


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/a97d3eda
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/a97d3eda
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/a97d3eda

Branch: refs/heads/master
Commit: a97d3edaae2fba293c6a5b5d43277214a2fb3a9a
Parents: 320c143
Author: GCHQResearcher1337 <39...@users.noreply.github.com>
Authored: Wed Jun 13 09:46:22 2018 +0100
Committer: GCHQResearcher1337 <39...@users.noreply.github.com>
Committed: Wed Jun 13 10:11:08 2018 +0100

----------------------------------------------------------------------
 .../traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java  |  8 ++++----
 .../traverser/B_LP_NL_O_S_SE_SL_Traverser.java    |  8 ++++----
 .../traverser/B_NL_O_S_SE_SL_Traverser.java       |  8 ++++----
 .../traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java |  8 ++++----
 .../traverser/LP_NL_O_OB_S_SE_SL_Traverser.java   |  8 ++++----
 .../traverser/NL_O_OB_S_SE_SL_Traverser.java      |  8 ++++----
 .../traversal/traverser/util/LabelledCounter.java | 18 +++++++++---------
 7 files changed, 33 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a97d3eda/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
index 3412965..c45e9a8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
@@ -44,7 +44,7 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
 
     @Override
     public void incrLoops(final String stepLabel) {
-        // If we encounter a new stack label then grow the stack otherwise increment the loop count
+        // If we encounter a new step label then grow the stack otherwise increment the loop count
         if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
             this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
         }
@@ -85,20 +85,20 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
     /////////////////
 
     @Override
-    public boolean equals(Object o) {
+    public boolean equals(final Object o) {
         if (this == o) return true;
         if (!(o instanceof B_LP_NL_O_P_S_SE_SL_Traverser)) return false;
         if (!super.equals(o)) return false;
 
         B_LP_NL_O_P_S_SE_SL_Traverser<?> that = (B_LP_NL_O_P_S_SE_SL_Traverser<?>) o;
 
-        return nestedLoops.equals(that.nestedLoops);
+        return this.nestedLoops.equals(that.nestedLoops);
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
-        result = 31 * result + nestedLoops.hashCode();
+        result = 31 * result + this.nestedLoops.hashCode();
         return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a97d3eda/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
index 250a1fd..3959dd7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
@@ -44,7 +44,7 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
 
     @Override
     public void incrLoops(final String stepLabel) {
-        // If we encounter a new stack label then grow the stack otherwise increment the loop count
+        // If we encounter a new step label then grow the stack otherwise increment the loop count
         if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
             this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
         }
@@ -85,20 +85,20 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
     /////////////////
 
     @Override
-    public boolean equals(Object o) {
+    public boolean equals(final Object o) {
         if (this == o) return true;
         if (!(o instanceof B_LP_NL_O_S_SE_SL_Traverser)) return false;
         if (!super.equals(o)) return false;
 
         B_LP_NL_O_S_SE_SL_Traverser<?> that = (B_LP_NL_O_S_SE_SL_Traverser<?>) o;
 
-        return nestedLoops.equals(that.nestedLoops);
+        return this.nestedLoops.equals(that.nestedLoops);
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
-        result = 31 * result + nestedLoops.hashCode();
+        result = 31 * result + this.nestedLoops.hashCode();
         return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a97d3eda/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
index 3018e22..11ce7fa 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
@@ -44,7 +44,7 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
 
     @Override
     public void incrLoops(final String stepLabel) {
-        // If we encounter a new stack label then grow the stack otherwise increment the loop count
+        // If we encounter a new step label then grow the stack otherwise increment the loop count
         if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
             this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
         }
@@ -85,20 +85,20 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
     /////////////////
 
     @Override
-    public boolean equals(Object o) {
+    public boolean equals(final Object o) {
         if (this == o) return true;
         if (!(o instanceof B_NL_O_S_SE_SL_Traverser)) return false;
         if (!super.equals(o)) return false;
 
         B_NL_O_S_SE_SL_Traverser<?> that = (B_NL_O_S_SE_SL_Traverser<?>) o;
 
-        return nestedLoops.equals(that.nestedLoops);
+        return this.nestedLoops.equals(that.nestedLoops);
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
-        result = 31 * result + nestedLoops.hashCode();
+        result = 31 * result + this.nestedLoops.hashCode();
         return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a97d3eda/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
index 3417864..f8b814f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
@@ -45,7 +45,7 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
 
     @Override
     public void incrLoops(final String stepLabel) {
-        // If we encounter a new stack label then grow the stack otherwise increment the loop count
+        // If we encounter a new step label then grow the stack otherwise increment the loop count
         if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
             this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
         }
@@ -86,20 +86,20 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
     /////////////////
 
     @Override
-    public boolean equals(Object o) {
+    public boolean equals(final Object o) {
         if (this == o) return true;
         if (!(o instanceof LP_NL_O_OB_P_S_SE_SL_Traverser)) return false;
         if (!super.equals(o)) return false;
 
         LP_NL_O_OB_P_S_SE_SL_Traverser<?> that = (LP_NL_O_OB_P_S_SE_SL_Traverser<?>) o;
 
-        return nestedLoops.equals(that.nestedLoops);
+        return this.nestedLoops.equals(that.nestedLoops);
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
-        result = 31 * result + nestedLoops.hashCode();
+        result = 31 * result + this.nestedLoops.hashCode();
         return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a97d3eda/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
index facd4f9..9649f80 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
@@ -45,7 +45,7 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
 
     @Override
     public void incrLoops(final String stepLabel) {
-        // If we encounter a new stack label then grow the stack otherwise increment the loop count
+        // If we encounter a new step label then grow the stack otherwise increment the loop count
         if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
             this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
         }
@@ -86,20 +86,20 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
     /////////////////
 
     @Override
-    public boolean equals(Object o) {
+    public boolean equals(final Object o) {
         if (this == o) return true;
         if (!(o instanceof LP_NL_O_OB_S_SE_SL_Traverser)) return false;
         if (!super.equals(o)) return false;
 
         LP_NL_O_OB_S_SE_SL_Traverser<?> that = (LP_NL_O_OB_S_SE_SL_Traverser<?>) o;
 
-        return nestedLoops.equals(that.nestedLoops);
+        return this.nestedLoops.equals(that.nestedLoops);
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
-        result = 31 * result + nestedLoops.hashCode();
+        result = 31 * result + this.nestedLoops.hashCode();
         return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a97d3eda/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
index d73dd19..2734d51 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
@@ -45,7 +45,7 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
 
     @Override
     public void incrLoops(final String stepLabel) {
-        // If we encounter a new stack label then grow the stack otherwise increment the loop count
+        // If we encounter a new step label then grow the stack otherwise increment the loop count
         if (this.nestedLoops.size() == 0 || !this.nestedLoops.peek().hasLabel(stepLabel)) {
             this.nestedLoops.add(new LabelledCounter(stepLabel, (short)1));
         }
@@ -86,20 +86,20 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
     /////////////////
 
     @Override
-    public boolean equals(Object o) {
+    public boolean equals(final Object o) {
         if (this == o) return true;
         if (!(o instanceof NL_O_OB_S_SE_SL_Traverser)) return false;
         if (!super.equals(o)) return false;
 
         NL_O_OB_S_SE_SL_Traverser<?> that = (NL_O_OB_S_SE_SL_Traverser<?>) o;
 
-        return nestedLoops.equals(that.nestedLoops);
+        return this.nestedLoops.equals(that.nestedLoops);
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
-        result = 31 * result + nestedLoops.hashCode();
+        result = 31 * result + this.nestedLoops.hashCode();
         return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a97d3eda/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
index bc07487..fe76891 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
@@ -28,11 +28,11 @@ import java.io.Serializable;
  */
 public class LabelledCounter implements Serializable {
 
-    private String label;
+    private final String label;
 
-    private MutableShort count;
+    private final MutableShort count;
 
-    public LabelledCounter(String label, short initialCount) {
+    public LabelledCounter(final String label, final short initialCount) {
         if (label == null) {
             throw new NullPointerException("Label is null");
         }
@@ -40,7 +40,7 @@ public class LabelledCounter implements Serializable {
         this.count = new MutableShort(initialCount);
     }
 
-    public boolean hasLabel(String label){
+    public boolean hasLabel(final String label){
         return this.label.equals(label);
     }
 
@@ -53,20 +53,20 @@ public class LabelledCounter implements Serializable {
     }
 
     @Override
-    public boolean equals(Object o) {
+    public boolean equals(final Object o) {
         if (this == o) return true;
         if (!(o instanceof LabelledCounter)) return false;
 
         LabelledCounter that = (LabelledCounter) o;
 
-        if (!label.equals(that.label)) return false;
-        return count.equals(that.count);
+        if (!this.label.equals(that.label)) return false;
+        return this.count.equals(that.count);
     }
 
     @Override
     public int hashCode() {
-        int result = label.hashCode();
-        result = 31 * result + count.hashCode();
+        int result = this.label.hashCode();
+        result = 31 * result + this.count.hashCode();
         return result;
     }
 }


[08/11] tinkerpop git commit: Named Loops - Allows the user to name a repeat loop and to then access a named loop counter.

Posted by sp...@apache.org.
Named Loops - Allows the user to name a repeat loop and to then access a named loop counter.

Changes to the LoopStep to allow the loop name to be passed.
Throw IllegalArgumentException if the loop name is not defined.
Map of loop names to loop Stack held in ReferenceMap.
Documentation updated with usage.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/a80eb841
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/a80eb841
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/a80eb841

Branch: refs/heads/master
Commit: a80eb84169048ed74c5ad27ebc4d12944fd0136a
Parents: 0b46fcd
Author: GCHQResearcher1337 <39...@users.noreply.github.com>
Authored: Fri Jul 6 15:43:06 2018 +0100
Committer: GCHQResearcher1337 <39...@users.noreply.github.com>
Committed: Fri Jul 6 15:57:51 2018 +0100

----------------------------------------------------------------------
 docs/src/reference/the-traversal.asciidoc       | 11 ++++
 .../gremlin/process/traversal/Traverser.java    | 13 +++-
 .../traversal/dsl/graph/GraphTraversal.java     | 30 ++++++++-
 .../gremlin/process/traversal/dsl/graph/__.java | 14 +++++
 .../traversal/step/branch/RepeatStep.java       | 17 ++++-
 .../process/traversal/step/map/LoopsStep.java   |  7 ++-
 .../B_LP_NL_O_P_S_SE_SL_Traverser.java          | 59 ++++++++++++++++--
 .../traverser/B_LP_NL_O_S_SE_SL_Traverser.java  | 58 +++++++++++++++--
 .../traverser/B_NL_O_S_SE_SL_Traverser.java     | 61 ++++++++++++++++--
 .../traverser/B_O_S_SE_SL_Traverser.java        | 15 ++++-
 .../LP_NL_O_OB_P_S_SE_SL_Traverser.java         | 58 +++++++++++++++--
 .../traverser/LP_NL_O_OB_S_SE_SL_Traverser.java | 60 ++++++++++++++++--
 .../traverser/NL_O_OB_S_SE_SL_Traverser.java    | 60 ++++++++++++++++--
 .../traverser/O_OB_S_SE_SL_Traverser.java       | 14 +++++
 .../traversal/traverser/ProjectedTraverser.java |  9 ++-
 .../traverser/util/AbstractTraverser.java       |  7 ++-
 .../traverser/util/EmptyTraverser.java          |  7 ++-
 .../traverser/util/LabelledCounter.java         |  7 ++-
 .../gremlin/structure/io/gryo/GryoVersion.java  |  7 ++-
 .../Process/Traversal/GraphTraversal.cs         | 18 ++++++
 .../src/Gremlin.Net/Process/Traversal/__.cs     | 16 +++++
 gremlin-test/features/branch/Repeat.feature     | 36 +++++++++++
 .../traversal/step/branch/RepeatTest.java       | 65 ++++++++++++++++++--
 23 files changed, 604 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/docs/src/reference/the-traversal.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index f845cd3..b565bae 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -2125,6 +2125,17 @@ traverser repeats. However, because the emit-predicate is declared true, those v
   Given that `loops==2`, the until-predicate fails and ripple and lop are emitted.
 Therefore, the traverser has seen the vertices: lop, vadas, josh, ripple, and lop.
 
+`repeat()`-steps may be nested inside each other or inside the `emit()` or `until()` predicates and they can also be 'named' by passing a string as the first parameter to `repeat()`. The loop counter of a named repeat step can be accessed within the looped context with `loops(loopName)` where `loopName` is the name set whe creating the `repeat()`-step.
+
+[gremlin-groovy,modern]
+----
+g.V(1).repeat(out("knows")).until(__.repeat(out("created")).emit(__.has("name", "lop"))) <1>
+g.V(6).repeat('a', both('created')).emit(repeat('b', __.both('knows')).until(or(loops().is(2), loops('b').is(loops('a')))).hasId(2)).dedup() <2>
+----
+
+<1> Starting from vertex 1, keep going taking outgoing 'knows' edges until the vertex was created by 'lop'.
+<2> Starting from vertex 6, keep taking created edges in either direction until the vertex is same distance from vertex 2 over knows edges as it is from vertex 6 over created edges.
+
 Finally, note that both `emit()` and `until()` can take a traversal and in such, situations, the predicate is
 determined by `traversal.hasNext()`. A few examples are provided below.
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
index 5fed40b..e07bec1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
@@ -89,6 +89,15 @@ public interface Traverser<T> extends Serializable, Comparable<Traverser<T>>, Cl
     public int loops();
 
     /**
+     * Return the number of times the traverser has gone through the named looping section of a traversal.
+     *
+     * @param loopName the name applied to the loop or null for the containing loop
+     * @return The number of times the traverser has gone through a loop
+     * @throws IllegalArgumentException if the loopName is not defined
+     */
+    public int loops(final String loopName);
+
+    /**
      * A traverser may represent a grouping of traversers to allow for more efficient data propagation.
      *
      * @return the number of traversers represented in this traverser.
@@ -216,10 +225,12 @@ public interface Traverser<T> extends Serializable, Comparable<Traverser<T>>, Cl
          * Initialise a loop by setting up the looping construct.
          * The step label is important to create a stack of loop counters when within a nested context.
          * If the provided label is not the same as the current label on the stack, add a new loop counter.
+         * The loopName can be used to refer to the loops counter via the {@link LoopsStep}
          *
          * @param stepLabel the label of the step that is being set-up.
+         * @param loopName the user defined name for referencing the loop counter or null if not set
          */
-        public void initialiseLoops(final String stepLabel);
+        public void initialiseLoops(final String stepLabel, final String loopName);
 
         /**
          * Increment the number of times the traverser has gone through a looping section of traversal.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 7d1e7e4..8684bfa 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -647,7 +647,20 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
      */
     public default GraphTraversal<S, Integer> loops() {
         this.asAdmin().getBytecode().addStep(Symbols.loops);
-        return this.asAdmin().addStep(new LoopsStep<>(this.asAdmin()));
+        return this.asAdmin().addStep(new LoopsStep<>(this.asAdmin(), null));
+    }
+
+    /**
+     * If the {@link Traverser} supports looping then calling this method will extract the number of loops for that
+     * traverser for the named loop.
+     *
+     * @return the traversal with an appended {@link LoopsStep}
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#loops-step" target="_blank">Reference Documentation - Loops Step</a>
+     * @since 3.4.0
+     */
+    public default GraphTraversal<S, Integer> loops(String loopName) {
+        this.asAdmin().getBytecode().addStep(Symbols.loops, loopName);
+        return this.asAdmin().addStep(new LoopsStep<>(this.asAdmin(), loopName));
     }
 
     /**
@@ -2290,6 +2303,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     }
 
     /**
+     * This step is used for looping over a some traversal given some break predicate.
+     *
+     * @param repeatTraversal the traversal to repeat over
+     * @param loopName The name given to the loop
+     * @return the traversal with the appended {@link RepeatStep}
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#repeat-step" target="_blank">Reference Documentation - Repeat Step</a>
+     * @since 3.4.0
+     */
+    public default GraphTraversal<S, E> repeat(final String loopName, final Traversal<?, E> repeatTraversal) {
+        this.asAdmin().getBytecode().addStep(Symbols.repeat, loopName, repeatTraversal);
+        return RepeatStep.addRepeatToTraversal(this, loopName, (Traversal.Admin<E, E>) repeatTraversal);
+    }
+
+
+    /**
      * Emit is used in conjunction with {@link #repeat(Traversal)} to determine what objects get emit from the loop.
      *
      * @param emitTraversal the emit predicate defined as a traversal

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index 2c73ce1..ae5c829 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -324,6 +324,13 @@ public class __ {
     }
 
     /**
+     * @see GraphTraversal#loops(String)
+     */
+    public static <A> GraphTraversal<A, Integer> loops(String loopName) {
+        return __.<A>start().loops(loopName);
+    }
+
+    /**
      * @see GraphTraversal#select(Pop, String)
      */
     public static <A, B> GraphTraversal<A, B> select(final Pop pop, final String selectKey) {
@@ -1030,6 +1037,13 @@ public class __ {
     }
 
     /**
+     * @see GraphTraversal#repeat(Traversal)
+     */
+    public static <A> GraphTraversal<A, A> repeat(final String loopName, final Traversal<?, A> traversal) {
+        return __.<A>start().repeat(loopName, traversal);
+    }
+
+    /**
      * @see GraphTraversal#emit(Traversal)
      */
     public static <A> GraphTraversal<A, A> emit(final Traversal<?, ?> emitTraversal) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
index ad949f8..b95f1cd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
@@ -43,6 +43,7 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
     private Traversal.Admin<S, S> repeatTraversal = null;
     private Traversal.Admin<S, ?> untilTraversal = null;
     private Traversal.Admin<S, ?> emitTraversal = null;
+    private String loopName = null;
     public boolean untilFirst = false;
     public boolean emitFirst = false;
 
@@ -68,6 +69,11 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
         this.integrateChild(this.repeatTraversal);
     }
 
+
+    public void setLoopName(final String loopName) {
+        this.loopName = loopName;
+    }
+
     public void setUntilTraversal(final Traversal.Admin<S, ?> untilTraversal) {
         if (null != this.untilTraversal)
             throw new IllegalStateException("The repeat()-step already has its until()-modulator declared: " + this);
@@ -189,7 +195,7 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
                 return this.repeatTraversal.getEndStep();
             } else {
                 final Traverser.Admin<S> start = this.starts.next();
-                start.initialiseLoops(this.getId());
+                start.initialiseLoops(this.getId(), this.loopName);
                 if (doUntil(start, true)) {
                     start.resetLoops();
                     return IteratorUtils.of(start);
@@ -216,7 +222,7 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
             return IteratorUtils.of(start);
         } else {
             start.setStepId(this.repeatTraversal.getStartStep().getId());
-            start.initialiseLoops(start.getStepId());
+            start.initialiseLoops(start.getStepId(), this.loopName);
             if (doEmit(start, true)) {
                 final Traverser.Admin<S> emitSplit = start.split();
                 emitSplit.resetLoops();
@@ -242,6 +248,13 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
         return traversal;
     }
 
+    public static <A, B, C extends Traversal<A, B>> C addRepeatToTraversal(final C traversal, final String loopName, final Traversal.Admin<B, B> repeatTraversal) {
+        addRepeatToTraversal(traversal, repeatTraversal);
+        final Step<?, B> step = traversal.asAdmin().getEndStep();
+        ((RepeatStep) step).setLoopName(loopName);
+        return traversal;
+    }
+
     public static <A, B, C extends Traversal<A, B>> C addUntilToTraversal(final C traversal, final Traversal.Admin<B, ?> untilPredicate) {
         final Step<?, B> step = traversal.asAdmin().getEndStep();
         if (step instanceof RepeatStep && null == ((RepeatStep) step).untilTraversal) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
index 2db9ab9..e95f26e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
@@ -26,12 +26,15 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
  */
 public final class LoopsStep<S> extends MapStep<S, Integer> {
 
-    public LoopsStep(final Traversal.Admin traversal) {
+    private String loopName;
+
+    public LoopsStep(final Traversal.Admin traversal, final String loopName) {
         super(traversal);
+        this.loopName = loopName;
     }
 
     @Override
     protected Integer map(final Traverser.Admin<S> traverser) {
-        return traverser.loops();
+        return traverser.loops(this.loopName);
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
index 380eb9f..04ba98a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java
@@ -18,14 +18,18 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.traverser;
 
+import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
 
+
+import java.util.Iterator;
 import java.util.Stack;
 
 public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser<T> {
 
     protected Stack<LabelledCounter> nestedLoops;
+    protected ReferenceMap loopNames = null;
 
     protected B_LP_NL_O_P_S_SE_SL_Traverser() {
     }
@@ -33,6 +37,7 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
     public B_LP_NL_O_P_S_SE_SL_Traverser(final T t, final Step<T, ?> step, final long initialBulk) {
         super(t, step, initialBulk);
         this.nestedLoops = new Stack<>();
+        this.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
     }
 
     /////////////////
@@ -43,9 +48,23 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
     }
 
     @Override
-    public void initialiseLoops(final String stepLabel) {
-        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel))
-            this.nestedLoops.push(new LabelledCounter(stepLabel, (short)0));
+    public int loops(final String loopName) {
+        if (loopName == null)
+            return loops();
+        else if (this.loopNames.containsKey(loopName))
+            return ((LabelledCounter) this.loopNames.get(loopName)).count();
+        else
+            throw new IllegalArgumentException("Loop name not defined: " + loopName);
+    }
+
+    @Override
+    public void initialiseLoops(final String stepLabel, final String loopName) {
+        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) {
+            LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
+            this.nestedLoops.push(lc);
+            if (loopName != null)
+                this.loopNames.put(loopName, lc);
+        }
     }
 
     @Override
@@ -66,6 +85,20 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
             clone.nestedLoops.push((LabelledCounter) lc.clone());
+
+        if (this.loopNames != null) {
+            clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            while (loopNamesIterator.hasNext()) {
+                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+
+                int idx = this.nestedLoops.indexOf(pair.getValue());
+                if (idx != -1)
+                    clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
+            }
+        }
+
         return clone;
     }
 
@@ -75,6 +108,20 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
             clone.nestedLoops.push((LabelledCounter) lc.clone());
+
+        if (this.loopNames != null) {
+            clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            while (loopNamesIterator.hasNext()) {
+                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+
+                int idx = this.nestedLoops.indexOf(pair.getValue());
+                if (idx != -1)
+                    clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
+            }
+        }
+
         return clone;
     }
 
@@ -93,13 +140,17 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser
 
         B_LP_NL_O_P_S_SE_SL_Traverser<?> that = (B_LP_NL_O_P_S_SE_SL_Traverser<?>) o;
 
-        return this.nestedLoops.equals(that.nestedLoops);
+        if (!this.nestedLoops.equals(that.nestedLoops)) return false;
+        return this.loopNames != null ? this.loopNames.equals(that.loopNames) : that.loopNames == null;
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
         result = 31 * result + this.nestedLoops.hashCode();
+        result = 31 * result + (this.loopNames != null ? this.loopNames.hashCode() : 0);
+
         return result;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
index aa3e9b0..8ddd9fc 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java
@@ -18,14 +18,17 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.traverser;
 
+import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
 
+import java.util.Iterator;
 import java.util.Stack;
 
 public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T> {
 
     protected Stack<LabelledCounter> nestedLoops;
+    protected ReferenceMap loopNames = null;
 
     protected B_LP_NL_O_S_SE_SL_Traverser() {
     }
@@ -33,6 +36,7 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
     public B_LP_NL_O_S_SE_SL_Traverser(final T t, final Step<T, ?> step, final long initialBulk) {
         super(t, step, initialBulk);
         this.nestedLoops = new Stack<>();
+        this.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
     }
 
     /////////////////
@@ -43,9 +47,23 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
     }
 
     @Override
-    public void initialiseLoops(final String stepLabel) {
-        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel))
-            this.nestedLoops.push(new LabelledCounter(stepLabel, (short)0));
+    public int loops(final String loopName) {
+        if (loopName == null)
+            return loops();
+        else if (this.loopNames.containsKey(loopName))
+            return ((LabelledCounter) this.loopNames.get(loopName)).count();
+        else
+            throw new IllegalArgumentException("Loop name not defined: " + loopName);
+    }
+
+    @Override
+    public void initialiseLoops(final String stepLabel, final String loopName) {
+        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) {
+            LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
+            this.nestedLoops.push(lc);
+            if (loopName != null)
+                this.loopNames.put(loopName, lc);
+        }
     }
 
     @Override
@@ -66,6 +84,20 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
             clone.nestedLoops.push((LabelledCounter) lc.clone());
+
+        if (this.loopNames != null) {
+            clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            while (loopNamesIterator.hasNext()) {
+                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+
+                int idx = this.nestedLoops.indexOf(pair.getValue());
+                if (idx != -1)
+                    clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
+            }
+        }
+
         return clone;
     }
 
@@ -75,6 +107,20 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
             clone.nestedLoops.push((LabelledCounter) lc.clone());
+
+        if (this.loopNames != null) {
+            clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            while (loopNamesIterator.hasNext()) {
+                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+
+                int idx = this.nestedLoops.indexOf(pair.getValue());
+                if (idx != -1)
+                    clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
+            }
+        }
+
         return clone;
     }
 
@@ -93,13 +139,17 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T>
 
         B_LP_NL_O_S_SE_SL_Traverser<?> that = (B_LP_NL_O_S_SE_SL_Traverser<?>) o;
 
-        return this.nestedLoops.equals(that.nestedLoops);
+        if (!this.nestedLoops.equals(that.nestedLoops)) return false;
+        return this.loopNames != null ? this.loopNames.equals(that.loopNames) : that.loopNames == null;
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
         result = 31 * result + this.nestedLoops.hashCode();
+        result = 31 * result + (this.loopNames != null ? this.loopNames.hashCode() : 0);
+
         return result;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
index 8d5d7dd..0eee799 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java
@@ -18,14 +18,18 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.traverser;
 
+import org.apache.commons.collections.MapIterator;
+import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
 
+import java.util.Iterator;
 import java.util.Stack;
 
 public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
 
     protected Stack<LabelledCounter> nestedLoops;
+    protected ReferenceMap loopNames = null;
 
     protected B_NL_O_S_SE_SL_Traverser() {
     }
@@ -33,6 +37,7 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
     public B_NL_O_S_SE_SL_Traverser(final T t, final Step<T, ?> step, final long initialBulk) {
         super(t, step, initialBulk);
         this.nestedLoops = new Stack<>();
+        this.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
     }
 
     /////////////////
@@ -43,9 +48,23 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
     }
 
     @Override
-    public void initialiseLoops(final String stepLabel) {
-        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel))
-            this.nestedLoops.push(new LabelledCounter(stepLabel, (short)0));
+    public int loops(final String loopName) {
+        if (loopName == null)
+            return loops();
+        else if (this.loopNames.containsKey(loopName))
+            return ((LabelledCounter) this.loopNames.get(loopName)).count();
+        else
+            throw new IllegalArgumentException("Loop name not defined: " + loopName);
+    }
+
+    @Override
+    public void initialiseLoops(final String stepLabel, final String loopName) {
+        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) {
+            LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
+            this.nestedLoops.push(lc);
+            if (loopName != null)
+                this.loopNames.put(loopName, lc);
+        }
     }
 
     @Override
@@ -63,18 +82,48 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
     @Override
     public <R> Admin<R> split(final R r, final Step<T, R> step) {
         final B_NL_O_S_SE_SL_Traverser<R> clone = (B_NL_O_S_SE_SL_Traverser<R>) super.split(r, step);
+
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
             clone.nestedLoops.push((LabelledCounter) lc.clone());
+
+        if (this.loopNames != null) {
+            clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            while (loopNamesIterator.hasNext()) {
+                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+
+                int idx = this.nestedLoops.indexOf(pair.getValue());
+                if (idx != -1)
+                    clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
+            }
+        }
+
         return clone;
     }
 
     @Override
     public Admin<T> split() {
         final B_NL_O_S_SE_SL_Traverser<T> clone = (B_NL_O_S_SE_SL_Traverser<T>) super.split();
+
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
             clone.nestedLoops.push((LabelledCounter) lc.clone());
+
+        if (this.loopNames != null) {
+            clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            while (loopNamesIterator.hasNext()) {
+                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+
+                int idx = this.nestedLoops.indexOf(pair.getValue());
+                if (idx != -1)
+                    clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
+            }
+        }
+
         return clone;
     }
 
@@ -93,13 +142,17 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
 
         B_NL_O_S_SE_SL_Traverser<?> that = (B_NL_O_S_SE_SL_Traverser<?>) o;
 
-        return this.nestedLoops.equals(that.nestedLoops);
+        if (!this.nestedLoops.equals(that.nestedLoops)) return false;
+        return this.loopNames != null ? this.loopNames.equals(that.loopNames) : that.loopNames == null;
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
         result = 31 * result + this.nestedLoops.hashCode();
+        result = 31 * result + (this.loopNames != null ? this.loopNames.hashCode() : 0);
+
         return result;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
index d184b7e..a6385a6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
@@ -32,6 +32,7 @@ public class B_O_S_SE_SL_Traverser<T> extends B_O_Traverser<T> {
 
     protected Object sack = null;
     protected short loops = 0;  // an optimization hack to use a short internally to save bits :)
+    protected String loopName = null;
     protected transient TraversalSideEffects sideEffects;
 
     protected B_O_S_SE_SL_Traverser() {
@@ -64,6 +65,19 @@ public class B_O_S_SE_SL_Traverser<T> extends B_O_Traverser<T> {
     }
 
     @Override
+    public int loops(final String loopName) {
+        if (loopName == null || this.loopName != null && this.loopName.equals(loopName))
+            return this.loops;
+        else
+            throw new IllegalArgumentException("Loop name not defined: " + loopName);
+    }
+
+    @Override
+    public void initialiseLoops(final String stepLabel , final String loopName){
+        this.loopName = loopName;
+    }
+
+    @Override
     public void incrLoops() {
         this.loops++;
     }
@@ -80,7 +94,6 @@ public class B_O_S_SE_SL_Traverser<T> extends B_O_Traverser<T> {
         return this.sideEffects;
     }
 
-
     @Override
     public void setSideEffects(final TraversalSideEffects sideEffects) {
         this.sideEffects = sideEffects;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
index 7fcaa2a..c7b42c6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java
@@ -19,14 +19,17 @@
 
 package org.apache.tinkerpop.gremlin.process.traversal.traverser;
 
+import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
 
+import java.util.Iterator;
 import java.util.Stack;
 
 public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Traverser<T> {
 
     protected Stack<LabelledCounter> nestedLoops;
+    protected ReferenceMap loopNames = null;
 
     protected LP_NL_O_OB_P_S_SE_SL_Traverser() {
     }
@@ -34,6 +37,7 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
     public LP_NL_O_OB_P_S_SE_SL_Traverser(final T t, final Step<T, ?> step) {
         super(t, step);
         this.nestedLoops = new Stack<>();
+        this.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
     }
 
     /////////////////
@@ -44,9 +48,23 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
     }
 
     @Override
-    public void initialiseLoops(final String stepLabel) {
-        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel))
-            this.nestedLoops.push(new LabelledCounter(stepLabel, (short)0));
+    public int loops(final String loopName) {
+        if (loopName == null)
+            return loops();
+        else if (this.loopNames.containsKey(loopName))
+            return ((LabelledCounter) this.loopNames.get(loopName)).count();
+        else
+            throw new IllegalArgumentException("Loop name not defined: " + loopName);
+    }
+
+    @Override
+    public void initialiseLoops(final String stepLabel, final String loopName) {
+        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) {
+            LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
+            this.nestedLoops.push(lc);
+            if (loopName != null)
+                this.loopNames.put(loopName, lc);
+        }
     }
 
     @Override
@@ -67,6 +85,20 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
             clone.nestedLoops.push((LabelledCounter) lc.clone());
+
+        if (this.loopNames != null) {
+            clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            while (loopNamesIterator.hasNext()) {
+                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+
+                int idx = this.nestedLoops.indexOf(pair.getValue());
+                if (idx != -1)
+                    clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
+            }
+        }
+
         return clone;
     }
 
@@ -76,6 +108,20 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
             clone.nestedLoops.push((LabelledCounter) lc.clone());
+
+        if (this.loopNames != null) {
+            clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            while (loopNamesIterator.hasNext()) {
+                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+
+                int idx = this.nestedLoops.indexOf(pair.getValue());
+                if (idx != -1)
+                    clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
+            }
+        }
+
         return clone;
     }
 
@@ -94,13 +140,17 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers
 
         LP_NL_O_OB_P_S_SE_SL_Traverser<?> that = (LP_NL_O_OB_P_S_SE_SL_Traverser<?>) o;
 
-        return this.nestedLoops.equals(that.nestedLoops);
+        if (!this.nestedLoops.equals(that.nestedLoops)) return false;
+        return this.loopNames != null ? this.loopNames.equals(that.loopNames) : that.loopNames == null;
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
         result = 31 * result + this.nestedLoops.hashCode();
+        result = 31 * result + (this.loopNames != null ? this.loopNames.hashCode() : 0);
+
         return result;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
index 92eb991..7e61841 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java
@@ -19,14 +19,17 @@
 
 package org.apache.tinkerpop.gremlin.process.traversal.traverser;
 
+import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
 
+import java.util.Iterator;
 import java.util.Stack;
 
 public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T> {
 
     protected Stack<LabelledCounter> nestedLoops;
+    protected ReferenceMap loopNames = null;
 
     protected LP_NL_O_OB_S_SE_SL_Traverser() {
     }
@@ -34,19 +37,34 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
     public LP_NL_O_OB_S_SE_SL_Traverser(final T t, final Step<T, ?> step) {
         super(t, step);
         this.nestedLoops = new Stack<>();
+        this.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
     }
 
     /////////////////
 
     @Override
     public int loops() {
-        return this.nestedLoops.size() > 0 ? this.nestedLoops.peek().count() : 0;
+        return this.nestedLoops.peek().count();
     }
 
     @Override
-    public void initialiseLoops(final String stepLabel) {
-        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel))
-            this.nestedLoops.push(new LabelledCounter(stepLabel, (short)0));
+    public int loops(final String loopName) {
+        if (loopName == null)
+            return loops();
+        else if (this.loopNames.containsKey(loopName))
+            return ((LabelledCounter) this.loopNames.get(loopName)).count();
+        else
+            throw new IllegalArgumentException("Loop name not defined: " + loopName);
+    }
+
+    @Override
+    public void initialiseLoops(final String stepLabel, final String loopName) {
+        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) {
+            LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
+            this.nestedLoops.push(lc);
+            if (loopName != null)
+                this.loopNames.put(loopName, lc);
+        }
     }
 
     @Override
@@ -67,6 +85,20 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
             clone.nestedLoops.push((LabelledCounter) lc.clone());
+
+        if (this.loopNames != null) {
+            clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            while (loopNamesIterator.hasNext()) {
+                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+
+                int idx = this.nestedLoops.indexOf(pair.getValue());
+                if (idx != -1)
+                    clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
+            }
+        }
+
         return clone;
     }
 
@@ -76,6 +108,20 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
             clone.nestedLoops.push((LabelledCounter) lc.clone());
+
+        if (this.loopNames != null) {
+            clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            while (loopNamesIterator.hasNext()) {
+                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+
+                int idx = this.nestedLoops.indexOf(pair.getValue());
+                if (idx != -1)
+                    clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
+            }
+        }
+
         return clone;
     }
 
@@ -94,13 +140,17 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T
 
         LP_NL_O_OB_S_SE_SL_Traverser<?> that = (LP_NL_O_OB_S_SE_SL_Traverser<?>) o;
 
-        return this.nestedLoops.equals(that.nestedLoops);
+        if (!this.nestedLoops.equals(that.nestedLoops)) return false;
+        return this.loopNames != null ? this.loopNames.equals(that.loopNames) : that.loopNames == null;
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
         result = 31 * result + this.nestedLoops.hashCode();
+        result = 31 * result + (this.loopNames != null ? this.loopNames.hashCode() : 0);
+
         return result;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
index 31e93fe..9bbd94a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java
@@ -19,21 +19,25 @@
 
 package org.apache.tinkerpop.gremlin.process.traversal.traverser;
 
+import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
 
+import java.util.Iterator;
 import java.util.Stack;
 
 public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
 
     protected Stack<LabelledCounter> nestedLoops;
-
+    protected ReferenceMap loopNames;
 
     protected NL_O_OB_S_SE_SL_Traverser() {
     }
 
     public NL_O_OB_S_SE_SL_Traverser(final T t, final Step<T, ?> step) {
         super(t, step);
+        this.nestedLoops = new Stack<>();
+        this.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
     }
 
     /////////////////
@@ -44,9 +48,23 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
     }
 
     @Override
-    public void initialiseLoops(final String stepLabel) {
-        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel))
-            this.nestedLoops.push(new LabelledCounter(stepLabel, (short)0));
+    public int loops(final String loopName) {
+        if (loopName == null)
+            return loops();
+        else if (this.loopNames.containsKey(loopName))
+            return ((LabelledCounter) this.loopNames.get(loopName)).count();
+        else
+            throw new IllegalArgumentException("Loop name not defined: " + loopName);
+    }
+
+    @Override
+    public void initialiseLoops(final String stepLabel, final String loopName) {
+        if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) {
+            LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0);
+            this.nestedLoops.push(lc);
+            if (loopName != null)
+                this.loopNames.put(loopName, lc);
+        }
     }
 
     @Override
@@ -67,6 +85,20 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
             clone.nestedLoops.push((LabelledCounter) lc.clone());
+
+        if (this.loopNames != null) {
+            clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            while (loopNamesIterator.hasNext()) {
+                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+
+                int idx = this.nestedLoops.indexOf(pair.getValue());
+                if (idx != -1)
+                    clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
+            }
+        }
+
         return clone;
     }
 
@@ -76,6 +108,20 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
         clone.nestedLoops = new Stack<>();
         for(LabelledCounter lc : this.nestedLoops)
             clone.nestedLoops.push((LabelledCounter) lc.clone());
+
+        if (this.loopNames != null) {
+            clone.loopNames = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+            Iterator loopNamesIterator = this.loopNames.entrySet().iterator();
+            while (loopNamesIterator.hasNext()) {
+                ReferenceMap.Entry pair = (ReferenceMap.Entry) loopNamesIterator.next();
+
+                int idx = this.nestedLoops.indexOf(pair.getValue());
+                if (idx != -1)
+                    clone.loopNames.put(pair.getKey(), clone.nestedLoops.get(idx));
+            }
+        }
+
         return clone;
     }
 
@@ -94,13 +140,17 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> {
 
         NL_O_OB_S_SE_SL_Traverser<?> that = (NL_O_OB_S_SE_SL_Traverser<?>) o;
 
-        return this.nestedLoops.equals(that.nestedLoops);
+        if (!this.nestedLoops.equals(that.nestedLoops)) return false;
+        return this.loopNames != null ? this.loopNames.equals(that.loopNames) : that.loopNames == null;
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
         result = 31 * result + this.nestedLoops.hashCode();
+        result = 31 * result + (this.loopNames != null ? this.loopNames.hashCode() : 0);
+
         return result;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java
index e35716d..6001a7b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/O_OB_S_SE_SL_Traverser.java
@@ -30,6 +30,7 @@ public class O_OB_S_SE_SL_Traverser<T> extends O_Traverser<T> {
 
     protected Object sack = null;
     protected short loops = 0;  // an optimization hack to use a short internally to save bits :)
+    protected String loopName = null;
     protected transient TraversalSideEffects sideEffects;
     protected String future = HALT;
     protected long bulk = 1L;
@@ -74,6 +75,19 @@ public class O_OB_S_SE_SL_Traverser<T> extends O_Traverser<T> {
     }
 
     @Override
+    public int loops(final String loopName) {
+        if (loopName == null || this.loopName != null && this.loopName.equals(loopName))
+            return this.loops;
+        else
+            throw new IllegalArgumentException("Loop name not defined: " + loopName);
+    }
+
+    @Override
+    public void initialiseLoops(final String stepLabel , final String loopName){
+        this.loopName = loopName;
+    }
+
+    @Override
     public void incrLoops() {
         this.loops++;
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
index b624eef..ad3712b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
@@ -91,8 +91,8 @@ public final class ProjectedTraverser<T, P> implements Traverser.Admin<T> {
     }
 
     @Override
-    public void initialiseLoops(final String stepLabel) {
-        this.baseTraverser.initialiseLoops(stepLabel);
+    public void initialiseLoops(final String stepLabel, final String loopName) {
+        this.baseTraverser.initialiseLoops(stepLabel, loopName);
     }
 
     @Override
@@ -172,6 +172,11 @@ public final class ProjectedTraverser<T, P> implements Traverser.Admin<T> {
     }
 
     @Override
+    public int loops(String loopName) {
+        return this.baseTraverser.loops(loopName);
+    }
+
+    @Override
     public long bulk() {
         return this.baseTraverser.bulk();
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
index 9d52fea..658ba4b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
@@ -100,7 +100,7 @@ public abstract class AbstractTraverser<T> implements Traverser<T>, Traverser.Ad
 
 
     @Override
-    public void initialiseLoops(final String stepLabel) {
+    public void initialiseLoops(final String stepLabel, final String loopName) {
 
     }
 
@@ -180,6 +180,11 @@ public abstract class AbstractTraverser<T> implements Traverser<T>, Traverser.Ad
     }
 
     @Override
+    public int loops(final String loopName) {
+        throw new UnsupportedOperationException("This traverser does not support named loops: " + this.getClass().getCanonicalName());
+    }
+
+    @Override
     public long bulk() {
         return 1l;
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
index 4f4ca0a..3aeafbd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
@@ -70,7 +70,7 @@ public final class EmptyTraverser<T> implements Traverser<T>, Traverser.Admin<T>
     }
 
     @Override
-    public void initialiseLoops(final String stepLabel) {
+    public void initialiseLoops(final String stepLabel, final String loopNam) {
 
     }
 
@@ -155,6 +155,11 @@ public final class EmptyTraverser<T> implements Traverser<T>, Traverser.Admin<T>
     }
 
     @Override
+    public int loops(final String loopName) {
+        return 0;
+    }
+
+    @Override
     public long bulk() {
         return 0l;
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
index 0e2130a..8be43e3 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java
@@ -29,15 +29,18 @@ import java.io.Serializable;
 public class LabelledCounter implements Serializable, Cloneable {
 
     private final String label;
+    private final MutableShort count = new MutableShort();
 
-    private final MutableShort count;
+    protected LabelledCounter() {
+        label = "";
+    }
 
     public LabelledCounter(final String label, final short initialCount) {
         if (label == null) {
             throw new NullPointerException("Label is null");
         }
         this.label = label;
-        this.count = new MutableShort(initialCount);
+        this.count.setValue(initialCount);
     }
 
     public boolean hasLabel(final String label){

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
index fb2cffa..6935549 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
@@ -117,6 +117,7 @@ import org.apache.tinkerpop.shaded.kryo.serializers.JavaSerializer;
 import org.javatuples.Pair;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.LabelledCounter;
 import org.apache.commons.lang.mutable.MutableShort;
+import org.apache.commons.collections.map.ReferenceMap;
 import java.util.Stack;
 
 import java.math.BigDecimal;
@@ -393,7 +394,8 @@ public enum GryoVersion {
             add(GryoTypeReg.of(LP_NL_O_OB_P_S_SE_SL_Traverser.class, 179));
             add(GryoTypeReg.of(LabelledCounter.class, 180));
             add(GryoTypeReg.of(MutableShort.class, 181));
-            add(GryoTypeReg.of(Stack.class, 182));                         // ***LAST ID***
+            add(GryoTypeReg.of(Stack.class, 182));
+            add(GryoTypeReg.of(ReferenceMap.class, 183));                        // ***LAST ID***
 
 
             // placeholder serializers for classes that don't live here in core. this will allow them to be used if
@@ -583,7 +585,8 @@ public enum GryoVersion {
             add(GryoTypeReg.of(LP_NL_O_OB_P_S_SE_SL_Traverser.class, 179));
             add(GryoTypeReg.of(LabelledCounter.class, 180));
             add(GryoTypeReg.of(MutableShort.class, 181));
-            add(GryoTypeReg.of(Stack.class, 182));                         // ***LAST ID***
+            add(GryoTypeReg.of(Stack.class, 182));
+            add(GryoTypeReg.of(ReferenceMap.class, 183));                        // ***LAST ID***
         }};
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index 537cdbe..4979067 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -914,6 +914,15 @@ namespace Gremlin.Net.Process.Traversal
         }
 
         /// <summary>
+        ///     Adds the loops step to this <see cref="GraphTraversal{SType, EType}" />.
+        /// </summary>
+        public GraphTraversal<S, int> Loops (string loopName)
+        {
+            Bytecode.AddStep("loops", loopName);
+            return Wrap<S, int>(this);
+        }
+
+        /// <summary>
         ///     Adds the map step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
         public GraphTraversal<S, E2> Map<E2> (IFunction function)
@@ -1249,6 +1258,15 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the repeat step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
+        public GraphTraversal<S, E> Repeat (string loopName, ITraversal repeatTraversal)
+        {
+            Bytecode.AddStep("repeat", loopName, repeatTraversal);
+            return Wrap<S, E>(this);
+        }
+
+        /// <summary>
+        ///     Adds the repeat step to this <see cref="GraphTraversal{SType, EType}" />.
+        /// </summary>
         public GraphTraversal<S, E> Repeat (ITraversal repeatTraversal)
         {
             Bytecode.AddStep("repeat", repeatTraversal);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
index 27a0004..3681ce6 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
@@ -697,6 +697,14 @@ namespace Gremlin.Net.Process.Traversal
         }
 
         /// <summary>
+        ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the loops step to that traversal.
+        /// </summary>
+        public static GraphTraversal<object, int> Loops(string loopName)
+        {
+            return new GraphTraversal<object, int>().Loops(loopName);            
+        }
+
+        /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the map step to that traversal.
         /// </summary>
         public static GraphTraversal<object, E2> Map<E2>(IFunction function)
@@ -933,6 +941,14 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the repeat step to that traversal.
         /// </summary>
+        public static GraphTraversal<object, object> Repeat(string loopName, ITraversal traversal)
+        {
+            return new GraphTraversal<object, object>().Repeat(loopName, traversal);            
+        }
+
+        /// <summary>
+        ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the repeat step to that traversal.
+        /// </summary>
         public static GraphTraversal<object, object> Repeat(ITraversal traversal)
         {
             return new GraphTraversal<object, object>().Repeat(traversal);            

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-test/features/branch/Repeat.feature
----------------------------------------------------------------------
diff --git a/gremlin-test/features/branch/Repeat.feature b/gremlin-test/features/branch/Repeat.feature
index 695ca1f..b5dc6ce 100644
--- a/gremlin-test/features/branch/Repeat.feature
+++ b/gremlin-test/features/branch/Repeat.feature
@@ -293,6 +293,18 @@ Scenario: g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_r
     | java |
     | java |
 
+Scenario: g_V_emit_repeatXa_outXknows_filterXloops_isX0XX_lang
+  Given the modern graph
+  And the traversal of
+    """
+    g.V().emit().repeat("a", __.out("knows").filter(__.loops("a").is(0))).values("lang")
+    """
+  When iterated to list
+  Then the result should be unordered
+    | result |
+    | java |
+    | java |
+
 Scenario: g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values
     Given the modern graph
     And using the parameter v3Id defined as "v[lop].id"
@@ -318,3 +330,27 @@ Scenario: g_VX1X_repeatXrepeatXunionXout_uses_out_traversesXX_whereXloops_isX0X_
       Then the result should be unordered
         | result |
         | tinkergraph |
+
+Scenario: g_V_repeatXa_outXknows_repeatXb_outXcreatedX_filterXloops_isX0XX_emit_lang
+  Given the modern graph
+  And the traversal of
+    """
+    g.V().repeat("a", __.out("knows").repeat("b", __.out("created").filter(__.loops("a").is(0))).emit()).emit().values("lang")
+    """
+  When iterated to list
+  Then the result should be unordered
+    | result |
+    | java |
+    | java |
+
+Scenario: g_VX6X_repeatXa_bothXcreatedXX_emitXrepeatXb_bothXknowsXX_untilXorXloops_isX2X_loopsXbX_isXloopsXaXXXX_hasXname_vadasXX_dedup_name
+  Given the modern graph
+  And using the parameter v6Id defined as "v[peter].id"
+  And the traversal of
+    """
+    g.V(v6Id).repeat("a", __.both("created")).emit(__.repeat("b", __.both("knows")).until(__.or(__.loops().is(2), __.loops("b").is(__.loops("a")))).has("name", "vadas")).dedup().values("name")
+    """
+  When iterated to list
+  Then the result should be unordered
+    | result |
+    | josh |

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80eb841/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
index b454c8c..a43534c 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java
@@ -114,6 +114,14 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, String> get_g_VX1X_repeatXrepeatXunionXout_uses_out_traversesXX_whereXloops_isX0X_timesX1X_timeX2X_name(final Object v1Id);
 
+    // NAMED LOOP
+
+    public abstract Traversal<Vertex, String> get_g_V_repeatXa_outXknows_repeatXb_outXcreatedX_filterXloops_isX0XX_emit_lang();
+
+    public abstract Traversal<Vertex, String> get_g_V_emit_repeatXa_outXknows_filterXloops_isX0XX_lang();
+
+    public abstract Traversal<Vertex, String> get_g_VX6X_repeatXa_bothXcreatedXX_emitXrepeatXb_bothXknowsXX_untilXorXloops_isX2X_loopsXbX_isXloopsXaXXXX_hasXname_vadasXX_dedup_name(final Object v6Id);
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_repeatXoutX_timesX2X_emit_path() {
@@ -388,7 +396,6 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
     @LoadGraphWith(MODERN)
     public void g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values() {
         final Traversal<Vertex, String> traversal = get_g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values(convertToVertexId("lop"));
-
         printTraversalForm(traversal);
         for (String res :   new String[]{"josh","lop", "ripple"})
         {
@@ -396,7 +403,6 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
             String lang = traversal.next();
             assertEquals(lang, res);
         }
-
         assertFalse(traversal.hasNext());
     }
 
@@ -404,12 +410,48 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
     @LoadGraphWith(CREW)
     public void g_VX1X_repeatXrepeatXunionXout_uses_out_traversesXX_whereXloops_isX0X_timesX1X_timeX2X_name() {
         final Traversal<Vertex, String> traversal = get_g_VX1X_repeatXrepeatXunionXout_uses_out_traversesXX_whereXloops_isX0X_timesX1X_timeX2X_name(convertToVertexId("marko"));
-
         printTraversalForm(traversal);
         assertTrue(traversal.hasNext());
         String name = traversal.next();
         assertEquals(name, "tinkergraph");
+        assertFalse(traversal.hasNext());
+    }
+
+    @LoadGraphWith(MODERN)
+    public void g_V_repeatXa_outXknows_repeatXb_outXcreatedX_filterXloops_isX0XX_emit_lang() {
+        final Traversal<Vertex, String> traversal = get_g_V_repeatXa_outXknows_repeatXb_outXcreatedX_filterXloops_isX0XX_emit_lang();
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        String lang = traversal.next();
+        assertEquals(lang, "java");
+        assertTrue(traversal.hasNext());
+        lang = traversal.next();
+        assertEquals(lang, "java");
+        assertFalse(traversal.hasNext());
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_emit_repeatXa_outXknows_filterXloops_isX0XX_lang() {
+        final Traversal<Vertex, String> traversal = get_g_V_emit_repeatXa_outXknows_filterXloops_isX0XX_lang();
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        String lang = traversal.next();
+        assertEquals(lang, "java");
+        assertTrue(traversal.hasNext());
+        lang = traversal.next();
+        assertEquals(lang, "java");
+        assertFalse(traversal.hasNext());
+    }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_VX6X_repeatXa_bothXcreatedXX_emitXrepeatXb_bothXknowsXX_untilXorXloops_isX2X_loopsXbX_isXloopsXaXXXX_hasXname_vadasXX_dedup_name() {
+        final Traversal<Vertex, String> traversal = get_g_VX6X_repeatXa_bothXcreatedXX_emitXrepeatXb_bothXknowsXX_untilXorXloops_isX2X_loopsXbX_isXloopsXaXXXX_hasXname_vadasXX_dedup_name(convertToVertexId("peter"));
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        String name = traversal.next();
+        assertEquals(name, "josh");
         assertFalse(traversal.hasNext());
     }
 
@@ -513,7 +555,22 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest {
 
         @Override
         public Traversal<Vertex, String> get_g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values(final Object v3Id) {
-            return g.V(v3Id).repeat( __.both("created")).until(loops().is(40)).emit(__.repeat(__.in("knows")).emit(loops().is(1))).dedup().values("name");
+            return g.V(v3Id).repeat(__.both("created")).until(loops().is(40)).emit(__.repeat(__.in("knows")).emit(loops().is(1))).dedup().values("name");
+        }
+
+        @Override
+        public Traversal<Vertex, String> get_g_V_repeatXa_outXknows_repeatXb_outXcreatedX_filterXloops_isX0XX_emit_lang() {
+            return g.V().repeat("a", out("knows").repeat("b", out("created").filter(loops("a").is(0))).emit()).emit().values("lang");
+        }
+
+        @Override
+        public Traversal<Vertex, String> get_g_V_emit_repeatXa_outXknows_filterXloops_isX0XX_lang() {
+            return g.V().emit().repeat("a", out("knows").filter(loops("a").is(0))).values("lang");
+        }
+
+        @Override
+        public Traversal<Vertex, String> get_g_VX6X_repeatXa_bothXcreatedXX_emitXrepeatXb_bothXknowsXX_untilXorXloops_isX2X_loopsXbX_isXloopsXaXXXX_hasXname_vadasXX_dedup_name(final Object v6Id) {
+            return g.V(v6Id).repeat("a", both("created")).emit(__.repeat("b", __.both("knows")).until(__.or(loops().is(2), loops("b").is(loops("a")))).has("name", "vadas")).dedup().values("name");
         }
 
         @Override


[06/11] tinkerpop git commit: Merge branch 'master' into TINKERPOP-967

Posted by sp...@apache.org.
Merge branch 'master' into TINKERPOP-967

Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/8a26b3a8
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/8a26b3a8
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/8a26b3a8

Branch: refs/heads/master
Commit: 8a26b3a8c225184e0f9ccd742219f6f971d3429c
Parents: 3974b07 1f240fe
Author: GCHQResearcher1337 <39...@users.noreply.github.com>
Authored: Sat Jun 30 09:47:42 2018 +0100
Committer: GitHub <no...@github.com>
Committed: Sat Jun 30 09:47:42 2018 +0100

----------------------------------------------------------------------
 .gitignore                                      |   2 +-
 CHANGELOG.asciidoc                              |  13 +-
 docker/Dockerfile                               |   4 +-
 docs/site/home/img/practical-gremlin-titled.png | Bin 0 -> 412544 bytes
 docs/site/home/index.html                       |   4 +-
 docs/site/home/template/header-footer.html      |   3 +
 .../developer/development-environment.asciidoc  |  14 +-
 docs/src/dev/developer/release.asciidoc         |   1 +
 docs/src/dev/provider/index.asciidoc            |  17 ++
 docs/src/index.asciidoc                         |   2 +-
 .../src/reference/gremlin-applications.asciidoc |  50 +++--
 .../reference/implementations-neo4j.asciidoc    |   4 +-
 .../reference/implementations-spark.asciidoc    |  64 +------
 docs/src/reference/the-graphcomputer.asciidoc   |  85 ++-------
 docs/src/reference/the-traversal.asciidoc       |  43 +++--
 .../upgrade/release-3.2.x-incubating.asciidoc   |  35 ++++
 docs/src/upgrade/release-3.3.x.asciidoc         |   8 +
 docs/src/upgrade/release-3.4.x.asciidoc         |  49 ++++-
 docs/static/images/practical-gremlin.png        | Bin 0 -> 392179 bytes
 .../tinkerpop/gremlin/console/Console.groovy    |  16 +-
 .../tinkerpop/gremlin/jsr223/CoreImports.java   |  10 +-
 .../bulkdumping/BulkDumperVertexProgram.java    |   3 +
 .../computer/bulkloading/BulkLoader.java        |   2 +
 .../bulkloading/BulkLoaderVertexProgram.java    |   8 +-
 .../bulkloading/IncrementalBulkLoader.java      |   2 +
 .../computer/bulkloading/OneTimeBulkLoader.java |   2 +
 .../computer/clone/CloneVertexProgram.java      |  98 ++++++++++
 .../computer/traversal/step/map/PageRank.java   |  43 +++++
 .../step/map/PageRankVertexProgramStep.java     |  41 +---
 .../traversal/step/map/PeerPressure.java        |  43 +++++
 .../step/map/PeerPressureVertexProgramStep.java |  40 +---
 .../gremlin/process/remote/RemoteGraph.java     |   4 +
 .../process/traversal/step/map/MathStep.java    |  64 +++++--
 .../step/sideEffect/AddPropertyStep.java        |   8 +-
 .../util/event/ConsoleMutationListener.java     |   5 -
 .../step/util/event/MutationListener.java       |  11 +-
 .../strategy/decoration/EventStrategy.java      | 108 ++++++-----
 .../tinkerpop/gremlin/structure/Graph.java      |   1 -
 .../util/empty/EmptyVertexProperty.java         |   2 +-
 .../structure/util/keyed/KeyedProperty.java     |  85 +++++++++
 .../util/keyed/KeyedVertexProperty.java         | 114 +++++++++++
 .../strategy/decoration/EventStrategyTest.java  |   1 -
 gremlin-dotnet/Gremlin.Net.sln                  |  19 +-
 .../glv/Gremlin.Net.Template.csproj.template    |  33 ++++
 .../glv/Gremlin.Net.Template.nuspec.template    |  21 ++
 gremlin-dotnet/glv/generate.groovy              |  36 ++--
 .../.template.config/template.json              |  14 ++
 .../Gremlin.Net.Template.csproj                 |  33 ++++
 .../Gremlin.Net.Template.nuspec                 |  21 ++
 .../src/Gremlin.Net.Template/Program.cs         |  50 +++++
 .../src/Gremlin.Net.Template/README.md          |  46 +++++
 .../src/Gremlin.Net.Template/Service.cs         |  43 +++++
 .../src/Gremlin.Net/Driver/ConnectionPool.cs    |  26 ++-
 gremlin-dotnet/src/pom.xml                      |  60 +++++-
 .../Gremlin.Net.Template.IntegrationTest.csproj |  20 ++
 .../ServiceTests.cs                             |  57 ++++++
 .../jsr223/GroovyCompilerGremlinPlugin.java     |   7 +
 .../src/main/jython/tests/conftest.py           |   2 +-
 gremlin-server/conf/gremlin-server-modern.yaml  |   1 +
 gremlin-server/conf/gremlin-server-neo4j.yaml   |   2 +-
 gremlin-server/conf/neo4j-empty.properties      |   2 +-
 .../src/test/scripts/neo4j-empty.properties     |   2 +-
 .../tinkerpop/gremlin/AbstractGremlinTest.java  |  78 +++++---
 .../apache/tinkerpop/gremlin/GraphManager.java  |   5 +
 .../apache/tinkerpop/gremlin/GraphProvider.java |  16 ++
 .../gremlin/process/ProcessComputerSuite.java   |   2 +
 .../computer/clone/CloneVertexProgramTest.java  |  98 ++++++++++
 .../process/traversal/step/map/MathTest.java    |  32 ++++
 .../traversal/step/map/PageRankTest.java        |  10 +-
 .../traversal/step/map/PeerPressureTest.java    |  10 +-
 .../decoration/EventStrategyProcessTest.java    | 190 ++++---------------
 .../neo4j/AbstractNeo4jGraphProvider.java       |  23 ++-
 pom.xml                                         |  15 +-
 73 files changed, 1539 insertions(+), 544 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8a26b3a8/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --cc CHANGELOG.asciidoc
index 55ab169,d4f0c2e..4dc106d
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@@ -37,7 -38,9 +38,10 @@@ This release also includes changes fro
  * Changed the order of `select()` scopes. The order is now: maps, side-effects, paths.
  * Removed previously deprecated Credentials DSL infrastructure.
  * Moved `TraversalEngine` to `gremlin-test` as it has long been only used in testing infrastructure.
 +* Nested loop support added allowing `repeat()` steps to be nested.
+ * Events from `EventStrategy` raised from "new" mutations will now return a `KeyedVertexProperty` or `KeyedProperty` as is appropriate.
+ * `MutationListener#vertexPropertyChanged(Vertex, VertexProperty, Object, Object...)` no longer has a default implementation.
+ * Removed previously deprecated `MutationListener#vertexPropertyChanged(Vertex, Property, Object, Object...)`.
  * Removed previously deprecated `OpSelectorHandler` constructor.
  * Removed previously deprecated `close()` from `GremlinGroovyScriptEngine` which no longer implements `AutoCloseable`.
  * Removed previously deprecated `getGraphInputFormat()` and `getGraphOutputFormat()` from `HadoopConfiguration`.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8a26b3a8/docs/src/upgrade/release-3.4.x.asciidoc
----------------------------------------------------------------------
diff --cc docs/src/upgrade/release-3.4.x.asciidoc
index 887ac38,8829569..8de3da9
--- a/docs/src/upgrade/release-3.4.x.asciidoc
+++ b/docs/src/upgrade/release-3.4.x.asciidoc
@@@ -113,22 -113,27 +113,43 @@@ gremlin> g.V().values('name').max(
  ==>vadas
  ----
  
 +==== Nested loop support
 +
 +Traversals now support nesting of `repeat()` loops.
 +
 +These can now be used to repeat another traversal while in a looped context, either inside the body of a `repeat()` or in its step modifiers (`until()` or `emit()`).
 +
 +[source,groovy]
 +----
 +gremlin> g.V().repeat(__.in('traverses').repeat(__.in('develops')).emit()).emit().values('name')
 +==>stephen
 +==>matthias
 +==>marko
 +----
 +
 +See: link:https://issues.apache.org/jira/browse/TINKERPOP-967[TINKERPOP-967]
 +
+ ==== EventStrategy API
+ 
+ There were some minor modifications to how `EventStrategy` is constructed and what can be expected from events raised
+ from the addition of new properties.
+ 
+ With respect to the change in terms of `EventStrategy` construction, the `detach()` builder method formerly took a
+ `Class` as an argument and that `Class` was meant to be one of the various "detachment factories" or `null`. That
+ approach was a bit confusing, so that signature has changed to `detach(EventStrategy.Detachment)` where the argument
+ is a more handy enum of detachment options.
+ 
+ As for the changes related to events themselves, it is first worth noting that the previously deprecated
+ `vertexPropertyChanged(Vertex, Property, Object, Object...)` on `MutationListener` has been removed for what should
+ have originally been the correct signature of `vertexPropertyChanged(Vertex, VertexProperty, Object, Object...)`. In
+ prior versions when this method and its related `edgePropertyChanged()` and `vertexPropertyPropertyChanged()` were
+ triggered by way of the addition of a new property a "fake" property was included with a `null` value for the
+ "oldValue" argument to these methods (as it did not exist prior to this event). That was a bit awkward to reason about
+ when dealing with that event. To make this easier, the event now raises with a `KeyedVertexProperty` or
+ `KeyedProperty` instance, which only contains a property key and no value in them.
+ 
+ link:https://issues.apache.org/jira/browse/TINKERPOP-1831[TINKERPOP-1831]
+ 
  ==== Deprecation Removal
  
  The following deprecated classes, methods or fields have been removed in this version:


[04/11] tinkerpop git commit: Tweak to RepeatUnrollStrategy and Nested Loop tests

Posted by sp...@apache.org.
Tweak to RepeatUnrollStrategy and Nested Loop tests

Tweak to RepeatUnrollStrategy to prevent multiple barrier steps being added back to back
Added tests for the RepeatUnrollStrategy in the case of Nested repeat() loops


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/ad35a6ac
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/ad35a6ac
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/ad35a6ac

Branch: refs/heads/master
Commit: ad35a6ac8261dfdaed74a8663dac71cac7cbef50
Parents: 27da9b7
Author: GCHQResearcher1337 <39...@users.noreply.github.com>
Authored: Mon Jun 18 17:06:21 2018 +0100
Committer: GCHQResearcher1337 <39...@users.noreply.github.com>
Committed: Mon Jun 18 17:06:21 2018 +0100

----------------------------------------------------------------------
 .../traversal/strategy/optimization/RepeatUnrollStrategy.java | 5 ++++-
 .../strategy/optimization/RepeatUnrollStrategyTest.java       | 7 +++++++
 2 files changed, 11 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ad35a6ac/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategy.java
index aaf1a55..d461472 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategy.java
@@ -69,8 +69,11 @@ public final class RepeatUnrollStrategy extends AbstractTraversalStrategy<Traver
                     for (int j = 0; j < loops; j++) {
                         TraversalHelper.insertTraversal(insertIndex, repeatTraversal.clone(), traversal);
                         insertIndex = insertIndex + repeatLength;
-                        if (j != (loops - 1) || !(traversal.getSteps().get(insertIndex).getNextStep() instanceof Barrier)) // only add a final NoOpBarrier is subsequent step is not a barrier
+                        if ((j != (loops - 1) || !(traversal.getSteps().get(insertIndex).getNextStep() instanceof Barrier)) // only add a final NoOpBarrier is subsequent step is not a barrier
+                            && !(traversal.getSteps().get(insertIndex) instanceof NoOpBarrierStep) // Don't add a barrier if this step is a barrier (prevents nested repeat adding the barrier multiple times)
+                           ) {
                             traversal.addStep(++insertIndex, new NoOpBarrierStep<>(traversal, MAX_BARRIER_SIZE));
+                        }
                     }
                     // label last step if repeat() was labeled
                     if (!repeatStep.getLabels().isEmpty())

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ad35a6ac/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategyTest.java
index 88eb5a6..13223cb 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategyTest.java
@@ -92,6 +92,13 @@ public class RepeatUnrollStrategyTest {
                 {__.repeat(__.outE().inV()).times(2), __.outE().inV().barrier(maxBarrierSize).outE().inV().barrier(maxBarrierSize), Collections.emptyList()},
                 {__.repeat(__.outE().filter(path()).inV()).times(2), __.outE().filter(path()).inV().barrier(maxBarrierSize).outE().filter(path()).inV().barrier(maxBarrierSize), Collections.singletonList(IncidentToAdjacentStrategy.instance())},
                 {__.repeat(__.outE().inV()).times(2), __.out().barrier(maxBarrierSize).out().barrier(maxBarrierSize), Collections.singletonList(IncidentToAdjacentStrategy.instance())},
+                // Nested Loop tests
+                {__.repeat(out().repeat(out()).times(0)).times(1), __.out().repeat(out()).times(0).barrier(maxBarrierSize), Collections.emptyList()},
+                {__.repeat(out().repeat(out()).times(1)).times(1), __.out().out().barrier(maxBarrierSize), Collections.emptyList()},
+                {__.repeat(out()).until(__.repeat(out()).until(predicate)), __.repeat(out()).until(__.repeat(out()).until(predicate)), Collections.emptyList()},
+                {__.repeat(__.repeat(out()).times(2)).until(predicate), __.repeat(__.out().barrier(maxBarrierSize).out().barrier(maxBarrierSize)).until(predicate), Collections.emptyList()},
+                {__.repeat(__.repeat(out("created")).until(__.has("name", "ripple"))), __.repeat(__.repeat(out("created")).until(__.has("name", "ripple"))), Collections.emptyList()},
+
         });
     }
 }