tinkerpop-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From spmalle...@apache.org
Subject [01/50] tinkerpop git commit: TINKERPOP-967 Support nested-repeat() structures [Forced Update!]
Date Thu, 19 Jul 2018 17:41:20 GMT
Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1996 2bca26741 -> 048ea21c0 (forced update)


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/TINKERPOP-1996
Commit: 320c14365f9a77a6942d8c5a6e997560634cf855
Parents: d3b6a34
Author: GCHQResearcher1337 <39384472+GCHQResearcher1337@users.noreply.github.com>
Authored: Mon Jun 4 10:35:29 2018 +0100
Committer: GCHQResearcher1337 <39384472+GCHQResearcher1337@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");
+        }
     }
 }


Mime
View raw message