This is an automated email from the ASF dual-hosted git repository.

colegreer pushed a commit to branch gvalue-range
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 6325b6adc529cee048fc1174956a78f0b2f80595
Author: Cole-Greer <[email protected]>
AuthorDate: Wed Jan 15 15:32:54 2025 -0800

    WIP add GValue to range(), limit(), skip(), and tail() steps
---
 .../gremlin/language/grammar/ArgumentVisitor.java  |  26 +++++
 .../language/grammar/TraversalMethodVisitor.java   |  84 +++++++++++---
 .../traversal/dsl/graph/GraphTraversal.java        | 125 +++++++++++++++++++++
 .../gremlin/process/traversal/dsl/graph/__.java    |  56 +++++++++
 .../traversal/step/filter/RangeGlobalStep.java     |  35 +++---
 .../traversal/step/filter/TailGlobalStep.java      |  21 ++--
 .../process/traversal/step/map/RangeLocalStep.java |  21 ++--
 .../process/traversal/step/map/TailLocalStep.java  |  13 ++-
 gremlin-language/src/main/antlr4/Gremlin.g4        |  16 +--
 9 files changed, 340 insertions(+), 57 deletions(-)

diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java
index e9eec826f4..cd19752309 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.language.grammar;
 
+import 
org.apache.tinkerpop.gremlin.process.traversal.GremlinTypeErrorException;
 import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
 import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
@@ -100,6 +101,31 @@ public class ArgumentVisitor extends 
DefaultGremlinBaseVisitor<Object> {
         }
     }
 
+    /**
+     * Alternative to visitIntegerArgument which promotes types to either Long 
or GValue<Long>
+     */
+    public Object parseLong(final GremlinParser.IntegerArgumentContext ctx) {
+        if (ctx.integerLiteral() != null) {
+            return 
antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue();
+        } else {
+            Object var = visitVariable(ctx.variable());
+            if (var instanceof Number) {
+                return ((Number) var).longValue();
+            }
+            if (GValue.valueInstanceOf(var, GType.LONG)) {
+                return var;
+            } else if (GValue.valueInstanceOf(var, GType.INTEGER)) {
+                return GValue.ofLong(((GValue<Integer>) var).getName(), 
((GValue<Integer>) var).get().longValue());
+            } else if (GValue.valueInstanceOf(var, GType.SHORT)) {
+                return GValue.ofLong(((GValue<Short>) var).getName(), 
((GValue<Short>) var).get().longValue());
+            } else if (GValue.valueInstanceOf(var, GType.BYTE)) {
+                return GValue.ofLong(((GValue<Byte>) var).getName(), 
((GValue<Byte>) var).get().longValue());
+            } else {
+                throw new GremlinParserException(String.format("Expected 
variable [%s] to resolve to an integer type, instead found: %s", 
ctx.variable().Identifier().getSymbol(), var.getClass().getName()));
+            }
+        }
+    }
+
     @Override
     public Object visitBooleanArgument(final 
GremlinParser.BooleanArgumentContext ctx) {
         if (ctx.booleanLiteral() != null) {
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index 066b550b67..f7389aa82f 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -1022,8 +1022,14 @@ public class TraversalMethodVisitor extends 
TraversalRootVisitor<GraphTraversal>
      */
     @Override
     public GraphTraversal visitTraversalMethod_limit_Scope_long(final 
GremlinParser.TraversalMethod_limit_Scope_longContext ctx) {
-        return 
graphTraversal.limit(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class,
 ctx.traversalScope()),
-                
antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
+        final Object literalOrVar = 
antlr.argumentVisitor.parseLong(ctx.integerArgument());
+        if (GValue.valueInstanceOf(literalOrVar, GType.LONG)) {
+            return 
graphTraversal.limit(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class,
 ctx.traversalScope()),
+                    (GValue<Long>) literalOrVar);
+        } else {
+            return 
graphTraversal.limit(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class,
 ctx.traversalScope()),
+                    (Long) literalOrVar);
+        }
     }
 
     /**
@@ -1031,7 +1037,12 @@ public class TraversalMethodVisitor extends 
TraversalRootVisitor<GraphTraversal>
      */
     @Override
     public GraphTraversal visitTraversalMethod_limit_long(final 
GremlinParser.TraversalMethod_limit_longContext ctx) {
-        return 
graphTraversal.limit(antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
+        final Object literalOrVar = 
antlr.argumentVisitor.parseLong(ctx.integerArgument());
+        if (GValue.valueInstanceOf(literalOrVar, GType.LONG)) {
+            return graphTraversal.limit((GValue<Long>) literalOrVar);
+        } else {
+            return graphTraversal.limit((Long) literalOrVar);
+        }
     }
 
     /**
@@ -1469,9 +1480,21 @@ public class TraversalMethodVisitor extends 
TraversalRootVisitor<GraphTraversal>
      */
     @Override
     public GraphTraversal visitTraversalMethod_range_Scope_long_long(final 
GremlinParser.TraversalMethod_range_Scope_long_longContext ctx) {
-        return 
graphTraversal.range(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class,
 ctx.traversalScope()),
-                
antlr.genericVisitor.parseIntegral(ctx.integerLiteral(0)).longValue(),
-                
antlr.genericVisitor.parseIntegral(ctx.integerLiteral(1)).longValue());
+        Object low = antlr.argumentVisitor.parseLong(ctx.integerArgument(0));
+        Object high = antlr.argumentVisitor.parseLong(ctx.integerArgument(1));
+        if (GValue.valueInstanceOf(low, GType.LONG) || 
GValue.valueInstanceOf(high, GType.LONG)) {
+            if (!GValue.valueInstanceOf(low, GType.LONG)) {
+                low = GValue.ofLong(null, (Long) low);
+            }
+            if (!GValue.valueInstanceOf(high, GType.LONG)) {
+                high = GValue.ofLong(null, (Long) high);
+            }
+            return 
graphTraversal.range(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class,
 ctx.traversalScope()),
+                    (GValue<Long>) low, (GValue<Long>) high);
+        } else {
+            return 
graphTraversal.range(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class,
 ctx.traversalScope()),
+                    (Long) low, (Long) high);
+        }
     }
 
     /**
@@ -1479,8 +1502,19 @@ public class TraversalMethodVisitor extends 
TraversalRootVisitor<GraphTraversal>
      */
     @Override
     public GraphTraversal visitTraversalMethod_range_long_long(final 
GremlinParser.TraversalMethod_range_long_longContext ctx) {
-        return 
graphTraversal.range(antlr.genericVisitor.parseIntegral(ctx.integerLiteral(0)).longValue(),
-               
antlr.genericVisitor.parseIntegral(ctx.integerLiteral(1)).longValue());
+        Object low = antlr.argumentVisitor.parseLong(ctx.integerArgument(0));
+        Object high = antlr.argumentVisitor.parseLong(ctx.integerArgument(1));
+        if (GValue.valueInstanceOf(low, GType.LONG) || 
GValue.valueInstanceOf(high, GType.LONG)) {
+            if (!GValue.valueInstanceOf(low, GType.LONG)) {
+                low = GValue.ofLong(null, (Long) low);
+            }
+            if (!GValue.valueInstanceOf(high, GType.LONG)) {
+                high = GValue.ofLong(null, (Long) high);
+            }
+            return graphTraversal.range((GValue<Long>) low, (GValue<Long>) 
high);
+        } else {
+            return graphTraversal.range((Long) low, (Long) high);
+        }
     }
 
     /**
@@ -1594,8 +1628,14 @@ public class TraversalMethodVisitor extends 
TraversalRootVisitor<GraphTraversal>
      */
     @Override
     public GraphTraversal visitTraversalMethod_skip_Scope_long(final 
GremlinParser.TraversalMethod_skip_Scope_longContext ctx) {
-        return 
graphTraversal.skip(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class,
 ctx.traversalScope()),
-                
antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
+        final Object literalOrVar = 
antlr.argumentVisitor.parseLong(ctx.integerArgument());
+        if (GValue.valueInstanceOf(literalOrVar, GType.LONG)) {
+            return 
graphTraversal.skip(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class,
 ctx.traversalScope()),
+                    (GValue<Long>) literalOrVar);
+        } else {
+            return 
graphTraversal.skip(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class,
 ctx.traversalScope()),
+                    (Long) literalOrVar);
+        }
     }
 
     /**
@@ -1603,7 +1643,12 @@ public class TraversalMethodVisitor extends 
TraversalRootVisitor<GraphTraversal>
      */
     @Override
     public GraphTraversal visitTraversalMethod_skip_long(final 
GremlinParser.TraversalMethod_skip_longContext ctx) {
-        return 
graphTraversal.skip(antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
+        final Object literalOrVar = 
antlr.argumentVisitor.parseLong(ctx.integerArgument());
+        if (GValue.valueInstanceOf(literalOrVar, GType.LONG)) {
+            return graphTraversal.skip((GValue<Long>) literalOrVar);
+        } else {
+            return graphTraversal.skip((Long) literalOrVar);
+        }
     }
 
     /**
@@ -1659,8 +1704,14 @@ public class TraversalMethodVisitor extends 
TraversalRootVisitor<GraphTraversal>
      */
     @Override
     public GraphTraversal visitTraversalMethod_tail_Scope_long(final 
GremlinParser.TraversalMethod_tail_Scope_longContext ctx) {
-        return 
graphTraversal.tail(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class,
 ctx.traversalScope()),
-                
antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
+        final Object literalOrVar = 
antlr.argumentVisitor.parseLong(ctx.integerArgument());
+        if (GValue.valueInstanceOf(literalOrVar, GType.LONG)) {
+            return 
graphTraversal.tail(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class,
 ctx.traversalScope()),
+                    (GValue<Long>) literalOrVar);
+        } else {
+            return 
graphTraversal.tail(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class,
 ctx.traversalScope()),
+                    (Long) literalOrVar);
+        }
     }
 
     /**
@@ -1668,7 +1719,12 @@ public class TraversalMethodVisitor extends 
TraversalRootVisitor<GraphTraversal>
      */
     @Override
     public GraphTraversal visitTraversalMethod_tail_long(final 
GremlinParser.TraversalMethod_tail_longContext ctx) {
-        return 
graphTraversal.tail(antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
+        final Object literalOrVar = 
antlr.argumentVisitor.parseLong(ctx.integerArgument());
+        if (GValue.valueInstanceOf(literalOrVar, GType.LONG)) {
+            return graphTraversal.tail((GValue<Long>) literalOrVar);
+        } else {
+            return graphTraversal.tail((Long) literalOrVar);
+        }
     }
 
     /**
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 a876193578..c93b150002 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
@@ -3112,6 +3112,21 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
         return this.asAdmin().addStep(new RangeGlobalStep<>(this.asAdmin(), 
low, high));
     }
 
+    /**
+     * Filter the objects in the traversal by the number of them to pass 
through the stream. Those before the value
+     * of {@code low} do not pass through and those that exceed the value of 
{@code high} will end the iteration.
+     *
+     * @param low  the number at which to start allowing objects through the 
stream
+     * @param high the number at which to end the stream - use {@code -1} to 
emit all remaining objects
+     * @return the traversal with an appended {@link RangeGlobalStep}
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#range-step";
 target="_blank">Reference Documentation - Range Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, E> range(final GValue<Long> low, final 
GValue<Long> high) {
+        this.asAdmin().getGremlinLang().addStep(Symbols.range, low, high);
+        return this.asAdmin().addStep(new RangeGlobalStep<>(this.asAdmin(), 
low, high));
+    }
+
     /**
      * Filter the objects in the traversal by the number of them to pass 
through the stream as constrained by the
      * {@link Scope}. Those before the value of {@code low} do not pass 
through and those that exceed the value of
@@ -3131,6 +3146,25 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
                 : new RangeLocalStep<>(this.asAdmin(), low, high));
     }
 
+    /**
+     * Filter the objects in the traversal by the number of them to pass 
through the stream as constrained by the
+     * {@link Scope}. Those before the value of {@code low} do not pass 
through and those that exceed the value of
+     * {@code high} will end the iteration.
+     *
+     * @param scope the scope of how to apply the {@code range}
+     * @param low   the number at which to start allowing objects through the 
stream
+     * @param high  the number at which to end the stream - use {@code -1} to 
emit all remaining objects
+     * @return the traversal with an appended {@link RangeGlobalStep} or 
{@link RangeLocalStep} depending on {@code scope}
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#range-step";
 target="_blank">Reference Documentation - Range Step</a>
+     * @since 4.0.0
+     */
+    public default <E2> GraphTraversal<S, E2> range(final Scope scope, final 
GValue<Long> low, final GValue<Long> high) {
+        this.asAdmin().getGremlinLang().addStep(Symbols.range, scope, low, 
high);
+        return this.asAdmin().addStep(scope.equals(Scope.global)
+                ? new RangeGlobalStep<>(this.asAdmin(), low, high)
+                : new RangeLocalStep<>(this.asAdmin(), low, high));
+    }
+
     /**
      * Filter the objects in the traversal by the number of them to pass 
through the stream, where only the first
      * {@code n} objects are allowed as defined by the {@code limit} argument.
@@ -3145,6 +3179,20 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
         return this.asAdmin().addStep(new RangeGlobalStep<>(this.asAdmin(), 0, 
limit));
     }
 
+    /**
+     * Filter the objects in the traversal by the number of them to pass 
through the stream, where only the first
+     * {@code n} objects are allowed as defined by the {@code limit} argument.
+     *
+     * @param limit the number at which to end the stream
+     * @return the traversal with an appended {@link RangeGlobalStep}
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#limit-step";
 target="_blank">Reference Documentation - Limit Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, E> limit(final GValue<Long> limit) {
+        this.asAdmin().getGremlinLang().addStep(Symbols.limit, limit);
+        return this.asAdmin().addStep(new RangeGlobalStep<>(this.asAdmin(), 
GValue.ofLong(null, 0L), limit));
+    }
+
     /**
      * Filter the objects in the traversal by the number of them to pass 
through the stream given the {@link Scope},
      * where only the first {@code n} objects are allowed as defined by the 
{@code limit} argument.
@@ -3162,6 +3210,23 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
                 : new RangeLocalStep<>(this.asAdmin(), 0, limit));
     }
 
+    /**
+     * Filter the objects in the traversal by the number of them to pass 
through the stream given the {@link Scope},
+     * where only the first {@code n} objects are allowed as defined by the 
{@code limit} argument.
+     *
+     * @param scope the scope of how to apply the {@code limit}
+     * @param limit the number at which to end the stream
+     * @return the traversal with an appended {@link RangeGlobalStep} or 
{@link RangeLocalStep} depending on {@code scope}
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#limit-step";
 target="_blank">Reference Documentation - Limit Step</a>
+     * @since 4.0.0
+     */
+    public default <E2> GraphTraversal<S, E2> limit(final Scope scope, final 
GValue<Long> limit) {
+        this.asAdmin().getGremlinLang().addStep(Symbols.limit, scope, limit);
+        return this.asAdmin().addStep(scope.equals(Scope.global)
+                ? new RangeGlobalStep<>(this.asAdmin(), GValue.ofLong(null, 
0L), limit)
+                : new RangeLocalStep<>(this.asAdmin(), GValue.ofLong(null, 
0L), limit));
+    }
+
     /**
      * Filters the objects in the traversal emitted as being last objects in 
the stream. In this case, only the last
      * object will be returned.
@@ -3189,6 +3254,20 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
         return this.asAdmin().addStep(new TailGlobalStep<>(this.asAdmin(), 
limit));
     }
 
+    /**
+     * Filters the objects in the traversal emitted as being last objects in 
the stream. In this case, only the last
+     * {@code n} objects will be returned as defined by the {@code limit}.
+     *
+     * @param limit the number at which to end the stream
+     * @return the traversal with an appended {@link TailGlobalStep}
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#tail-step"; 
target="_blank">Reference Documentation - Tail Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, E> tail(final GValue<Long> limit) {
+        this.asAdmin().getGremlinLang().addStep(Symbols.tail, limit);
+        return this.asAdmin().addStep(new TailGlobalStep<>(this.asAdmin(), 
limit));
+    }
+
     /**
      * Filters the objects in the traversal emitted as being last objects in 
the stream given the {@link Scope}. In
      * this case, only the last object in the stream will be returned.
@@ -3222,6 +3301,23 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
                 : new TailLocalStep<>(this.asAdmin(), limit));
     }
 
+    /**
+     * Filters the objects in the traversal emitted as being last objects in 
the stream given the {@link Scope}. In
+     * this case, only the last {@code n} objects will be returned as defined 
by the {@code limit}.
+     *
+     * @param scope the scope of how to apply the {@code tail}
+     * @param limit the number at which to end the stream
+     * @return the traversal with an appended {@link TailGlobalStep} or {@link 
TailLocalStep} depending on {@code scope}
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#tail-step"; 
target="_blank">Reference Documentation - Tail Step</a>
+     * @since 4.0.0
+     */
+    public default <E2> GraphTraversal<S, E2> tail(final Scope scope, final 
GValue<Long> limit) {
+        this.asAdmin().getGremlinLang().addStep(Symbols.tail, scope, limit);
+        return this.asAdmin().addStep(scope.equals(Scope.global)
+                ? new TailGlobalStep<>(this.asAdmin(), limit)
+                : new TailLocalStep<>(this.asAdmin(), limit));
+    }
+
     /**
      * Filters out the first {@code n} objects in the traversal.
      *
@@ -3235,6 +3331,19 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
         return this.asAdmin().addStep(new RangeGlobalStep<>(this.asAdmin(), 
skip, -1));
     }
 
+    /**
+     * Filters out the first {@code n} objects in the traversal.
+     *
+     * @param skip the number of objects to skip
+     * @return the traversal with an appended {@link RangeGlobalStep}
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#skip-step"; 
target="_blank">Reference Documentation - Skip Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, E> skip(final GValue<Long> skip) {
+        this.asAdmin().getGremlinLang().addStep(Symbols.skip, skip);
+        return this.asAdmin().addStep(new RangeGlobalStep<>(this.asAdmin(), 
skip, GValue.ofLong(null, -1L)));
+    }
+
     /**
      * Filters out the first {@code n} objects in the traversal.
      *
@@ -3251,6 +3360,22 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
                 : new RangeLocalStep<>(this.asAdmin(), skip, -1));
     }
 
+    /**
+     * Filters out the first {@code n} objects in the traversal.
+     *
+     * @param scope the scope of how to apply the {@code tail}
+     * @param skip  the number of objects to skip
+     * @return the traversal with an appended {@link RangeGlobalStep} or 
{@link RangeLocalStep} depending on {@code scope}
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#skip-step"; 
target="_blank">Reference Documentation - Skip Step</a>
+     * @since 4.0.0
+     */
+    public default <E2> GraphTraversal<S, E2> skip(final Scope scope, final 
GValue<Long> skip) {
+        this.asAdmin().getGremlinLang().addStep(Symbols.skip, scope, skip);
+        return this.asAdmin().addStep(scope.equals(Scope.global)
+                ? new RangeGlobalStep<>(this.asAdmin(), skip, 
GValue.ofLong(null, -1L))
+                : new RangeLocalStep<>(this.asAdmin(), skip, 
GValue.ofLong(null, -1L)));
+    }
+
     /**
      * Once the first {@link Traverser} hits this step, a count down is 
started. Once the time limit is up, all remaining traversers are filtered out.
      *
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 ac882fe31a..05632f25d6 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
@@ -1306,6 +1306,13 @@ public class __ {
         return __.<A>start().range(low, high);
     }
 
+    /**
+     * @see GraphTraversal#range(long, long)
+     */
+    public static <A> GraphTraversal<A, A> range(final GValue<Long> low, final 
GValue<Long> high) {
+        return __.<A>start().range(low, high);
+    }
+
     /**
      * @see GraphTraversal#range(Scope, long, long)
      */
@@ -1313,6 +1320,13 @@ public class __ {
         return __.<A>start().range(scope, low, high);
     }
 
+    /**
+     * @see GraphTraversal#range(Scope, long, long)
+     */
+    public static <A> GraphTraversal<A, A> range(final Scope scope, final 
GValue<Long> low, final GValue<Long> high) {
+        return __.<A>start().range(scope, low, high);
+    }
+
     /**
      * @see GraphTraversal#limit(long)
      */
@@ -1320,6 +1334,13 @@ public class __ {
         return __.<A>start().limit(limit);
     }
 
+    /**
+     * @see GraphTraversal#limit(long)
+     */
+    public static <A> GraphTraversal<A, A> limit(final GValue<Long> limit) {
+        return __.<A>start().limit(limit);
+    }
+
     /**
      * @see GraphTraversal#limit(Scope, long)
      */
@@ -1327,6 +1348,13 @@ public class __ {
         return __.<A>start().limit(scope, limit);
     }
 
+    /**
+     * @see GraphTraversal#limit(Scope, long)
+     */
+    public static <A> GraphTraversal<A, A> limit(final Scope scope, final 
GValue<Long> limit) {
+        return __.<A>start().limit(scope, limit);
+    }
+
     /**
      * @see GraphTraversal#skip(long)
      */
@@ -1334,6 +1362,13 @@ public class __ {
         return __.<A>start().skip(skip);
     }
 
+    /**
+     * @see GraphTraversal#skip(long)
+     */
+    public static <A> GraphTraversal<A, A> skip(final GValue<Long> skip) {
+        return __.<A>start().skip(skip);
+    }
+
     /**
      * @see GraphTraversal#skip(Scope, long)
      */
@@ -1341,6 +1376,13 @@ public class __ {
         return __.<A>start().skip(scope, skip);
     }
 
+    /**
+     * @see GraphTraversal#skip(Scope, long)
+     */
+    public static <A> GraphTraversal<A, A> skip(final Scope scope, final 
GValue<Long> skip) {
+        return __.<A>start().skip(scope, skip);
+    }
+
     /**
      * @see GraphTraversal#tail()
      */
@@ -1355,6 +1397,13 @@ public class __ {
         return __.<A>start().tail(limit);
     }
 
+    /**
+     * @see GraphTraversal#tail(long)
+     */
+    public static <A> GraphTraversal<A, A> tail(final GValue<Long> limit) {
+        return __.<A>start().tail(limit);
+    }
+
     /**
      * @see GraphTraversal#tail(Scope)
      */
@@ -1369,6 +1418,13 @@ public class __ {
         return __.<A>start().tail(scope, limit);
     }
 
+    /**
+     * @see GraphTraversal#tail(Scope, long)
+     */
+    public static <A> GraphTraversal<A, A> tail(final Scope scope, final 
GValue<Long> limit) {
+        return __.<A>start().tail(scope, limit);
+    }
+
     /**
      * @see GraphTraversal#simplePath()
      */
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java
index 9824332785..7b6fc721ab 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java
@@ -23,6 +23,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Bypassing;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Ranging;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
@@ -44,14 +45,18 @@ import java.util.function.BinaryOperator;
  */
 public final class RangeGlobalStep<S> extends FilterStep<S> implements 
Ranging, Bypassing, Barrier<TraverserSet<S>> {
 
-    private long low;
-    private final long high;
+    private GValue<Long> low;
+    private final GValue<Long> high;
     private AtomicLong counter = new AtomicLong(0l);
     private boolean bypass;
 
     public RangeGlobalStep(final Traversal.Admin traversal, final long low, 
final long high) {
+        this(traversal, GValue.ofLong(null, low), GValue.ofLong(null, high));
+    }
+
+    public RangeGlobalStep(final Traversal.Admin traversal, final GValue<Long> 
low, final GValue<Long> high) {
         super(traversal);
-        if (low != -1 && high != -1 && low > high) {
+        if (low.get() != -1 && high.get() != -1 && low.get() > high.get()) {
             throw new IllegalArgumentException("Not a legal range: [" + low + 
", " + high + ']');
         }
         this.low = low;
@@ -62,12 +67,12 @@ public final class RangeGlobalStep<S> extends FilterStep<S> 
implements Ranging,
     protected boolean filter(final Traverser.Admin<S> traverser) {
         if (this.bypass) return true;
 
-        if (this.high != -1 && this.counter.get() >= this.high) {
+        if (this.high.get() != -1 && this.counter.get() >= this.high.get()) {
             throw FastNoSuchElementException.instance();
         }
 
         long avail = traverser.bulk();
-        if (this.counter.get() + avail <= this.low) {
+        if (this.counter.get() + avail <= this.low.get()) {
             // Will not surpass the low w/ this traverser. Skip and filter the 
whole thing.
             this.counter.getAndAdd(avail);
             return false;
@@ -76,13 +81,13 @@ public final class RangeGlobalStep<S> extends FilterStep<S> 
implements Ranging,
         // Skip for the low and trim for the high. Both can happen at once.
 
         long toSkip = 0;
-        if (this.counter.get() < this.low) {
-            toSkip = this.low - this.counter.get();
+        if (this.counter.get() < this.low.get()) {
+            toSkip = this.low.get() - this.counter.get();
         }
 
         long toTrim = 0;
-        if (this.high != -1 && this.counter.get() + avail >= this.high) {
-            toTrim = this.counter.get() + avail - this.high;
+        if (this.high.get() != -1 && this.counter.get() + avail >= 
this.high.get()) {
+            toTrim = this.counter.get() + avail - this.high.get();
         }
 
         long toEmit = avail - toSkip - toTrim;
@@ -100,17 +105,17 @@ public final class RangeGlobalStep<S> extends 
FilterStep<S> implements Ranging,
 
     @Override
     public String toString() {
-        return StringFactory.stepString(this, this.low, this.high);
+        return StringFactory.stepString(this, this.low.get(), this.high.get());
     }
 
     @Override
     public long getLowRange() {
-        return this.low;
+        return this.low.get();
     }
 
     @Override
     public long getHighRange() {
-        return this.high;
+        return this.high.get();
     }
 
     @Override
@@ -122,14 +127,14 @@ public final class RangeGlobalStep<S> extends 
FilterStep<S> implements Ranging,
 
     @Override
     public int hashCode() {
-        return super.hashCode() ^ Long.hashCode(this.low) ^ 
Long.hashCode(this.high);
+        return super.hashCode() ^ Long.hashCode(this.low.get()) ^ 
Long.hashCode(this.high.get());
     }
 
     @Override
     public boolean equals(final Object other) {
         if (super.equals(other)) {
             final RangeGlobalStep typedOther = (RangeGlobalStep) other;
-            return typedOther.low == this.low && typedOther.high == this.high;
+            return typedOther.low.get() == this.low.get() && 
typedOther.high.get() == this.high.get();
         }
         return false;
     }
@@ -142,7 +147,7 @@ public final class RangeGlobalStep<S> extends FilterStep<S> 
implements Ranging,
 
     @Override
     public MemoryComputeKey<TraverserSet<S>> getMemoryComputeKey() {
-        return MemoryComputeKey.of(this.getId(), new 
RangeBiOperator<>(this.high), false, true);
+        return MemoryComputeKey.of(this.getId(), new 
RangeBiOperator<>(this.high.get()), false, true);
     }
 
     @Override
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailGlobalStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailGlobalStep.java
index cc746c8bb3..293eba24de 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailGlobalStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailGlobalStep.java
@@ -23,6 +23,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Bypassing;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
@@ -41,15 +42,19 @@ import java.util.Set;
  */
 public final class TailGlobalStep<S> extends AbstractStep<S, S> implements 
Bypassing, Barrier<TraverserSet<S>> {
 
-    private final long limit;
+    private final GValue<Long> limit;
     private Deque<Traverser.Admin<S>> tail;
     private long tailBulk = 0L;
     private boolean bypass = false;
 
     public TailGlobalStep(final Traversal.Admin traversal, final long limit) {
+        this(traversal, GValue.ofLong(null, limit));
+    }
+
+    public TailGlobalStep(final Traversal.Admin traversal, final GValue<Long> 
limit) {
         super(traversal);
         this.limit = limit;
-        this.tail = new ArrayDeque<>((int) limit);
+        this.tail = new ArrayDeque<>(limit.get().intValue());
     }
 
     public void setBypass(final boolean bypass) {
@@ -69,7 +74,7 @@ public final class TailGlobalStep<S> extends AbstractStep<S, 
S> implements Bypas
             // Pull the oldest traverser from the tail buffer.
             final Traverser.Admin<S> oldest = this.tail.pop();
             // Trim any excess from the oldest traverser.
-            final long excess = this.tailBulk - this.limit;
+            final long excess = this.tailBulk - this.limit.get();
             if (excess > 0) {
                 oldest.setBulk(oldest.bulk() - excess);
                 // Account for the loss of excess in the tail buffer
@@ -90,20 +95,20 @@ public final class TailGlobalStep<S> extends 
AbstractStep<S, S> implements Bypas
 
     @Override
     public String toString() {
-        return StringFactory.stepString(this, this.limit);
+        return StringFactory.stepString(this, this.limit.get());
     }
 
     @Override
     public TailGlobalStep<S> clone() {
         final TailGlobalStep<S> clone = (TailGlobalStep<S>) super.clone();
-        clone.tail = new ArrayDeque<>((int) this.limit);
+        clone.tail = new ArrayDeque<>(this.limit.get().intValue());
         clone.tailBulk = 0L;
         return clone;
     }
 
     @Override
     public int hashCode() {
-        return super.hashCode() ^ Long.hashCode(this.limit);
+        return super.hashCode() ^ Long.hashCode(this.limit.get());
     }
 
     @Override
@@ -118,7 +123,7 @@ public final class TailGlobalStep<S> extends 
AbstractStep<S, S> implements Bypas
         while (!this.tail.isEmpty()) {
             final Traverser.Admin<S> oldest = this.tail.getFirst();
             final long bulk = oldest.bulk();
-            if (this.tailBulk - bulk < limit)
+            if (this.tailBulk - bulk < limit.get())
                 break;
             this.tail.pop();
             this.tailBulk -= bulk;
@@ -129,7 +134,7 @@ public final class TailGlobalStep<S> extends 
AbstractStep<S, S> implements Bypas
 
     @Override
     public MemoryComputeKey<TraverserSet<S>> getMemoryComputeKey() {
-        return MemoryComputeKey.of(this.getId(), new 
RangeGlobalStep.RangeBiOperator<>(this.limit), false, true);
+        return MemoryComputeKey.of(this.getId(), new 
RangeGlobalStep.RangeBiOperator<>(this.limit.get()), false, true);
     }
 
     @Override
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
index 19b26af911..a1052be995 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
@@ -21,6 +21,7 @@ package 
org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import 
org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -39,12 +40,16 @@ import java.util.Set;
  */
 public final class RangeLocalStep<S> extends ScalarMapStep<S, S> {
 
-    private final long low;
-    private final long high;
+    private final GValue<Long> low;
+    private final GValue<Long> high;
 
     public RangeLocalStep(final Traversal.Admin traversal, final long low, 
final long high) {
+        this(traversal, GValue.ofLong(null, low), GValue.ofLong(null, high));
+    }
+
+    public RangeLocalStep(final Traversal.Admin traversal, final GValue<Long> 
low, final GValue<Long> high) {
         super(traversal);
-        if (low != -1 && high != -1 && low > high) {
+        if (low.get() != -1 && high.get() != -1 && low.get() > high.get()) {
             throw new IllegalArgumentException("Not a legal range: [" + low + 
", " + high + ']');
         }
         this.low = low;
@@ -52,18 +57,18 @@ public final class RangeLocalStep<S> extends 
ScalarMapStep<S, S> {
     }
 
     public long getLowRange() {
-        return this.low;
+        return this.low.get();
     }
  
     public long getHighRange() {
-        return this.high;
+        return this.high.get();
     } 
  
 
     @Override
     protected S map(final Traverser.Admin<S> traverser) {
         final S start = traverser.get();
-        return applyRange(start, this.low, this.high);
+        return applyRange(start, this.low.get(), this.high.get());
     }
 
     /**
@@ -146,12 +151,12 @@ public final class RangeLocalStep<S> extends 
ScalarMapStep<S, S> {
 
     @Override
     public String toString() {
-        return StringFactory.stepString(this, this.low, this.high);
+        return StringFactory.stepString(this, this.low.get(), this.high.get());
     }
 
     @Override
     public int hashCode() {
-        return super.hashCode() ^ Long.hashCode(this.high) ^ 
Long.hashCode(this.low);
+        return super.hashCode() ^ Long.hashCode(this.high.get()) ^ 
Long.hashCode(this.low.get());
     }
 
     @Override
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
index 9f9770644f..2dbe084db8 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
@@ -22,6 +22,7 @@ package 
org.apache.tinkerpop.gremlin.process.traversal.step.map;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
@@ -36,9 +37,13 @@ import java.util.Set;
  */
 public final class TailLocalStep<S> extends ScalarMapStep<S, S> {
 
-    private final long limit;
+    private final GValue<Long> limit;
 
     public TailLocalStep(final Traversal.Admin traversal, final long limit) {
+        this(traversal, GValue.ofLong(null, limit));
+    }
+
+    public TailLocalStep(final Traversal.Admin traversal, final GValue<Long> 
limit) {
         super(traversal);
         this.limit = limit;
     }
@@ -55,19 +60,19 @@ public final class TailLocalStep<S> extends 
ScalarMapStep<S, S> {
                                 start instanceof Path ? ((Path) start).size() :
                                         start instanceof Iterable ? 
IteratorUtils.count((Iterable) start) :
                                                 
IteratorUtils.count(IteratorUtils.asIterator(start));
-        final long low = high - this.limit;
+        final long low = high - this.limit.get();
         final S result = RangeLocalStep.applyRange(start, low, high);
         return result;
     }
 
     @Override
     public String toString() {
-        return StringFactory.stepString(this, this.limit);
+        return StringFactory.stepString(this, this.limit.get());
     }
 
     @Override
     public int hashCode() {
-        return super.hashCode() ^ Long.hashCode(this.limit);
+        return super.hashCode() ^ Long.hashCode(this.limit.get());
     }
 
     @Override
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 
b/gremlin-language/src/main/antlr4/Gremlin.g4
index 8133e751ad..422166578e 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -588,8 +588,8 @@ traversalMethod_label
     ;
 
 traversalMethod_limit
-    : 'limit' LPAREN traversalScope COMMA integerLiteral RPAREN 
#traversalMethod_limit_Scope_long
-    | 'limit' LPAREN integerLiteral RPAREN #traversalMethod_limit_long
+    : 'limit' LPAREN traversalScope COMMA integerArgument RPAREN 
#traversalMethod_limit_Scope_long
+    | 'limit' LPAREN integerArgument RPAREN #traversalMethod_limit_long
     ;
 
 traversalMethod_local
@@ -720,8 +720,8 @@ traversalMethod_propertyMap
     ;
 
 traversalMethod_range
-    : 'range' LPAREN traversalScope COMMA integerLiteral COMMA integerLiteral 
RPAREN #traversalMethod_range_Scope_long_long
-    | 'range' LPAREN integerLiteral COMMA integerLiteral RPAREN 
#traversalMethod_range_long_long
+    : 'range' LPAREN traversalScope COMMA integerArgument COMMA 
integerArgument RPAREN #traversalMethod_range_Scope_long_long
+    | 'range' LPAREN integerArgument COMMA integerArgument RPAREN 
#traversalMethod_range_long_long
     ;
 
 traversalMethod_read
@@ -770,8 +770,8 @@ traversalMethod_simplePath
     ;
 
 traversalMethod_skip
-    : 'skip' LPAREN traversalScope COMMA integerLiteral RPAREN 
#traversalMethod_skip_Scope_long
-    | 'skip' LPAREN integerLiteral RPAREN #traversalMethod_skip_long
+    : 'skip' LPAREN traversalScope COMMA integerArgument RPAREN 
#traversalMethod_skip_Scope_long
+    | 'skip' LPAREN integerArgument RPAREN #traversalMethod_skip_long
     ;
 
 traversalMethod_store
@@ -790,8 +790,8 @@ traversalMethod_sum
 traversalMethod_tail
     : 'tail' LPAREN RPAREN #traversalMethod_tail_Empty
     | 'tail' LPAREN traversalScope RPAREN #traversalMethod_tail_Scope
-    | 'tail' LPAREN traversalScope COMMA integerLiteral RPAREN 
#traversalMethod_tail_Scope_long
-    | 'tail' LPAREN integerLiteral RPAREN #traversalMethod_tail_long
+    | 'tail' LPAREN traversalScope COMMA integerArgument RPAREN 
#traversalMethod_tail_Scope_long
+    | 'tail' LPAREN integerArgument RPAREN #traversalMethod_tail_long
     ;
 
 traversalMethod_fail


Reply via email to