You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2021/11/05 14:02:35 UTC

[tinkerpop] 01/01: TINKERPOP-2524 Supported more explicit numeric literals in grammar

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

spmallette pushed a commit to branch TINKERPOP-2524
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit c2b4f2fc0a02e0022602978faf21bea205e56460
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Fri Nov 5 09:57:00 2021 -0400

    TINKERPOP-2524 Supported more explicit numeric literals in grammar
    
    Added byte, short, BigInteger, BigDecimal which basically just follows the pattern Java/Groovy have with a character suffix. While these literals have some specific use for Gremlin users they also have importance to the gherkin test suite where validating numeric semantics required a wider range of numeric types in the test definitions.
---
 CHANGELOG.asciidoc                                 |   1 +
 docs/src/dev/developer/for-committers.asciidoc     |   9 +-
 .../language/grammar/GenericLiteralVisitor.java    |  40 ++++--
 .../grammar/GeneralLiteralVisitorTest.java         | 133 +++++++++---------
 .../Gherkin/CommonSteps.cs                         |   8 +-
 .../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs |   7 +
 .../test/cucumber/feature-steps.js                 |   2 +-
 .../gremlin-javascript/test/cucumber/gremlin.js    |   7 +
 gremlin-language/src/main/antlr4/Gremlin.g4        |   4 +-
 .../src/main/python/radish/feature_steps.py        |   2 +-
 gremlin-python/src/main/python/radish/gremlin.py   |   7 +
 .../server/handler/SaslAuthenticationHandler.java  |   3 +-
 gremlin-test/features/semantics/Equality.feature   | 156 ++++++++++++++++++++-
 .../tinkerpop/gremlin/features/StepDefinition.java |  11 +-
 14 files changed, 291 insertions(+), 99 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index af06a51..f2c6522 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -31,6 +31,7 @@ limitations under the License.
 * Removed `groovy` and `groovy-json` dependencies from `gremlin-driver` as well as related `JsonBuilder` serialization support.
 * Replaced log4j usage with logback where builds rely on and packaged distributions now contain the latter.
 * Prevented metrics computation unless the traversal is in a locked state.
+* Added syntax to Gremlin grammar to explicitly define `byte`, `short` and `BigInteger`.
 * Created a way to produce a corpus of Gremlin traversals via `FeatureReader` and `DocumentationReader` in `gremlin-language`.
 * Exposed Gherkin tests as part of the provider test suite.
 * Packaged Gherkin tests and data as standalone package as a convenience distribution.
diff --git a/docs/src/dev/developer/for-committers.asciidoc b/docs/src/dev/developer/for-committers.asciidoc
index 33465ee..c3c3453 100644
--- a/docs/src/dev/developer/for-committers.asciidoc
+++ b/docs/src/dev/developer/for-committers.asciidoc
@@ -357,11 +357,14 @@ they are required for the test.
 the type notation system so that it is possible to have maps containing arbitrary keys and values.
 * Numeric - *d[_xxx_]._y_* - The "xxx" should be replaced with a number. The suffix denoted by "y" should always be
 included to further qualify the type of numeric. The following options are available:
-** *d* - 32-bit Double
-** *f* - 32-bit Float
+** *b* - 8-bit byte
+** *s* - 16-bit Short
 ** *i* - 32-bit Integer
+** *f* - 32-bit Float
 ** *l* - 64-bit Long
-** *m* - Arbitrary-precision signed decimal numbers (i.e. BigDecimal in Java)
+** *d* - 64-bit Double
+** *m* - Arbitrary-precision signed decimal numbers (e.g. `BigDecimal` in Java)
+** *n* - Arbitrary-precision integers (e.g. `BigInteger` in Java)
 * Path - *p[_xxx_,_yyy_,_zzz_,...]* - A comma separated collection of values that make up the `Path` should be added to
 between the square brackets. These values respect the type system thus allowing for creation of `Path` of vertices,
 edges, maps, and any other available type.
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
index 1529392..1d93387 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
@@ -308,12 +308,25 @@ public class GenericLiteralVisitor extends GremlinBaseVisitor<Object> {
     @Override
     public Object visitIntegerLiteral(final GremlinParser.IntegerLiteralContext ctx) {
         String integerLiteral = ctx.getText().toLowerCase().replace("_", "");
-        // handle suffix: L/l
+        // handle suffixes for specific types
         final int lastCharIndex = integerLiteral.length() - 1;
-        if (integerLiteral.charAt(lastCharIndex) == 'l') {
-            integerLiteral = integerLiteral.substring(0, lastCharIndex);
-
-            return Long.decode(integerLiteral);
+        final char suffix = integerLiteral.charAt(lastCharIndex);
+        switch (suffix) {
+            case 'b':
+                integerLiteral = integerLiteral.substring(0, lastCharIndex);
+                return Byte.decode(integerLiteral);
+            case 's':
+                integerLiteral = integerLiteral.substring(0, lastCharIndex);
+                return Short.decode(integerLiteral);
+            case 'i':
+                integerLiteral = integerLiteral.substring(0, lastCharIndex);
+                return Integer.decode(integerLiteral);
+            case 'l':
+                integerLiteral = integerLiteral.substring(0, lastCharIndex);
+                return Long.decode(integerLiteral);
+            case 'n':
+                integerLiteral = integerLiteral.substring(0, lastCharIndex);
+                return new BigInteger(integerLiteral);
         }
 
         try {
@@ -363,18 +376,19 @@ public class GenericLiteralVisitor extends GremlinBaseVisitor<Object> {
         final String floatLiteral = ctx.getText().toLowerCase();
 
         // check suffix
-        final char lastCharacter = floatLiteral.charAt(floatLiteral.length() - 1);
-        if (Character.isDigit(lastCharacter)) {
-            // if there is no suffix, parse it as BigDecimal
-            return new BigDecimal(floatLiteral);
-        }
-
-        if (lastCharacter == 'f') {
+        final int lastCharIndex = floatLiteral.length() - 1;
+        final char lastCharacter = floatLiteral.charAt(lastCharIndex);
+        if (lastCharacter == 'm') {
+            // parse M/m or whatever which could be a parse exception
+            return new BigDecimal(floatLiteral.substring(0, lastCharIndex));
+        } else if (lastCharacter == 'f') {
             // parse F/f suffix as Float
             return new Float(ctx.getText());
-        } else {
+        } else if (lastCharacter == 'd'){
             // parse D/d suffix as Double
             return new Double(floatLiteral);
+        } else {
+            return new BigDecimal(floatLiteral);
         }
     }
 
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
index c8a350e..7791a08 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
@@ -292,44 +292,54 @@ public class GeneralLiteralVisitorTest {
         public String script;
 
         @Parameterized.Parameter(value = 1)
-        public String expected;
+        public Object expected;
 
         @Parameterized.Parameters(name = "{0}")
         public static Iterable<Object[]> generateTestParameters() {
             return Arrays.asList(new Object[][]{
                     // decimal format
-                    {"1", "1"},
-                    {"-11", "-11"},
-                    {"0", "0"},
-                    {"1L", "1L"},
-                    {"-1l", "-1l"},
-                    {"1_2_3", "123"},
-                    {"-1_2_3L", "-123L"},
-                    {"9223372036854775807", "9223372036854775807"},
-                    {"-9223372036854775808", "-9223372036854775808"},
-                    {"9223372036854775807L", "9223372036854775807"},
-                    {"-9223372036854775808l", "-9223372036854775808"},
+                    {"1", 1},
+                    {"-11", -11},
+                    {"0", 0},
+                    {"1B", (byte) 1},
+                    {"-1b", (byte) -1},
+                    {"1S", (short) 1},
+                    {"-1s", (short) -1},
+                    {"1I", 1},
+                    {"-1i", -1},
+                    {"1L", 1L},
+                    {"-1l", -1L},
+                    {"1_2_3", 123},
+                    {"-1_2_3L", -123L},
+                    {"1N", new BigInteger("1")},
+                    {"-1n", new BigInteger("-1")},
+                    {"9223372036854775807", 9223372036854775807L},
+                    {"-9223372036854775808", -9223372036854775808L},
+                    {"9223372036854775807L", 9223372036854775807L},
+                    {"-9223372036854775808l", -9223372036854775808L},
+                    {"9999999999999999999999999999999999999999999999999N", new BigInteger("9999999999999999999999999999999999999999999999999")},
+                    {"9999999999999999999999999999999999999999999999999n", new BigInteger("9999999999999999999999999999999999999999999999999")},
                     // hex format
-                    {"0xA", "10"},
-                    {"-0xA", "-10"},
-                    {"0xaL", "10l"},
-                    {"-0xal", "-10l"},
-                    {"-0xA_0L", "-160l"},
-                    {"0x10", "16"},
-                    {"-0x10", "-16"},
-                    {"0x10", "16"},
-                    {"-0x10l", "-16l"},
-                    {"-0x1_0L", "-16l"},
+                    {"0xA", 10},
+                    {"-0xA", -10},
+                    {"0xaL", 10L},
+                    {"-0xal", -10L},
+                    {"-0xA_0L", -160L},
+                    {"0x10", 16},
+                    {"-0x10", -16},
+                    {"0x10", 16},
+                    {"-0x10l", -16L},
+                    {"-0x1_0L", -16L},
                     // oct format
-                    {"01", "1"},
-                    {"-01", "-1"},
-                    {"01L", "1l"},
-                    {"-01l", "-1l"},
-                    {"010", "8"},
-                    {"-010", "-8"},
-                    {"010L", "8l"},
-                    {"-010l", "-8l"},
-                    {"-01_0L", "-8l"},
+                    {"01", 1},
+                    {"-01", -1},
+                    {"01L", 1L},
+                    {"-01l", -1L},
+                    {"010", 8},
+                    {"-010", -8},
+                    {"010L", 8L},
+                    {"-010l", -8L},
+                    {"-01_0L", -8L},
             });
         }
 
@@ -340,19 +350,7 @@ public class GeneralLiteralVisitorTest {
             final GremlinParser.IntegerLiteralContext ctx = parser.integerLiteral();
 
             final Object actualValue = GenericLiteralVisitor.getInstance().visitIntegerLiteral(ctx);
-
-            // verify suffix L/l
-            if (expected.toUpperCase().charAt(expected.length() - 1) == 'L') {
-                assertEquals(Long.valueOf(expected.substring(0, expected.length() - 1)), actualValue);
-                return;
-            }
-
-            // based on value range verify the value is parsed in correct type
-            try {
-                assertEquals(Integer.valueOf(expected), actualValue);
-            } catch (NumberFormatException ignoredException) {
-                assertEquals(Long.valueOf(expected), actualValue);
-            }
+            assertEquals(expected, actualValue);
         }
     }
 
@@ -398,34 +396,33 @@ public class GeneralLiteralVisitorTest {
         public String script;
 
         @Parameterized.Parameter(value = 1)
-        public String expected;
-
-        @Parameterized.Parameter(value = 2)
-        public String type;
+        public Object expected;
 
         @Parameterized.Parameters()
         public static Iterable<Object[]> generateTestParameters() {
             return Arrays.asList(new Object[][]{
-                    {"1.1", "1.1", "java.math.BigDecimal"},
-                    {"-0.1", "-0.1", "java.math.BigDecimal"},
-                    {"1.0E+12", "1.0E12", "java.math.BigDecimal"},
-                    {"-0.1E-12", "-0.1E-12", "java.math.BigDecimal"},
-                    {"1E12", "1E12", "java.math.BigDecimal"},
+                    {"1.1m", new BigDecimal("1.1")},
+                    {"1.1M", new BigDecimal("1.1")},
+                    {"1.1", new BigDecimal("1.1")},
+                    {"-0.1", new BigDecimal("-0.1")},
+                    {"1.0E+12", new BigDecimal("1.0E12")},
+                    {"-0.1E-12", new BigDecimal("-0.1E-12")},
+                    {"1E12", new BigDecimal("1E12")},
                     // float
-                    {"1.1f", "1.1", "java.lang.Float"},
-                    {"-0.1F", "-0.1", "java.lang.Float"},
-                    {"1.0E+12f", "1.0E12", "java.lang.Float"},
-                    {"-0.1E-12F", "-0.1E-12", "java.lang.Float"},
-                    {"1E12f", "1E12", "java.lang.Float"},
-                    {"1F", "1", "java.lang.Float"},
+                    {"1.1f", 1.1F},
+                    {"-0.1F", -0.1F},
+                    {"1.0E+12f", 1.0E12F},
+                    {"-0.1E-12F", -0.1E-12F},
+                    {"1E12f", 1E12F},
+                    {"1F", 1F},
 
                     // double
-                    {"1.1d", "1.1", "java.lang.Double"},
-                    {"-0.1D", "-0.1", "java.lang.Double"},
-                    {"1.0E+12d", "1.0E12", "java.lang.Double"},
-                    {"-0.1E-12D", "-0.1E-12", "java.lang.Double"},
-                    {"1E12d", "1E12", "java.lang.Double"},
-                    {"1D", "1", "java.lang.Double"}
+                    {"1.1d", 1.1D},
+                    {"-0.1D", -0.1D},
+                    {"1.0E+12d", 1.0E12D},
+                    {"-0.1E-12D", -0.1E-12D},
+                    {"1E12d", 1E12D},
+                    {"1D", 1D}
             });
         }
 
@@ -435,11 +432,7 @@ public class GeneralLiteralVisitorTest {
             final GremlinParser parser = new GremlinParser(new CommonTokenStream(lexer));
             final GremlinParser.FloatLiteralContext ctx = parser.floatLiteral();
 
-            final Class<?> clazz = Class.forName(type);
-            final Constructor<?> ctor = clazz.getConstructor(String.class);
-            final Object expectedValue = ctor.newInstance(expected);
-
-            assertEquals(expectedValue, GenericLiteralVisitor.getInstance().visitFloatLiteral(ctx));
+            assertEquals(expected, GenericLiteralVisitor.getInstance().visitFloatLiteral(ctx));
         }
     }
 
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
index a2941eb..11e71c8 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
@@ -26,6 +26,7 @@ using System.Collections;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
+using System.Numerics;
 using System.Text.Json;
 using System.Text.RegularExpressions;
 using Gherkin.Ast;
@@ -54,7 +55,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
         private static readonly IDictionary<Regex, Func<string, string, object>> Parsers =
             new Dictionary<string, Func<string, string, object>>
             {
-                {@"d\[(.*)\]\.([ilfdm])", ToNumber},
+                {@"d\[(.*)\]\.([bsilfdmn])", ToNumber},
                 {@"D\[(.+)\]", ToDirection},
                 {@"v\[(.+)\]", ToVertex},
                 {@"v\[(.+)\]\.id", (x, graphName) => ToVertex(x, graphName).Id},
@@ -74,11 +75,14 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
         private static readonly IDictionary<char, Func<string, object>> NumericParsers =
             new Dictionary<char, Func<string, object>>
             {
+                { 'b', s => Convert.ToByte(s) },
+                { 's', s => Convert.ToInt16(s) },
                 { 'i', s => Convert.ToInt32(s) },
                 { 'l', s => Convert.ToInt64(s) },
                 { 'f', s => Convert.ToSingle(s, CultureInfo.InvariantCulture) },
                 { 'd', s => Convert.ToDouble(s, CultureInfo.InvariantCulture) },
-                { 'm', s => Convert.ToDecimal(s, CultureInfo.InvariantCulture) }
+                { 'm', s => Convert.ToDecimal(s, CultureInfo.InvariantCulture) },
+                { 'n', s => BigInteger.Parse(s) }
             };
 
         [Given("the (\\w+) graph")]
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 2c8d242..bb8565b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -686,7 +686,14 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_hasLabelXpersonX_V_hasLabelXsoftwareX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").V().HasLabel("software").Values<object>("name")}}, 
                {"g_V_hasLabelXloopsX_bothEXselfX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("loops").BothE("self")}}, 
                {"g_V_hasLabelXloopsX_bothXselfX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("loops").Both("self")}}, 
+               {"Primitives_Number_eqXbyteX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}}, 
+               {"Primitives_Number_eqXshortX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}}, 
                {"Primitives_Number_eqXintX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}}, 
+               {"Primitives_Number_eqXlongX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}}, 
+               {"Primitives_Number_eqXbigintX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}}, 
+               {"Primitives_Number_eqXfloatX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}}, 
+               {"Primitives_Number_eqXdoubleX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}}, 
+               {"Primitives_Number_eqXbigdecimalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}}, 
                {"g_V_valueXnameX_aggregateXxX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Aggregate("x").Cap<object>("x")}}, 
                {"g_V_valueXnameX_aggregateXglobal_xX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Aggregate(Scope.Global,"x").Cap<object>("x")}}, 
                {"g_V_aggregateXxX_byXnameX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("x").By("name").Cap<object>("x")}}, 
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
index 7a9c8ee..e9d39cf 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
@@ -42,7 +42,7 @@ const direction = traversalModule.direction;
 const mapAsObject = false;
 
 const parsers = [
-  [ 'd\\[(.*)\\]\\.[ilfdm]', toNumeric ],
+  [ 'd\\[(.*)\\]\\.[bsilfdmn]', toNumeric ],
   [ 'v\\[(.+)\\]', toVertex ],
   [ 'v\\[(.+)\\]\\.id', toVertexId ],
   [ 'v\\[(.+)\\]\\.sid', toVertexIdString ],
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index 8507405..a780192 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -675,7 +675,14 @@ const gremlins = {
     g_V_hasLabelXpersonX_V_hasLabelXsoftwareX_name: [function({g}) { return g.V().hasLabel("person").V().hasLabel("software").values("name") }], 
     g_V_hasLabelXloopsX_bothEXselfX: [function({g}) { return g.V().hasLabel("loops").bothE("self") }], 
     g_V_hasLabelXloopsX_bothXselfX: [function({g}) { return g.V().hasLabel("loops").both("self") }], 
+    Primitives_Number_eqXbyteX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }], 
+    Primitives_Number_eqXshortX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }], 
     Primitives_Number_eqXintX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }], 
+    Primitives_Number_eqXlongX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }], 
+    Primitives_Number_eqXbigintX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }], 
+    Primitives_Number_eqXfloatX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }], 
+    Primitives_Number_eqXdoubleX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }], 
+    Primitives_Number_eqXbigdecimalX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }], 
     g_V_valueXnameX_aggregateXxX_capXxX: [function({g}) { return g.V().values("name").aggregate("x").cap("x") }], 
     g_V_valueXnameX_aggregateXglobal_xX_capXxX: [function({g}) { return g.V().values("name").aggregate(Scope.global,"x").cap("x") }], 
     g_V_aggregateXxX_byXnameX_capXxX: [function({g}) { return g.V().aggregate("x").by("name").cap("x") }], 
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4
index 0844d67..e277baa 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -1362,7 +1362,7 @@ OctalIntegerLiteral
 
 fragment
 IntegerTypeSuffix
-	:	[lL]
+	:	[bBsSnNiIlL]
 	;
 
 fragment
@@ -1489,7 +1489,7 @@ Sign
 
 fragment
 FloatTypeSuffix
-	:	[fFdD]
+	:	[fFdDmM]
 	;
 
 // Boolean Literals
diff --git a/gremlin-python/src/main/python/radish/feature_steps.py b/gremlin-python/src/main/python/radish/feature_steps.py
index eb225bd..9fd8cf6 100644
--- a/gremlin-python/src/main/python/radish/feature_steps.py
+++ b/gremlin-python/src/main/python/radish/feature_steps.py
@@ -162,7 +162,7 @@ def _convert(val, ctx):
         return [] if val == "l[]" else list(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
     elif isinstance(val, str) and re.match(r"^s\[.*\]$", val):           # parse set
         return set() if val == "s[]" else set(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
-    elif isinstance(val, str) and re.match(r"^d\[.*\]\.[ilfdm]$", val):  # parse numeric
+    elif isinstance(val, str) and re.match(r"^d\[.*\]\.[bsilfdmn]$", val):  # parse numeric
         return float(val[2:-3]) if val[2:-3].__contains__(".") else long(val[2:-3])
     elif isinstance(val, str) and re.match(r"^v\[.*\]\.id$", val):       # parse vertex id
         return __find_cached_element(ctx, graph_name, val[2:-4], "v").id
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 5f9535a..0aa4c93 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -660,7 +660,14 @@ world.gremlins = {
     'g_V_hasLabelXpersonX_V_hasLabelXsoftwareX_name': [(lambda g:g.V().hasLabel('person').V().hasLabel('software').name)], 
     'g_V_hasLabelXloopsX_bothEXselfX': [(lambda g:g.V().hasLabel('loops').bothE('self'))], 
     'g_V_hasLabelXloopsX_bothXselfX': [(lambda g:g.V().hasLabel('loops').both('self'))], 
+    'Primitives_Number_eqXbyteX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))], 
+    'Primitives_Number_eqXshortX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))], 
     'Primitives_Number_eqXintX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))], 
+    'Primitives_Number_eqXlongX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))], 
+    'Primitives_Number_eqXbigintX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))], 
+    'Primitives_Number_eqXfloatX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))], 
+    'Primitives_Number_eqXdoubleX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))], 
+    'Primitives_Number_eqXbigdecimalX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))], 
     'g_V_valueXnameX_aggregateXxX_capXxX': [(lambda g:g.V().name.aggregate('x').cap('x'))], 
     'g_V_valueXnameX_aggregateXglobal_xX_capXxX': [(lambda g:g.V().name.aggregate(Scope.global_,'x').cap('x'))], 
     'g_V_aggregateXxX_byXnameX_capXxX': [(lambda g:g.V().aggregate('x').by('name').cap('x'))], 
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
index 2adc97f..848be27 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
@@ -156,8 +156,7 @@ public class SaslAuthenticationHandler extends AbstractAuthenticationHandler {
                     ctx.writeAndFlush(error);
                 }
             }
-        }
-        else {
+        } else {
             logger.warn("{} only processes RequestMessage instances - received {} - channel closing",
                     this.getClass().getSimpleName(), msg.getClass());
             ctx.close();
diff --git a/gremlin-test/features/semantics/Equality.feature b/gremlin-test/features/semantics/Equality.feature
index cb57121..58a1439 100644
--- a/gremlin-test/features/semantics/Equality.feature
+++ b/gremlin-test/features/semantics/Equality.feature
@@ -18,11 +18,52 @@
 @StepClassSemantics
 Feature: Equality
 
-  # TODO: TINKERPOP-2524 to support all the number types (and others required for semantics checks)
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: Primitives_Number_eqXbyteX
+    Given the empty graph
+    And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+    And using the parameter xx2 defined as "d[1].b"
+    And the traversal of
+      """
+      g.inject(xx1).unfold().where(__.is(xx2))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[1].i |
+      | d[1].l |
+      | d[1].f |
+      | d[1].d |
+      | d[1].s |
+      | d[1].n |
+      | d[1].m |
+      | d[1].b |
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: Primitives_Number_eqXshortX
+    Given the empty graph
+    And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+    And using the parameter xx2 defined as "d[1].s"
+    And the traversal of
+      """
+      g.inject(xx1).unfold().where(__.is(xx2))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[1].i |
+      | d[1].l |
+      | d[1].f |
+      | d[1].d |
+      | d[1].s |
+      | d[1].n |
+      | d[1].m |
+      | d[1].b |
+
   @GraphComputerVerificationInjectionNotSupported
   Scenario: Primitives_Number_eqXintX
     Given the empty graph
-    And using the parameter xx1 defined as "l[d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i]"
+    And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
     And using the parameter xx2 defined as "d[1].i"
     And the traversal of
       """
@@ -34,4 +75,113 @@ Feature: Equality
       | d[1].i |
       | d[1].l |
       | d[1].f |
-      | d[1].d |
\ No newline at end of file
+      | d[1].d |
+      | d[1].s |
+      | d[1].n |
+      | d[1].m |
+      | d[1].b |
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: Primitives_Number_eqXlongX
+    Given the empty graph
+    And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+    And using the parameter xx2 defined as "d[1].l"
+    And the traversal of
+      """
+      g.inject(xx1).unfold().where(__.is(xx2))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[1].i |
+      | d[1].l |
+      | d[1].f |
+      | d[1].d |
+      | d[1].s |
+      | d[1].n |
+      | d[1].m |
+      | d[1].b |
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: Primitives_Number_eqXbigintX
+    Given the empty graph
+    And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+    And using the parameter xx2 defined as "d[1].n"
+    And the traversal of
+      """
+      g.inject(xx1).unfold().where(__.is(xx2))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[1].i |
+      | d[1].l |
+      | d[1].f |
+      | d[1].d |
+      | d[1].s |
+      | d[1].n |
+      | d[1].m |
+      | d[1].b |
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: Primitives_Number_eqXfloatX
+    Given the empty graph
+    And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+    And using the parameter xx2 defined as "d[1].f"
+    And the traversal of
+      """
+      g.inject(xx1).unfold().where(__.is(xx2))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[1].i |
+      | d[1].l |
+      | d[1].f |
+      | d[1].d |
+      | d[1].s |
+      | d[1].n |
+      | d[1].m |
+      | d[1].b |
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: Primitives_Number_eqXdoubleX
+    Given the empty graph
+    And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+    And using the parameter xx2 defined as "d[1].d"
+    And the traversal of
+      """
+      g.inject(xx1).unfold().where(__.is(xx2))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[1].i |
+      | d[1].l |
+      | d[1].f |
+      | d[1].d |
+      | d[1].s |
+      | d[1].n |
+      | d[1].m |
+      | d[1].b |
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: Primitives_Number_eqXbigdecimalX
+    Given the empty graph
+    And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+    And using the parameter xx2 defined as "d[1].m"
+    And the traversal of
+      """
+      g.inject(xx1).unfold().where(__.is(xx2))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[1].i |
+      | d[1].l |
+      | d[1].f |
+      | d[1].d |
+      | d[1].s |
+      | d[1].n |
+      | d[1].m |
+      | d[1].b |
\ No newline at end of file
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
index 410858c..6b644a0 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
@@ -56,6 +56,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
 import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -93,11 +94,14 @@ public final class StepDefinition {
             final String listItems = Stream.of(items).map(String::trim).map(x -> convertToString(x)).collect(Collectors.joining(","));
             return String.format("[%s]", listItems);
         }));
-        add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.i"), s -> s));
+        add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.b"), s -> s + "b"));
+        add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.s"), s -> s + "s"));
+        add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.i"), s -> s + "i"));
         add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.l"), s -> s + "l"));
         add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.f"), s -> s + "f"));
         add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.d"), s -> s + "d"));
-        add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.m"), s -> String.format("new BigDecimal(%s)", s)));
+        add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.m"), s -> s + "m"));
+        add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.n"), s -> s + "n"));
 
         add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.id"), s -> g.V().has("name", s).id().next().toString()));
         add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.sid"), s -> g.V().has("name", s).id().next().toString()));
@@ -155,11 +159,14 @@ public final class StepDefinition {
             throw new AssumptionViolatedException("This test uses a Path as a parameter which is not supported by gremlin-language");
         }));
 
+        add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.b"), Byte::parseByte));
+        add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.s"), Short::parseShort));
         add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.i"), Integer::parseInt));
         add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.l"), Long::parseLong));
         add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.f"), Float::parseFloat));
         add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.d"), Double::parseDouble));
         add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.m"), BigDecimal::new));
+        add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.n"), BigInteger::new));
 
         add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.id"), s -> g.V().has("name", s).id().next()));
         add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.sid"), s -> g.V().has("name", s).id().next().toString()));