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

xiazcy pushed a commit to branch type-enum-poc
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit b59199b8f8af133650fcbfb245f118feb5638b62
Merge: 13a51e9dfb d6b80bd724
Author: Yang Xia <[email protected]>
AuthorDate: Mon Jul 28 19:41:55 2025 -0700

    Merge branch '3.8-dev' into TINKERPOP-3166_asNumber

 .github/workflows/build-test.yml                   |  14 -
 CHANGELOG.asciidoc                                 |  22 +-
 docker/Dockerfile                                  |   5 +-
 docs/site/home/download.html                       |   2 +-
 .../dev/developer/development-environment.asciidoc |   4 +-
 docs/src/dev/provider/gremlin-semantics.asciidoc   |  26 ++
 docs/src/reference/gremlin-applications.asciidoc   |  21 +-
 docs/src/reference/gremlin-variants.asciidoc       |  20 +-
 .../reference/implementations-tinkergraph.asciidoc |   4 +-
 docs/src/reference/the-traversal.asciidoc          |  23 +-
 docs/src/tutorials/getting-started/index.asciidoc  |   6 +-
 docs/src/upgrade/release-3.7.x.asciidoc            |   5 +
 docs/src/upgrade/release-3.8.x.asciidoc            | 309 ++++++++------
 gremlin-console/src/main/bin/gremlin-java8.bat     |  59 ---
 gremlin-console/src/main/bin/gremlin.sh            |   1 +
 .../tinkerpop/gremlin/console/Console.groovy       |   3 +-
 .../gremlin/console/GremlinGroovysh.groovy         |  81 +---
 .../gremlin/console/LocalSafeParser.groovy         | 146 +++++++
 .../gremlin/console/GremlinGroovyshTest.groovy     |  26 +-
 .../gremlin/console/LocalSafeParserTest.groovy     | 186 +++++++++
 .../grammar/DefaultGremlinBaseVisitor.java         |   4 +
 .../language/grammar/TraversalMethodVisitor.java   |   8 +
 .../traversal/dsl/graph/GraphTraversal.java        |  14 +
 .../gremlin/process/traversal/dsl/graph/__.java    |   7 +
 .../process/traversal/step/map/AsBoolStep.java     |  61 +++
 .../process/traversal/step/map/CallStep.java       |  22 +-
 .../process/traversal/util/BytecodeHelper.java     |   2 +
 .../process/traversal/util/DefaultTraversal.java   |   6 +-
 .../language/translator/GremlinTranslatorTest.java |   9 +
 .../process/traversal/step/map/AsBoolStepTest.java |  81 ++++
 .../process/traversal/step/map/CallStepTest.java   |  68 ++++
 .../traversal/util/DefaultTraversalTest.java       |  93 +++++
 gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj  |   2 +-
 .../Process/Traversal/GraphTraversal.cs            |   9 +
 .../src/Gremlin.Net/Process/Traversal/__.cs        |   8 +
 .../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs |  15 +
 gremlin-go/docker-compose.yml                      |   2 +-
 gremlin-go/driver/anonymousTraversal.go            |   7 +-
 gremlin-go/driver/client.go                        |   3 +-
 gremlin-go/driver/client_test.go                   |  32 ++
 gremlin-go/driver/cucumber/gremlin.go              |  15 +
 gremlin-go/driver/graphTraversal.go                |  10 +-
 gremlin-go/examples/go.mod                         |  13 +-
 gremlin-go/examples/go.sum                         |  61 +--
 gremlin-go/go.mod                                  |   2 +-
 gremlin-javascript/examples/node/package-lock.json |   2 +-
 gremlin-javascript/examples/node/package.json      |   2 +-
 gremlin-javascript/pom.xml                         |   4 +-
 .../gremlin-javascript/docker-compose.yml          |   2 +-
 .../gremlin-javascript/lib/driver/connection.js    |   3 +-
 .../lib/process/graph-traversal.js                 |  11 +
 .../gremlin-javascript/package-lock.json           |   2 +-
 .../javascript/gremlin-javascript/package.json     |   2 +-
 .../gremlin-javascript/test/cucumber/gremlin.js    |  15 +
 .../gremlin-javascript/test/unit/client-test.js    |  13 +
 gremlin-language/src/main/antlr4/Gremlin.g4        |   7 +
 .../gremlin_python/driver/aiohttp/transport.py     |   2 +
 .../gremlin_python/process/graph_traversal.py      |  14 +
 gremlin-python/src/main/python/radish/gremlin.py   |  15 +
 .../apache/tinkerpop/gremlin/server/Settings.java  |  11 +
 .../gremlin/server/channel/UnifiedChannelizer.java |   9 +
 .../gremlin/server/handler/AbstractSession.java    |   3 +
 .../gremlin/server/handler/MultiTaskSession.java   |   3 +
 .../gremlin/server/handler/SessionException.java   |   3 +
 .../gremlin/server/handler/SessionTask.java        |   3 +
 .../gremlin/server/handler/SingleTaskSession.java  |   3 +
 .../gremlin/server/handler/UnifiedHandler.java     |   3 +
 .../gremlin/server/GremlinDriverIntegrateTest.java |  47 +++
 .../gremlin/test/features/map/AsBool.feature       | 203 ++++++++++
 .../gremlin/process/ApplyStrategiesBenchmark.java  | 134 ++++++
 .../gremlin/process/TraversalLockBenchmark.java    | 135 ++++++
 gremlint/package-lock.json                         |   2 +-
 gremlint/package.json                              |   2 +-
 gremlint/pom.xml                                   |   4 +-
 pom.xml                                            |  32 +-
 .../structure/TinkerElementContainer.java          |  21 +-
 .../structure/TinkerTransactionGraph.java          |  10 +-
 .../structure/TinkerTransactionGraphTest.java      | 451 +++++++++++++++++++--
 78 files changed, 2247 insertions(+), 443 deletions(-)

diff --cc CHANGELOG.asciidoc
index c969413f17,4947b39a17..baa442c7d8
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@@ -76,8 -79,8 +79,9 @@@ This release also includes changes fro
  * Moved all lambda oriented Gremlin tests to `LambdaStepTest` in the Java 
test suite.
  * Removed the `@RemoteOnly` testing tag in Gherkin as lambda tests have all 
been moved to the Java test suite.
  * Updated gremlin-javascript to use GraphBinary as default instead of 
GraphSONv3
 +* Added the `asNumber()` step to perform number conversion.
  * Renamed many types in the grammar for consistent use of terms "Literal", 
"Argument", and "Varargs"
+ * Changed `gremlin-net` so that System.Text.Json is only listed as an 
explicit dependency when it is not available from the framework.
  
  == TinkerPop 3.7.0 (Gremfir Master of the Pan Flute)
  
diff --cc docs/src/upgrade/release-3.8.x.asciidoc
index 2ca45e6322,4d996ad3bb..3574e7b8fa
--- a/docs/src/upgrade/release-3.8.x.asciidoc
+++ b/docs/src/upgrade/release-3.8.x.asciidoc
@@@ -30,110 -30,48 +30,111 @@@ complete list of all the modifications 
  
  === Upgrading for Users
  
 +==== Number Conversion Step
 +
 +We have been iteratively introducing new language features into Gremlin, with 
the most recent major additions being string, list and date manipulation
 +steps introduced in the 3.7 line. In 3.8.0, we are now introducing a number 
conversion step, `asNumber()`, to bridge
 +a gap in casting functionalities.
 +
 +The new `asNumber()` serves as an umbrella step that parses strings and casts 
numbers into desired types. For the convenience of remote traversals in GLVs, 
these number types are denoted by a set of number tokens (`N`).
 +
 +This new step will allow users to normalize their data by converting string 
numbers and mixed numeric types to a consistent format, making it easier to 
perform downstream mathematical operations. As an example:
 +
 +[source,text]
 +----
 +// sum() step can only take numbers
 +gremlin> g.inject(1.0, 2l, 3, "4", "0x5").sum()
 +class java.lang.String cannot be cast to class java.lang.Number
 +
 +// use asNumber() to avoid casting exceptions
 +gremlin> g.inject(1.0, 2l, 3, "4", "0x5").asNumber().sum()
 +==>15.0
 +
 +// given sum() step returned a double, one can use asNumber() to further cast 
the result into desired type
 +gremlin> g.inject(1.0, 2l, 3, "4", "0x5").asNumber().sum().asNumber(N.int_)
 +==>15
 +----
 +
 +Semantically, the `asNumber()` step will convert the incoming traverser to a 
logical parsable type if no argument is provided, or to the desired numerical 
type, based on the number token (`N`) provided.
 +
 +Numerical input will pass through unless a type is specified by the number 
token. `ArithmeticException` will be thrown for any overflow as a result of 
narrowing of types:
 +
 +[source,text]
 +----
 +gremlin> g.inject(5.0).asNumber(N.int_)
 +==> 5    // casts double to int
 +gremlin> g.inject(12).asNumber(N.byte_)
 +==> 12
 +gremlin> g.inject(128).asNumber(N.byte_)
 +==> ArithmeticException
 +----
 +
 +String input will be parsed. By default, the smalled unit of number to be 
parsed into is `int` if no number token is provided. `NumberFormatException` 
will be thrown for any unparsable strings:
 +
 +[source,text]
 +----
 +gremlin> g.inject("5").asNumber()
 +==> 5
 +gremlin> g.inject("5.7").asNumber(N.int_)
 +==> 5
 +gremlin> g.inject("1,000").asNumber(N.int_)
 +==> NumberFormatException
 +gremlin> g.inject("128").asNumber(N.byte_)
 +==> ArithmeticException
 +----
 +
 +All other input types will result in `IllegalArgumentException`:
 +[source,text]
 +----
 +gremlin> g.inject([1, 2, 3, 4]).asNumber()
 +==> IllegalArgumentException
 +----
 +
 +See: 
link:https://tinkerpop.apache.org/docs/3.8.0/reference/#asNumber-step[asNumber()-step]
 +See: link:https://issues.apache.org/jira/browse/TINKERPOP-3166[TINKERPOP-3166]
 +
- ==== Removal of Vertex/ReferenceVertex from grammar
+ ==== Boolean Conversion Step
  
- `StructureVertex`, previously used to construct new vertices in the grammar, 
now been removed. The `V()` step, as well
- as the `from()` and `to()` modulators used with `addE()`, previously accepted 
`StructureVertex` as arguments in the
- grammar. In its place, the `from()` and `to()` modulators can now directly 
accept a vertex id in place of a `Vertex`
- when used with `addE()` (`V()` has always accepted ids in addition to 
vertices). When using these steps in `gremlin-lang`
- scripts, the vertex id must be used directly. This change has no effect on 
the `GraphTraversal` API, nor on
- `gremlin-groovy` scripts. Vertices can continue to be used directly such 
places.
+ The `asBool()` step bridges another gap in Gremlin's casting functionalities. 
Users now have the ability to parse strings and 
+ numbers into boolean values, both for normalization and to perform boolean 
logic with numerical values.
  
- [source,groovy]
+ [source,text]
  ----
- // 3.7.3
- gremlin> v1 = g.V(1).next()
- ==>v[1]
- gremlin> v2 = g.V(2).next()
- ==>v[2]
- gremlin> script = String.format("g.V(new 
Vertex(%s)).outE().where(inV().is(new Vertex(%s)))", v1.id(), v2.id())
- ==>g.V(new Vertex(1)).outE().where(inV().is(new Vertex(2)))
- gremlin> client.submit(script).all().get().get(0).getEdge()
- ==>e[7][1-knows->2]
+ gremlin> g.inject(2, "true", 1, 0, false, "FALSE").asBool().fold()
+ ==>[true,true,true,false,false,false]
  
- // 3.8.0
- gremlin> v1 = g.V(1).next()
- ==>v[1]
- gremlin> v2 = g.V(2).next()
- ==>v[2]
- gremlin> script = String.format("g.V(%s).outE().where(inV().id().is(%s))", 
v1.id(), v2.id())
- ==>g.V(1).outE().where(inV().id().is(2))
- gremlin> client.submit(script).all().get().get(0).getEdge()
- ==>e[7][1-knows->2]
+ // using the modern graph, we can turn count() results into boolean values
+ gremlin> g.V().local(outE().count()).fold()
+ ==>[3,0,0,2,0,1]
+ gremlin> g.V().local(outE().count()).asBool().fold()
+ ==>[true,false,false,true,false,true]
+ // a slightly more complex one using sack for boolean operations for vertices 
with both 'person' label and has out edges
+ gremlin> 
g.V().sack(assign).by(__.hasLabel('person').count().asBool()).sack(and).by(__.outE().count().asBool()).sack().path()
+ ==>[v[1],true]
+ ==>[v[2],false]
+ ==>[v[3],false]
+ ==>[v[4],true]
+ ==>[v[5],false]
+ ==>[v[6],true]
  ----
  
- ==== Auto promotion of number types
+ See: 
link:https://tinkerpop.apache.org/docs/3.8.0/reference/#asBool-step[asBool()-step]
+ See: link:https://issues.apache.org/jira/browse/TINKERPOP-3175[TINKERPOP-3175]
  
- Previously, operations like sum or sack that involved mathematical 
calculations did not automatically promote the result
- to a larger numeric type (e.g., from int to long) when needed. As a result, 
values could wrap around within their current
- type, leading to unexpected behavior. This issue has now been resolved by 
enabling automatic type promotion for results.
+ ==== Set minimum Java version to 11
  
- Now, any mathematical operations such as Add, Sub, Mul, and Div will now 
automatically promote to the next numeric type
- if an overflow is detected. For integers, the promotion sequence is: byte → 
short → int → long → overflow exception. For
- floating-point numbers, the sequence is: float → double → infinity.
+ TinkerPop 3.8 requires a minimum of Java 11 for building and running. Support 
for Java 1.8 has been dropped.
+ 
+ ==== Auto-promotion of Numbers
+ 
+ Previously, operations like `sum` or `sack` that involved mathematical 
calculations did not automatically promote the
+ result to a larger numeric type (e.g., from int to long) when needed. As a 
result, values could wrap around within their
+ current type leading to unexpected behavior. This issue has now been resolved 
by enabling automatic type promotion for
+ results.
+ 
+ Now, any mathematical operations such as `Add`, `Sub`, `Mul`, and `Div` will 
now automatically promote to the next
+ numeric type if an overflow is detected. For integers, the promotion sequence 
is: byte → short → int → long → overflow
+ exception. For floating-point numbers, the sequence is: float → double → 
infinity.
  
  The following example showcases the change in overflow behavior between 3.7.3 
and 3.8.0
  
diff --cc 
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index aa3c2cfbc5,8470cb289a..2d70e4e155
--- 
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
@@@ -83,8 -82,8 +83,9 @@@ import org.apache.tinkerpop.gremlin.pro
  import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStep;
  import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStartStep;
  import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStep;
 -import org.apache.tinkerpop.gremlin.process.traversal.step.map.AsDateStep;
+ import org.apache.tinkerpop.gremlin.process.traversal.step.map.AsBoolStep;
 +import org.apache.tinkerpop.gremlin.process.traversal.step.map.AsDateStep;
 +import org.apache.tinkerpop.gremlin.process.traversal.step.map.AsNumberStep;
  import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.AsStringGlobalStep;
  import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.AsStringLocalStep;
  import org.apache.tinkerpop.gremlin.process.traversal.step.map.CallStep;
diff --cc 
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java
index e9e2ac90da,0ad7c53764..1b0ce092bf
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java
@@@ -64,8 -64,8 +64,9 @@@ import org.apache.tinkerpop.gremlin.pro
  import 
org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep;
  import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStep;
  import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStep;
+ import org.apache.tinkerpop.gremlin.process.traversal.step.map.AsBoolStep;
  import org.apache.tinkerpop.gremlin.process.traversal.step.map.AsDateStep;
 +import org.apache.tinkerpop.gremlin.process.traversal.step.map.AsNumberStep;
  import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.AsStringGlobalStep;
  import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.AsStringLocalStep;
  import org.apache.tinkerpop.gremlin.process.traversal.step.map.CallStep;
diff --cc gremlin-go/driver/anonymousTraversal.go
index 6cf32581bb,67b107ab07..dfc99e60f3
--- a/gremlin-go/driver/anonymousTraversal.go
+++ b/gremlin-go/driver/anonymousTraversal.go
@@@ -383,14 -383,14 +383,19 @@@ func (anonymousTraversal *anonymousTrav
  
  // AsDate adds the AsDate step to the GraphTraversal.
  func (anonymousTraversal *anonymousTraversal) AsDate(args ...interface{}) 
*GraphTraversal {
-       return anonymousTraversal.graphTraversal().AsDate(args...)
+         return anonymousTraversal.graphTraversal().AsDate(args...)
+ }
+ 
+ // AsBool adds the AsBool step to the GraphTraversal.
+ func (anonymousTraversal *anonymousTraversal) AsBool(args ...interface{}) 
*GraphTraversal {
+         return anonymousTraversal.graphTraversal().AsBool(args...)
  }
  
 +// AsDate adds the AsNumber step to the GraphTraversal.
 +func (anonymousTraversal *anonymousTraversal) AsNumber(args ...interface{}) 
*GraphTraversal {
 +      return anonymousTraversal.graphTraversal().AsNumber(args...)
 +}
 +
  // AsString adds the asString step to the GraphTraversal.
  func (anonymousTraversal *anonymousTraversal) AsString(args ...interface{}) 
*GraphTraversal {
        return anonymousTraversal.graphTraversal().AsString(args...)
diff --cc gremlin-go/driver/graphTraversal.go
index b6b165f22d,ae9aa7f262..2608d74cbd
--- a/gremlin-go/driver/graphTraversal.go
+++ b/gremlin-go/driver/graphTraversal.go
@@@ -106,18 -106,18 +106,24 @@@ func (g *GraphTraversal) As(args ...int
        return g
  }
  
+ // AsBool adds the asBool step to the GraphTraversal.
+ func (g *GraphTraversal) AsBool(args ...interface{}) *GraphTraversal {
+       g.Bytecode.AddStep("asBool", args...)
+       return g
+ }
+ 
  // AsDate adds the asDate step to the GraphTraversal.
  func (g *GraphTraversal) AsDate(args ...interface{}) *GraphTraversal {
-       g.Bytecode.AddStep("asDate", args...)
-       return g
+         g.Bytecode.AddStep("asDate", args...)
+         return g
  }
  
 +// AsNumber adds the asNumber step to the GraphTraversal.
 +func (g *GraphTraversal) AsNumber(args ...interface{}) *GraphTraversal {
 +      g.Bytecode.AddStep("asNumber", args...)
 +      return g
 +}
 +
  // AsString adds the asString step to the GraphTraversal.
  func (g *GraphTraversal) AsString(args ...interface{}) *GraphTraversal {
        g.Bytecode.AddStep("asString", args...)
diff --cc gremlin-language/src/main/antlr4/Gremlin.g4
index 00031355f6,0b60761f35..a3544cfe71
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@@ -1685,9 -1672,9 +1690,10 @@@ keywor
      | K_AND
      | K_ANY
      | K_AS
+     | K_ASBOOL
      | K_ASC
      | K_ASDATE
 +    | K_ASNUMBER
      | K_ASSTRING
      | K_ASSIGN
      | K_BARRIER
@@@ -1954,9 -1932,9 +1960,10 @@@ K_ALL: 'all'
  K_AND: 'and';
  K_ANY: 'any';
  K_AS: 'as';
+ K_ASBOOL: 'asBool';
  K_ASC: 'asc';
  K_ASDATE: 'asDate';
 +K_ASNUMBER: 'asNumber';
  K_ASSTRING: 'asString';
  K_ASSIGN: 'assign';
  K_BARRIER: 'barrier';
diff --cc 
gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
index ced9fc1890,9a33d899fd..f2399ef42e
--- a/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
+++ b/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
@@@ -2425,10 -2425,10 +2437,12 @@@ statics.add_static('and_', and_
  
  statics.add_static('as_', as_)
  
+ statics.add_static('as_bool', as_bool)
+ 
  statics.add_static('as_date', as_date)
  
 +statics.add_static('as_number', as_number)
 +
  statics.add_static('as_string', as_string)
  
  statics.add_static('barrier', barrier)

Reply via email to