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 2022/01/18 20:23:00 UTC

[tinkerpop] branch TINKERPOP-2681 updated: wip

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

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


The following commit(s) were added to refs/heads/TINKERPOP-2681 by this push:
     new 0e09fbd  wip
0e09fbd is described below

commit 0e09fbd3d7bfce63cf1618a7531ab1b4b4a1bd77
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Tue Jan 18 15:22:38 2022 -0500

    wip
---
 docs/src/dev/developer/for-committers.asciidoc     |   1 +
 .../tinkerpop/gremlin/jsr223/CoreImports.java      |   2 +
 .../language/grammar/GenericLiteralVisitor.java    |   5 +
 .../language/grammar/GremlinBaseVisitor.java       |  15 +-
 .../language/grammar/TraversalMethodVisitor.java   |  10 +
 .../grammar/TraversalSourceSpawnMethodVisitor.java |  10 +
 .../traversal/dsl/graph/GraphTraversal.java        |  31 +-
 .../traversal/dsl/graph/GraphTraversalSource.java  |  33 +-
 .../gremlin/process/traversal/dsl/graph/__.java    |  30 +-
 .../process/traversal/step/map/MergeEdgeStep.java  | 334 +++++++++++++++++++
 .../language/grammar/TraversalEnumParserTest.java  |   4 +-
 gremlin-dotnet/build/generate.groovy               |  10 +
 .../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs |  24 ++
 .../ast/VarAsBindingASTTransformation.groovy       |   7 +-
 .../jsr223/GremlinGroovyScriptEngineTest.java      |   9 +-
 gremlin-javascript/build/generate.groovy           |  11 +
 .../lib/process/graph-traversal.js                 |  22 ++
 .../gremlin-javascript/lib/process/traversal.js    |   1 +
 .../gremlin-javascript/test/cucumber/gremlin.js    | 369 ++++++++++++++++++++-
 gremlin-language/src/main/antlr4/Gremlin.g4        |   5 +-
 .../language/corpus/DocumentationReader.java       |   2 +
 .../language/grammar/ReferenceGrammarTest.java     |  16 +-
 gremlin-python/build/generate.groovy               |  10 +
 gremlin-python/src/main/python/radish/gremlin.py   |  24 ++
 gremlin-test/features/map/MergeEdge.feature        | 184 ++++++++++
 gremlin-test/features/map/MergeVertex.feature      |  16 +-
 gremlin-test/features/sideEffect/Group.feature     |   2 +-
 .../tinkerpop/gremlin/features/StepDefinition.java |  30 +-
 28 files changed, 1176 insertions(+), 41 deletions(-)

diff --git a/docs/src/dev/developer/for-committers.asciidoc b/docs/src/dev/developer/for-committers.asciidoc
index 056f9a8..9ccf5a4 100644
--- a/docs/src/dev/developer/for-committers.asciidoc
+++ b/docs/src/dev/developer/for-committers.asciidoc
@@ -516,6 +516,7 @@ tag when one is necessary will cause provider tests to fail:
 
 * `@AllowNullPropertyValues` - The scenario requires that the graph be configured with `AllowNullPropertyValues` as
 `true` (meaning that it can store `null` values).
+* `@AllowUserSuppliedIds` - The scenario requires that the graph be configured with `UserSuppliedIds` as `true`.
 * `@GraphComputerVerificationInjectionNotSupported` - The scenario will not work on with `GraphComputer` because the
 `inject()` step is not supported.
 * `@GraphComputerVerificationMidVNotSupported` - The scenario will not work on with `GraphComputer` because the
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
index a34f0d7..67be548 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
@@ -55,6 +55,7 @@ import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.verifica
 import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
 import org.apache.tinkerpop.gremlin.process.traversal.Bindings;
 import org.apache.tinkerpop.gremlin.process.traversal.IO;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
 import org.apache.tinkerpop.gremlin.process.traversal.Operator;
 import org.apache.tinkerpop.gremlin.process.traversal.Order;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
@@ -195,6 +196,7 @@ public final class CoreImports {
         CLASS_IMPORTS.add(VertexProperty.Cardinality.class);
         CLASS_IMPORTS.add(Column.class);
         CLASS_IMPORTS.add(Direction.class);
+        CLASS_IMPORTS.add(Merge.class);
         CLASS_IMPORTS.add(Operator.class);
         CLASS_IMPORTS.add(Order.class);
         CLASS_IMPORTS.add(Pop.class);
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 151174a..73be3d8 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
@@ -307,6 +307,11 @@ public class GenericLiteralVisitor extends GremlinBaseVisitor<Object> {
         return antlr.tvisitor.visitNestedTraversal(ctx);
     }
 
+    @Override
+    public Object visitStructureVertex(final GremlinParser.StructureVertexContext ctx) {
+        return StructureElementVisitor.instance().visitStructureVertex(ctx);
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinBaseVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinBaseVisitor.java
index 0a93e4e..d6c2565 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinBaseVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinBaseVisitor.java
@@ -1533,11 +1533,6 @@ public class GremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> implement
 	}
 
 	@Override
-	public T visitTraversalSourceSpawnMethod_mergeE(final GremlinParser.TraversalSourceSpawnMethod_mergeEContext ctx) {
-		notImplemented(ctx); return null;
-	}
-
-	@Override
 	public T visitTraversalMethod_option_Merge_Map(GremlinParser.TraversalMethod_option_Merge_MapContext ctx) {
 		notImplemented(ctx); return null;
 	}
@@ -1571,4 +1566,14 @@ public class GremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> implement
 	public T visitTraversalMethod_mergeE_Traversal(final GremlinParser.TraversalMethod_mergeE_TraversalContext ctx) {
 		notImplemented(ctx); return null;
 	}
+
+	@Override
+	public T visitTraversalSourceSpawnMethod_mergeE_Map(final GremlinParser.TraversalSourceSpawnMethod_mergeE_MapContext ctx) {
+		notImplemented(ctx); return null;
+	}
+
+	@Override
+	public T visitTraversalSourceSpawnMethod_mergeE_Traversal(final GremlinParser.TraversalSourceSpawnMethod_mergeE_TraversalContext ctx) {
+		notImplemented(ctx); return 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 be0fff5..10266ff 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
@@ -97,6 +97,16 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
     }
 
     @Override
+    public GraphTraversal visitTraversalMethod_mergeE_Map(final GremlinParser.TraversalMethod_mergeE_MapContext ctx) {
+        return this.graphTraversal.mergeE(GenericLiteralVisitor.getMapLiteral(ctx.genericLiteralMap()));
+    }
+
+    @Override
+    public GraphTraversal visitTraversalMethod_mergeE_Traversal(final GremlinParser.TraversalMethod_mergeE_TraversalContext ctx) {
+        return this.graphTraversal.mergeE(antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
+    }
+
+    @Override
     public GraphTraversal visitTraversalMethod_addE_Traversal(final GremlinParser.TraversalMethod_addE_TraversalContext ctx) {
         return this.graphTraversal.addE(antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
index 664afac..f7d04f7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
@@ -126,4 +126,14 @@ public class TraversalSourceSpawnMethodVisitor extends GremlinBaseVisitor<GraphT
     public GraphTraversal visitTraversalSourceSpawnMethod_mergeV_Traversal(final GremlinParser.TraversalSourceSpawnMethod_mergeV_TraversalContext ctx) {
         return this.traversalSource.mergeV(anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
     }
+
+    @Override
+    public GraphTraversal visitTraversalSourceSpawnMethod_mergeE_Traversal(final GremlinParser.TraversalSourceSpawnMethod_mergeE_TraversalContext ctx) {
+        return this.traversalSource.mergeE(anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
+    }
+
+    @Override
+    public GraphTraversal visitTraversalSourceSpawnMethod_mergeE_Map(final GremlinParser.TraversalSourceSpawnMethod_mergeE_MapContext ctx) {
+        return this.traversalSource.mergeE(GenericLiteralVisitor.getMapLiteral(ctx.genericLiteralMap()));
+    }
 }
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 721c1f7..13092bf 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
@@ -103,6 +103,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.MaxGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MaxLocalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeEdgeStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeVertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MinGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MinLocalStep;
@@ -1099,9 +1100,35 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
      *  {@link T} or a {@code String}.
      *  @since 3.6.0
      */
-    public default GraphTraversal<S, Vertex> mergeV(final Traversal<S, Map<Object, Object>> searchCreate) {
+    public default GraphTraversal<S, Vertex> mergeV(final Traversal<?, Map<Object, Object>> searchCreate) {
         this.asAdmin().getBytecode().addStep(Symbols.mergeV, searchCreate);
-        final MergeVertexStep<S> step = new MergeVertexStep<>(this.asAdmin(), false, searchCreate.asAdmin());
+        final MergeVertexStep<S> step = new MergeVertexStep(this.asAdmin(), false, searchCreate.asAdmin());
+        return this.asAdmin().addStep(step);
+    }
+
+    /**
+     * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a
+     * {@code Map} as an argument.
+     *
+     * @param searchCreate This {@code Map} can have a key of {@link T} {@link Direction} or a {@code String}.
+     * @since 3.6.0
+     */
+    public default GraphTraversal<S, Edge> mergeE(final Map<?, Object> searchCreate) {
+        this.asAdmin().getBytecode().addStep(Symbols.mergeE, searchCreate);
+        final MergeEdgeStep<S> step = new MergeEdgeStep(this.asAdmin(), false, searchCreate);
+        return this.asAdmin().addStep(step);
+    }
+
+    /**
+     * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a
+     * {@code Map} as an argument.
+     *
+     * @param searchCreate This {@code Map} can have a key of {@link T} {@link Direction} or a {@code String}.
+     * @since 3.6.0
+     */
+    public default GraphTraversal<S, Edge> mergeE(final Traversal<?, Map<Object, Object>> searchCreate) {
+        this.asAdmin().getBytecode().addStep(Symbols.mergeE, searchCreate);
+        final MergeEdgeStep<S> step = new MergeEdgeStep(this.asAdmin(), false, searchCreate.asAdmin());
         return this.asAdmin().addStep(step);
     }
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
index 6726255..5806227 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
@@ -30,11 +30,13 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStartStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStartStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeEdgeStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeVertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IoStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.RequirementsStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.structure.Direction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
@@ -388,7 +390,7 @@ public class GraphTraversalSource implements TraversalSource {
      * {@link T} or a {@code String}.
      * @since 3.6.0
      */
-    public <S> GraphTraversal<S, Vertex> mergeV(final Traversal<S, Map<Object, Object>> searchCreate) {
+    public <S> GraphTraversal<S, Vertex> mergeV(final Traversal<?, Map<Object, Object>> searchCreate) {
         final GraphTraversalSource clone = this.clone();
         clone.bytecode.addStep(GraphTraversal.Symbols.mergeV, searchCreate);
         final GraphTraversal.Admin<S, Vertex> traversal = new DefaultGraphTraversal<>(clone);
@@ -398,13 +400,30 @@ public class GraphTraversalSource implements TraversalSource {
     /**
      * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a
      * {@code Map} as an argument.
+     *
+     * @param searchCreate This {@code Map} can have a key of {@link T} {@link Direction} or a {@code String}.
+     * @since 3.6.0
      */
-//    public GraphTraversal<Edge, Edge> mergeE(final Map<?, Object> searchCreate) {
-//        final GraphTraversalSource clone = this.clone();
-//        clone.bytecode.addStep(GraphTraversal.Symbols.mergeE, searchCreate);
-//        final GraphTraversal.Admin<Edge, Edge> traversal = new DefaultGraphTraversal<>(clone);
-//        return traversal.addStep(new MergeVertexStartStep(traversal, searchCreate));
-//    }
+    public GraphTraversal<Edge, Edge> mergeE(final Map<?, Object> searchCreate) {
+        final GraphTraversalSource clone = this.clone();
+        clone.bytecode.addStep(GraphTraversal.Symbols.mergeE, searchCreate);
+        final GraphTraversal.Admin<Edge, Edge> traversal = new DefaultGraphTraversal<>(clone);
+        return traversal.addStep(new MergeEdgeStep(traversal, true, searchCreate));
+    }
+
+    /**
+     * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a
+     * {@code Map} as an argument.
+     *
+     * @param searchCreate This {@code Map} can have a key of {@link T} {@link Direction} or a {@code String}.
+     * @since 3.6.0
+     */
+    public GraphTraversal<Edge, Edge> mergeE(final Traversal<?, Map<Object, Object>> searchCreate) {
+        final GraphTraversalSource clone = this.clone();
+        clone.bytecode.addStep(GraphTraversal.Symbols.mergeE, searchCreate);
+        final GraphTraversal.Admin<Edge, Edge> traversal = new DefaultGraphTraversal<>(clone);
+        return traversal.addStep(new MergeEdgeStep(traversal, true, searchCreate.asAdmin()));
+    }
 
     /**
      * Spawns a {@link GraphTraversal} starting it with arbitrary values.
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 08a4c07..a1ce789 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
@@ -516,6 +516,20 @@ public class __ {
     }
 
     /**
+     * @see GraphTraversal#mergeV(Map)
+     */
+    public static <A> GraphTraversal<A, Vertex> mergeV(final Map<Object, Object> searchCreate) {
+        return __.<A>start().mergeV(searchCreate);
+    }
+
+    /**
+     * @see GraphTraversal#mergeV(Traversal)
+     */
+    public static <A> GraphTraversal<A, Vertex> mergeV(final Traversal<?, Map<Object, Object>> searchCreate) {
+        return __.<A>start().mergeV(searchCreate);
+    }
+
+    /**
      * @see GraphTraversal#addE(String)
      */
     public static <A> GraphTraversal<A, Edge> addE(final String edgeLabel) {
@@ -523,13 +537,27 @@ public class __ {
     }
 
     /**
-     * @see GraphTraversal#addE(org.apache.tinkerpop.gremlin.process.traversal.Traversal)
+     * @see GraphTraversal#addE(Traversal)
      */
     public static <A> GraphTraversal<A, Edge> addE(final Traversal<?, String> edgeLabelTraversal) {
         return __.<A>start().addE(edgeLabelTraversal);
     }
 
     /**
+     * @see GraphTraversal#mergeE(Map)
+     */
+    public static <A> GraphTraversal<A, Edge> mergeE(final Map<?, Object> searchCreate) {
+        return __.<A>start().mergeE(searchCreate);
+    }
+
+    /**
+     * @see GraphTraversal#mergeE(Traversal)
+     */
+    public static <A> GraphTraversal<A, Edge> mergeE(final Traversal<?, Map<Object, Object>> searchCreate) {
+        return __.<A>start().mergeE(searchCreate);
+    }
+
+    /**
      * @see GraphTraversal#math(String)
      */
     public static <A> GraphTraversal<A, Double> math(final String expression) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeEdgeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeEdgeStep.java
new file mode 100644
index 0000000..e5e4a19
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeEdgeStep.java
@@ -0,0 +1,334 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.CallbackRegistry;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.Event;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.ListCallbackRegistry;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.util.Attachable;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Stream;
+
+/**
+ * Implementation for the {@code mergeE()} step covering both the start step version and the one used mid-traversal.
+ */
+public class MergeEdgeStep<S> extends FlatMapStep<S, Edge> implements Mutating<Event>,
+        TraversalOptionParent<Merge, S, Edge> {
+
+    private final boolean isStart;
+    private boolean first = true;
+    private Traversal.Admin<S,Map<Object, Object>> searchCreateTraversal;
+    private Traversal.Admin<S, Map<Object, Object>> onCreateTraversal = null;
+    private Traversal.Admin<S, Map<String, Object>> onMatchTraversal = null;
+
+    private CallbackRegistry<Event> callbackRegistry;
+
+    public MergeEdgeStep(final Traversal.Admin traversal, final boolean isStart, final Map<Object, Object> searchCreate) {
+        this(traversal, isStart, new ConstantTraversal<>(searchCreate));
+    }
+
+    public MergeEdgeStep(final Traversal.Admin traversal, final boolean isStart, final Traversal.Admin<?,Map<Object, Object>> searchCreateTraversal) {
+        super(traversal);
+        this.isStart = isStart;
+        this.searchCreateTraversal = integrateChild(searchCreateTraversal);
+    }
+
+    public Traversal.Admin<S, Map<Object, Object>> getSearchCreateTraversal() {
+        return searchCreateTraversal;
+    }
+
+    public Traversal.Admin<S, Map<Object, Object>> getOnCreateTraversal() {
+        return onCreateTraversal;
+    }
+
+    public Traversal.Admin<S, Map<String, Object>> getOnMatchTraversal() {
+        return onMatchTraversal;
+    }
+
+    /**
+     * Determines if this is a start step.
+     */
+    public boolean isStart() {
+        return isStart;
+    }
+
+    public boolean isFirst() {
+        return first;
+    }
+
+    public CallbackRegistry<Event> getCallbackRegistry() {
+        return callbackRegistry;
+    }
+
+    @Override
+    public void addChildOption(final Merge token, final Traversal.Admin<S, Edge> traversalOption) {
+        if (token == Merge.onCreate) {
+            this.onCreateTraversal = this.integrateChild(traversalOption);
+        } else if (token == Merge.onMatch) {
+            this.onMatchTraversal = this.integrateChild(traversalOption);
+        } else {
+            throw new UnsupportedOperationException(String.format("Option %s for Merge is not supported", token.name()));
+        }
+    }
+
+    @Override
+    public <S, E> List<Traversal.Admin<S, E>> getLocalChildren() {
+        final List<Traversal.Admin<S, E>> children = new ArrayList<>();
+        if (searchCreateTraversal != null) children.add((Traversal.Admin<S, E>) searchCreateTraversal);
+        if (onMatchTraversal != null) children.add((Traversal.Admin<S, E>) onMatchTraversal);
+        if (onCreateTraversal != null) children.add((Traversal.Admin<S, E>) onCreateTraversal);
+        return children;
+    }
+
+    @Override
+    public void configure(final Object... keyValues) {
+        // this is a Mutating step but property() should not be folded into this step. this exception should not
+        // end up visible to users really
+    }
+
+    @Override
+    public Parameters getParameters() {
+        // merge doesn't take fold ups of property() calls. those need to get treated as regular old PropertyStep
+        // instances. not sure if this should support with() though.....none of the other Mutating steps do.
+        return null;
+    }
+
+    @Override
+    protected Traverser.Admin<Edge> processNextStart() {
+        // when it's a start step a traverser needs to be created to kick off the traversal.
+        if (isStart && first) {
+            first = false;
+            final TraverserGenerator generator = this.getTraversal().getTraverserGenerator();
+            this.addStart(generator.generate(false, (Step) this, 1L));
+        }
+        return super.processNextStart();
+    }
+
+    /**
+     * Use the {@code Map} of search criteria to most efficiently return a {@code Stream<Edge>} of matching elements.
+     * Providers might override this method when extending this step to provide their own optimized mechanisms for
+     * matching the list of edges. This implementation is only optimized for the {@link T#id} so any other usage
+     * will simply be in-memory filtering which could be slow.
+     */
+    protected Stream<Edge> createSearchStream(final Map<Object,Object> search) {
+        final Graph graph = this.getTraversal().getGraph().get();
+
+        final Optional<Direction> directionUsedInLookup;
+        Stream<Edge> stream;
+        // prioritize lookup by id, then use vertices as starting point if possible
+        if (search.containsKey(T.id)) {
+            stream = IteratorUtils.stream(graph.edges(search.get(T.id)));
+            directionUsedInLookup = Optional.empty();
+        } else if (search.containsKey(Direction.OUT)) {
+            stream = IteratorUtils.stream(graph.vertices(search.get(Direction.OUT))).flatMap(v -> IteratorUtils.stream(v.edges(Direction.OUT)));
+            directionUsedInLookup = Optional.of(Direction.OUT);
+        } else if (search.containsKey(Direction.IN)) {
+            stream = IteratorUtils.stream(graph.vertices(search.get(Direction.IN))).flatMap(v -> IteratorUtils.stream(v.edges(Direction.IN)));
+            directionUsedInLookup = Optional.of(Direction.IN);
+        } else {
+            stream = IteratorUtils.stream(graph.edges());
+            directionUsedInLookup = Optional.empty();
+        }
+
+        // in-memory filter is not going to be nice here. it will be up to graphs to optimize this step as they do
+        // for other Mutation steps
+        stream = stream.filter(e -> {
+            // try to match on all search criteria skipping T.id as it was handled above
+            return search.entrySet().stream().filter(
+                    kv -> kv.getKey() != T.id && !(directionUsedInLookup.isPresent() && kv.getKey() == directionUsedInLookup.get())).
+                    allMatch(kv -> {
+                        if (kv.getKey() == T.label) {
+                            return e.label().equals(kv.getValue());
+                        } else if (kv.getKey() instanceof Direction) {
+                            final Direction direction = (Direction) kv.getKey();
+
+                            // try to take advantage of string id conversions of the graph by doing a lookup rather
+                            // than direct compare on id
+                            final Iterator<Vertex> found = graph.vertices(kv.getValue());
+                            return found.hasNext() && e.vertices(direction).next().equals(found.next());
+                        } else {
+                            final Property<Object> vp = e.property(kv.getKey().toString());
+                            return vp.isPresent() && kv.getValue().equals(vp.value());
+                        }
+                    });
+        });
+
+        return stream;
+    }
+
+    @Override
+    protected Iterator<Edge> flatMap(final Traverser.Admin<S> traverser) {
+        final S possibleVertex = traverser.get();
+        final Map<Object,Object> searchCreate = TraversalUtil.apply(traverser, searchCreateTraversal);
+
+        Vertex outV = (Vertex) searchCreate.getOrDefault(Direction.OUT, possibleVertex);
+        Vertex inV = (Vertex) searchCreate.getOrDefault(Direction.IN, possibleVertex);
+
+        if (inV instanceof Attachable)
+            inV = ((Attachable<Vertex>) inV)
+                    .attach(Attachable.Method.getOrCreate(this.getTraversal().getGraph().orElse(EmptyGraph.instance())));
+        if (outV instanceof Attachable)
+            outV = ((Attachable<Vertex>) outV)
+                    .attach(Attachable.Method.getOrCreate(this.getTraversal().getGraph().orElse(EmptyGraph.instance())));
+
+        final Vertex fromV = outV;
+        final Vertex toV = inV;
+
+        Stream<Edge> stream = createSearchStream(searchCreate);
+        stream = stream.map(e -> {
+            // if no onMatch is defined then there is no update - return the vertex unchanged
+            if (null == onMatchTraversal) return e;
+
+            // assume good input from GraphTraversal - folks might drop in a T here even though it is immutable
+            final Map<String, Object> onMatchMap = TraversalUtil.apply(traverser, onMatchTraversal);
+            onMatchMap.forEach((key, value) -> {
+                // trigger callbacks for eventing - in this case, it's a VertexPropertyChangedEvent. if there's no
+                // registry/callbacks then just set the property
+                if (this.callbackRegistry != null && !callbackRegistry.getCallbacks().isEmpty()) {
+                    final EventStrategy eventStrategy = getTraversal().getStrategies().getStrategy(EventStrategy.class).get();
+                    final Property<Object> oldValue = eventStrategy.detach(e.property(key));
+                    final Event.EdgePropertyChangedEvent vpce = new Event.EdgePropertyChangedEvent(eventStrategy.detach(e), oldValue, value);
+                    this.callbackRegistry.getCallbacks().forEach(c -> c.accept(vpce));
+                }
+                e.property(key, value);
+            });
+
+            return e;
+        });
+
+        // if the stream has something then there is a match (possibly updated) and is returned, otherwise a new
+        // edge is created
+        final Iterator<Edge> edges = stream.iterator();
+        if (edges.hasNext()) {
+            return edges;
+        } else {
+            final Edge edge;
+
+            // if there is an onCreateTraversal then the search criteria is ignored for the creation as it is provided
+            // by way of the traversal which will return the Map
+            final Map<Object,Object> m = null == onCreateTraversal ? searchCreate : TraversalUtil.apply(traverser, onCreateTraversal);
+            final List<Object> keyValues = new ArrayList<>();
+            String label = Edge.DEFAULT_LABEL;
+            for (Map.Entry<Object, Object> entry : m.entrySet()) {
+                // skip Direction keys as they are already handled in getting fromV/toV
+                if (entry.getKey() instanceof Direction) continue;
+
+                if (entry.getKey().equals(T.label)) {
+                    label = (String) entry.getValue();
+                } else {
+                    keyValues.add(entry.getKey());
+                    keyValues.add(entry.getValue());
+                }
+            }
+
+            edge = fromV.addEdge(label, toV, keyValues.toArray(new Object[keyValues.size()]));
+
+            // trigger callbacks for eventing - in this case, it's a VertexAddedEvent
+            if (this.callbackRegistry != null && !callbackRegistry.getCallbacks().isEmpty()) {
+                final EventStrategy eventStrategy = getTraversal().getStrategies().getStrategy(EventStrategy.class).get();
+                final Event.EdgeAddedEvent vae = new Event.EdgeAddedEvent(eventStrategy.detach(edge));
+                this.callbackRegistry.getCallbacks().forEach(c -> c.accept(vae));
+            }
+
+            return IteratorUtils.of(edge);
+        }
+    }
+
+    @Override
+    public CallbackRegistry<Event> getMutatingCallbackRegistry() {
+        if (null == callbackRegistry) callbackRegistry = new ListCallbackRegistry<>();
+        return callbackRegistry;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        if (searchCreateTraversal != null)
+            result ^= searchCreateTraversal.hashCode();
+        if (onCreateTraversal != null)
+            result ^= onCreateTraversal.hashCode();
+        if (onMatchTraversal != null)
+            result ^= onMatchTraversal.hashCode();
+        return result;
+    }
+
+    @Override
+    public void reset() {
+        super.reset();
+        first = true;
+        searchCreateTraversal.reset();
+        if (onCreateTraversal != null) onCreateTraversal.reset();
+        if (onMatchTraversal != null) onMatchTraversal.reset();
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements();
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.stepString(this, searchCreateTraversal, onCreateTraversal, onMatchTraversal);
+    }
+
+    @Override
+    public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
+        super.setTraversal(parentTraversal);
+        this.integrateChild(searchCreateTraversal);
+        this.integrateChild(onCreateTraversal);
+        this.integrateChild(onMatchTraversal);
+    }
+
+    @Override
+    public MergeEdgeStep<S> clone() {
+        final MergeEdgeStep<S> clone = (MergeEdgeStep<S>) super.clone();
+        clone.searchCreateTraversal = searchCreateTraversal.clone();
+        clone.onCreateTraversal = onCreateTraversal != null ? onCreateTraversal.clone() : null;
+        clone.onMatchTraversal = onMatchTraversal != null ? onMatchTraversal.clone() : null;
+        return clone;
+    }
+}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalEnumParserTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalEnumParserTest.java
index 0d490df..6ed0d3f 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalEnumParserTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalEnumParserTest.java
@@ -53,13 +53,14 @@ public class TraversalEnumParserTest {
                     {"org.apache.tinkerpop.gremlin.process.traversal.Scope", "traversalScope"},
                     {"org.apache.tinkerpop.gremlin.process.traversal.Order", "traversalOrder"},
                     {"org.apache.tinkerpop.gremlin.process.traversal.Pop", "traversalPop"},
+                    {"org.apache.tinkerpop.gremlin.process.traversal.Pick", "traversalOptionParent"},
+                    {"org.apache.tinkerpop.gremlin.process.traversal.Merge", "traversalMerge"},
                     {"org.apache.tinkerpop.gremlin.process.traversal.SackFunctions$Barrier", "traversalSackMethod"},
                     {"org.apache.tinkerpop.gremlin.process.traversal.Operator", "traversalOperator"},
                     {"org.apache.tinkerpop.gremlin.structure.T", "traversalToken"},
                     {"org.apache.tinkerpop.gremlin.structure.Column", "traversalColumn"},
                     {"org.apache.tinkerpop.gremlin.structure.Direction", "traversalDirection"},
                     {"org.apache.tinkerpop.gremlin.structure.VertexProperty$Cardinality", "traversalCardinality"},
-                    {"org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent$Pick", "traversalOptionParent"},
             });
         }
 
@@ -91,6 +92,7 @@ public class TraversalEnumParserTest {
             return Arrays.asList(new Object[][]{
                     {"org.apache.tinkerpop.gremlin.process.traversal.Scope", "traversalScope"},
                     {"org.apache.tinkerpop.gremlin.process.traversal.Order", "traversalOrder"},
+                    {"org.apache.tinkerpop.gremlin.process.traversal.Merge", "traversalMerge"},
                     {"org.apache.tinkerpop.gremlin.structure.T", "traversalToken"}
             });
         }
diff --git a/gremlin-dotnet/build/generate.groovy b/gremlin-dotnet/build/generate.groovy
index d6f8c60..addf07e 100644
--- a/gremlin-dotnet/build/generate.groovy
+++ b/gremlin-dotnet/build/generate.groovy
@@ -31,6 +31,16 @@ import java.nio.file.Paths
 
 import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal
 
+// getting an exception like:
+// > InvocationTargetException: javax.script.ScriptException: groovy.lang.MissingMethodException: No signature of
+// > method: org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal.mergeE() is applicable for
+// > argument types: (String) values: [4ffdea36-4a0e-4681-acba-e76875d1b25b]
+// usually means bindings are not being extracted properly by VarAsBindingASTTransformation which typically happens
+// when a step is taking an argument that cannot properly resolve to the type required by the step itself. there are
+// special cases in that VarAsBindingASTTransformation class which might need to be adjusted. Editing the
+// GremlinGroovyScriptEngineTest#shouldProduceBindingsForVars() with the failing step and argument can typically make
+// this issue relatively easy to debug and enforce.
+
 // file is overwritten on each generation
 radishGremlinFile = new File("${projectBaseDir}/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs")
 
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index ea6bf4d..610c7e4 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -498,6 +498,30 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Mean<object>()}}, 
                {"g_injectXnull_10_20_nullX_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null,p["xx1"],p["xx2"],null).Mean<object>()}}, 
                {"g_injectXlistXnull_10_20_nullXX_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Mean<object>(Scope.Local)}}, 
+               {"g_V_mergeEXlabel_self_weight_05X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29), (g,p) =>g.V().MergeE(p["xx1"]), (g,p) =>g.E().HasLabel("self").Has("weight",0.5)}}, 
+               {"g_mergeEXlabel_knows_out_marko_in_vadasX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property(T.Id,100).Property("name","marko").AddV("person").Property(T.Id,101).Property("name","vadas"), (g,p) =>g.MergeE(p["xx1"]), (g,p) =>g.V().Has("person","name","marko").Out("knows").Has("person","name","vadas")}}, 
+               {"g_mergeEXlabel_knows_out_marko_in_vadas_weight_05X_exists", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property(T.Id,100).Property("name","marko").As("a").AddV("person").Property(T.Id,101).Property("name","vadas").As("b").AddE("knows").From("a").To("b"), (g,p) =>g.MergeE(p["xx1"]), (g,p) =>g.V().Has("person","name","marko").OutE("knows").Has("weight",0.5).InV().Has("person","name","vadas"), (g,p) =>g.V().Has("p [...]
+               {"g_mergeEXlabel_knows_out_marko_in_vadas_weight_05X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.MergeE(p["xx1"]), (g,p) =>g.V(), (g,p) =>g.E().HasLabel("knows").Has("weight",0.5)}}, 
+               {"g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.MergeE(p["xx1"]).Option(Merge.OnCreate,p["xx2"]).Option(Merge.OnMatch,p["xx3"]), (g,p) =>g.V(), (g,p) =>g.E().HasLabel("knows").Has("created","Y"), (g,p) =>g.E().HasLabel("knows").Has("created","N")}}, 
+               {"g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property(T.Id,100).Property("name","marko").As("a").AddV("person").Property(T.Id,101).Property("name","vadas").As("b").AddE("knows").From("a").To("b"), (g,p) =>g.MergeE(p["xx1"]).Option(Merge.OnCreate,p["xx2"]).Option(Merge.OnMatch,p["xx3"]), (g,p) =>g.V(), (g,p) =>g. [...]
+               {"g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property(T.Id,100).Property("name","marko").As("a").AddV("person").Property(T.Id,101).Property("name","vadas").As("b").AddE("knows").From("a").To("b").Property("created","Y"), (g,p) =>g.MergeE(p["xx1"]).Option(Merge.OnCreate,p["xx2"]).Option(Merge.OnMatch,p["x [...]
+               {"g_V_hasXperson_name_marko_X_mergeEXlabel_knowsX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property(T.Id,100).Property("name","marko").As("a").AddV("person").Property(T.Id,101).Property("name","vadas").As("b").AddE("knows").From("a").To("b").Property("created","Y").AddE("knows").From("a").To("b"), (g,p) =>g.V().Has("person","name","marko").Me [...]
+               {"g_VX100X_VX101X_mergeEXlabel_knows_out_marko_in_vadasX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property(T.Id,100).Property("name","marko"), (g,p) =>g.V(100).V(101).MergeE(p["xx1"]), (g,p) =>g.V(), (g,p) =>g.E()}}, 
+               {"g_mergeVXlabel_person_name_stephenX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.MergeV(p["xx1"]), (g,p) =>g.V().Has("person","name","stephen")}}, 
+               {"g_mergeVXlabel_person_name_markoX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.MergeV(p["xx1"]), (g,p) =>g.V().Has("person","name","marko")}}, 
+               {"g_mergeVXlabel_person_name_stephenX_optionXonCreate_label_person_name_stephen_age_19X_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.MergeV(p["xx1"]).Option(Merge.OnCreate,p["xx2"]), (g,p) =>g.V().Has("person","name","stephen").Has("age",19)}}, 
+               {"g_mergeVXlabel_person_name_markoX_optionXonMatch_age_19X_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.MergeV(p["xx1"]).Option(Merge.OnMatch,p["xx2"]), (g,p) =>g.V().Has("person","name","marko").Has("age",19)}}, 
+               {"g_withSideEffectXc_label_person_name_stephenX_withSideEffectXm_label_person_name_stephen_age_19X_mergeVXselectXcXX_optionXonCreate_selectXmXX_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.WithSideEffect("c",p["xx1"]).WithSideEffect("m",p["xx2"]).MergeV(__.Select<object>("c")).Option(Merge.OnCreate,__.Select<object>("m")), (g,p) =>g.V().Has [...]
+               {"g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_mergeVXselectXcXX_optionXonMatch_selectXmXX_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.WithSideEffect("c",p["xx1"]).WithSideEffect("m",p["xx2"]).MergeV(__.Select<object>("c")).Option(Merge.OnMatch,__.Select<object>("m")), (g,p) =>g.V().Has("person","name","marko").Has( [...]
+               {"g_mergeVXlabel_person_name_markoX_propertyXname_vadas_acl_publicX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.MergeV(p["xx1"]).Property("name","vadas","acl","public"), (g,p) =>g.V().Properties<object>("name").HasValue("vadas").Has("acl","public")}}, 
+               {"g_injectX0X_mergeVXlabel_person_name_stephenX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.Inject(0).MergeV(p["xx1"]), (g,p) =>g.V().Has("person","name","stephen")}}, 
+               {"g_injectX0X_mergeVXlabel_person_name_markoX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.Inject(0).MergeV(p["xx1"]), (g,p) =>g.V().Has("person","name","marko")}}, 
+               {"g_injectX0X_mergeVXlabel_person_name_stephenX_optionXonCreate_label_person_name_stephen_age_19X_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.Inject(0).MergeV(p["xx1"]).Option(Merge.OnCreate,p["xx2"]), (g,p) =>g.V().Has("person","name","stephen").Has("age",19)}}, 
+               {"g_injectX0X_mergeVXlabel_person_name_markoX_optionXonMatch_age_19X_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.Inject(0).MergeV(p["xx1"]).Option(Merge.OnMatch,p["xx2"]), (g,p) =>g.V().Has("person","name","marko").Has("age",19)}}, 
+               {"g_withSideEffectXc_label_person_name_stephenX_withSideEffectXm_label_person_name_stephen_age_19X_injectX0X_mergeVXselectXcXX_optionXonCreate_selectXmXX_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.WithSideEffect("c",p["xx1"]).WithSideEffect("m",p["xx2"]).Inject(0).MergeV(__.Select<object>("c")).Option(Merge.OnCreate,__.Select<object>("m") [...]
+               {"g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_injectX0X_mergeVXselectXcXX_optionXonMatch_selectXmXX_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.WithSideEffect("c",p["xx1"]).WithSideEffect("m",p["xx2"]).Inject(0).MergeV(__.Select<object>("c")).Option(Merge.OnMatch,__.Select<object>("m")), (g,p) =>g.V().Has("person", [...]
+               {"g_injectX0X_mergeVXlabel_person_name_markoX_propertyXname_vadas_acl_publicX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.Inject(0).MergeV(p["xx1"]).Property("name","vadas","acl","public"), (g,p) =>g.V().Properties<object>("name").HasValue("vadas").Has("acl","public")}}, 
+               {"g_injectXlabel_person_name_marko_label_person_name_stephenX_mergeVXidentityX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.Inject(p["xx1"],p["xx2"]).MergeV(__.Identity()), (g,p) =>g.V().Has("person","name","stephen"), (g,p) =>g.V().Has("person","name","marko"), (g,p) =>g.V()}}, 
                {"g_V_age_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Min<object>()}}, 
                {"g_V_foo_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("foo").Min<object>()}}, 
                {"g_V_name_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Min<object>()}}, 
diff --git a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/jsr223/ast/VarAsBindingASTTransformation.groovy b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/jsr223/ast/VarAsBindingASTTransformation.groovy
index 1da973d..ea3c65a 100644
--- a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/jsr223/ast/VarAsBindingASTTransformation.groovy
+++ b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/jsr223/ast/VarAsBindingASTTransformation.groovy
@@ -20,6 +20,7 @@
 package org.apache.tinkerpop.gremlin.groovy.jsr223.ast
 
 import org.apache.tinkerpop.gremlin.process.traversal.Order
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
 import org.apache.tinkerpop.gremlin.process.traversal.Translator
@@ -115,7 +116,11 @@ class VarAsBindingASTTransformation implements ASTTransformation {
                                 case GraphTraversal.Symbols.by:
                                     if (i == 1) bindingValue = new PropertyExpression(new ClassExpression(new ClassNode(Order)), "desc")
                                     break
-                                case GraphTraversal.Symbols.fail:
+                                case GraphTraversal.Symbols.mergeE:
+                                case GraphTraversal.Symbols.mergeV:
+                                    bindingValue = new MethodCallExpression(new ClassExpression(new ClassNode(Collections)), "emptyMap", new TupleExpression())
+                                    break
+                                case GraphTraversal.Symbols.option:
                                     if (i == 1) bindingValue = new MethodCallExpression(new ClassExpression(new ClassNode(Collections)), "emptyMap", new TupleExpression())
                                     break
                             }
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java
index 3baf20e..66b2dbd 100644
--- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java
@@ -484,6 +484,8 @@ public class GremlinGroovyScriptEngineTest {
         final Traversal.Admin<Vertex, Vertex> t = (Traversal.Admin<Vertex, Vertex>)
                 engine.eval("g.V(v1Id).has(\"person\",\"age\",29).has('person','active',x).in(\"knows\")." +
                         System.lineSeparator() +
+                        "mergeE(m1).mergeV(m2).option(Merge.onCreate,m3)." +
+                        System.lineSeparator() +
                         "choose(__.out().count()).option(two, __.values(\"name\")).option(three, __.values(\"age\"))." +
                         System.lineSeparator() +
                         "filter(outE().count().is(y))."  +
@@ -498,15 +500,18 @@ public class GremlinGroovyScriptEngineTest {
         final String gremlinAsPython = translator.translate(bytecode).getScript();
 
         final Map<String,Object> bytecodeBindings = bytecode.getBindings();
-        assertEquals(7, bytecodeBindings.size());
+        assertEquals(10, bytecodeBindings.size());
         assertThat(bytecodeBindings.containsKey("x"), is(true));
         assertThat(bytecodeBindings.containsKey("y"), is(true));
         assertThat(bytecodeBindings.containsKey("v1Id"), is(true));
         assertThat(bytecodeBindings.containsKey("l"), is(true));
         assertThat(bytecodeBindings.containsKey("o"), is(true));
+        assertThat(bytecodeBindings.containsKey("m1"), is(true));
+        assertThat(bytecodeBindings.containsKey("m2"), is(true));
+        assertThat(bytecodeBindings.containsKey("m3"), is(true));
         assertThat(bytecodeBindings.containsKey("two"), is(true));
         assertThat(bytecodeBindings.containsKey("three"), is(true));
 
-        assertEquals("g.V(v1Id).has('person','age',29).has('person','active',x).in_('knows').choose(__.out().count()).option(two,__.name).option(three,__.age).filter_(__.outE().count().is_(y)).map(l).order().by('name',o)", gremlinAsPython);
+        assertEquals("g.V(v1Id).has('person','age',29).has('person','active',x).in_('knows').mergeE(m1).mergeV(m2).option(Merge.onCreate,m3).choose(__.out().count()).option(two,__.name).option(three,__.age).filter_(__.outE().count().is_(y)).map(l).order().by('name',o)", gremlinAsPython);
     }
 }
\ No newline at end of file
diff --git a/gremlin-javascript/build/generate.groovy b/gremlin-javascript/build/generate.groovy
index 013f840..1b52ea4 100644
--- a/gremlin-javascript/build/generate.groovy
+++ b/gremlin-javascript/build/generate.groovy
@@ -31,6 +31,16 @@ import java.nio.file.Paths
 
 import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal
 
+// getting an exception like:
+// > InvocationTargetException: javax.script.ScriptException: groovy.lang.MissingMethodException: No signature of
+// > method: org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal.mergeE() is applicable for
+// > argument types: (String) values: [4ffdea36-4a0e-4681-acba-e76875d1b25b]
+// usually means bindings are not being extracted properly by VarAsBindingASTTransformation which typically happens
+// when a step is taking an argument that cannot properly resolve to the type required by the step itself. there are
+// special cases in that VarAsBindingASTTransformation class which might need to be adjusted. Editing the
+// GremlinGroovyScriptEngineTest#shouldProduceBindingsForVars() with the failing step and argument can typically make
+// this issue relatively easy to debug and enforce.
+
 // file is overwritten on each generation
 radishGremlinFile = new File("${projectBaseDir}/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js")
 
@@ -84,6 +94,7 @@ radishGremlinFile.withWriter('UTF-8') { Writer writer ->
                     '    IN: traversalModule.direction.in,\n' +
                     '    OUT: traversalModule.direction.out\n' +
                     '};\n' +
+                    'const Merge = traversalModule.merge;\n' +
                     'const P = traversalModule.P;\n' +
                     'const Pick = traversalModule.pick\n' +
                     'const Pop = traversalModule.pop\n' +
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
index 6c49ec5..c609ba0 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
@@ -810,6 +810,26 @@ class GraphTraversal extends Traversal {
     this.bytecode.addStep('mean', args);
     return this;
   }
+
+  /**
+   * Graph traversal mergeE method.
+   * @param {...Object} args
+   * @returns {GraphTraversal}
+   */
+  mergeE(...args) {
+    this.bytecode.addStep("mergeE", args);
+    return this;
+  }
+
+  /**
+   * Graph traversal mergeV method.
+   * @param {...Object} args
+   * @returns {GraphTraversal}
+   */
+  mergeV(...args) {
+    this.bytecode.addStep("mergeV", args);
+    return this;
+  }
   
   /**
    * Graph traversal min method.
@@ -1365,6 +1385,8 @@ const statics = {
   math: (...args) => callOnEmptyTraversal('math', args),
   max: (...args) => callOnEmptyTraversal('max', args),
   mean: (...args) => callOnEmptyTraversal('mean', args),
+  mergeE: (...args) => callOnEmptyTraversal("mergeE", args),
+  mergeV: (...args) => callOnEmptyTraversal("mergeV", args),
   min: (...args) => callOnEmptyTraversal('min', args),
   not: (...args) => callOnEmptyTraversal('not', args),
   optional: (...args) => callOnEmptyTraversal('optional', args),
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
index f72c3f9..bbffeea 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
@@ -496,6 +496,7 @@ module.exports = {
   direction: toEnum('Direction', 'BOTH IN OUT'),
   graphSONVersion: toEnum('GraphSONVersion', 'V1_0 V2_0 V3_0'),
   gryoVersion: toEnum('GryoVersion', 'V1_0 V3_0'),
+  merge: toEnum('Merge', 'onCreate onMatch'),
   operator: toEnum('Operator', 'addAll and assign div max min minus mult or sum sumLong'),
   order: toEnum('Order', 'asc desc shuffle'),
   pick: toEnum('Pick', 'any none'),
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 23d914d..bad83af 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
@@ -36,6 +36,7 @@ const Direction = {
     IN: traversalModule.direction.in,
     OUT: traversalModule.direction.out
 };
+const Merge = traversalModule.merge;
 const P = traversalModule.P;
 const Pick = traversalModule.pick
 const Pop = traversalModule.pop
@@ -486,4 +487,370 @@ const gremlins = {
     g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_mean: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").unfold().mean() }], 
     g_injectXnull_10_20_nullX_mean: [function({g, xx1, xx2}) { return g.inject(null,xx1,xx2,null).mean() }], 
     g_injectXlistXnull_10_20_nullXX_meanXlocalX: [function({g, xx1}) { return g.inject(xx1).mean(Scope.local) }], 
-    g_injectX0X_mergeVXlabel_person_name_stephenX: [
\ No newline at end of file
+    g_V_mergeEXlabel_self_weight_05X: [function({g, xx1}) { return g.addV("person").property("name","marko").property("age",29) }, function({g, xx1}) { return g.V().mergeE(xx1) }, function({g, xx1}) { return g.E().hasLabel("self").has("weight",0.5) }], 
+    g_mergeEXlabel_knows_out_marko_in_vadasX: [function({g, xx1}) { return g.addV("person").property(T.id,100).property("name","marko").addV("person").property(T.id,101).property("name","vadas") }, function({g, xx1}) { return g.mergeE(xx1) }, function({g, xx1}) { return g.V().has("person","name","marko").out("knows").has("person","name","vadas") }], 
+    g_mergeEXlabel_knows_out_marko_in_vadas_weight_05X_exists: [function({g, xx1}) { return g.addV("person").property(T.id,100).property("name","marko").as("a").addV("person").property(T.id,101).property("name","vadas").as("b").addE("knows").from_("a").to("b") }, function({g, xx1}) { return g.mergeE(xx1) }, function({g, xx1}) { return g.V().has("person","name","marko").outE("knows").has("weight",0.5).inV().has("person","name","vadas") }, function({g, xx1}) { return g.V().has("person","na [...]
+    g_mergeEXlabel_knows_out_marko_in_vadas_weight_05X: [function({g, xx1}) { return g.mergeE(xx1) }, function({g, xx1}) { return g.V() }, function({g, xx1}) { return g.E().hasLabel("knows").has("weight",0.5) }], 
+    g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX: [function({g, xx1, xx3, xx2}) { return g.mergeE(xx1).option(Merge.onCreate,xx2).option(Merge.onMatch,xx3) }, function({g, xx1, xx3, xx2}) { return g.V() }, function({g, xx1, xx3, xx2}) { return g.E().hasLabel("knows").has("created","Y") }, function({g, xx1, xx3, xx2}) { return g.E().hasLabel("knows").has("created","N") }], 
+    g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists: [function({g, xx1, xx3, xx2}) { return g.addV("person").property(T.id,100).property("name","marko").as("a").addV("person").property(T.id,101).property("name","vadas").as("b").addE("knows").from_("a").to("b") }, function({g, xx1, xx3, xx2}) { return g.mergeE(xx1).option(Merge.onCreate,xx2).option(Merge.onMatch,xx3) }, function({g, xx1, xx3, xx2}) { return g.V() }, function({g, xx1, xx [...]
+    g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated: [function({g, xx1, xx3, xx2}) { return g.addV("person").property(T.id,100).property("name","marko").as("a").addV("person").property(T.id,101).property("name","vadas").as("b").addE("knows").from_("a").to("b").property("created","Y") }, function({g, xx1, xx3, xx2}) { return g.mergeE(xx1).option(Merge.onCreate,xx2).option(Merge.onMatch,xx3) }, function({g, xx1, xx3, xx2}) { retu [...]
+    g_V_hasXperson_name_marko_X_mergeEXlabel_knowsX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated: [function({g, xx1, xx3, xx2}) { return g.addV("person").property(T.id,100).property("name","marko").as("a").addV("person").property(T.id,101).property("name","vadas").as("b").addE("knows").from_("a").to("b").property("created","Y").addE("knows").from_("a").to("b") }, function({g, xx1, xx3, xx2}) { return g.V().has("person","name","marko").mergeE(xx1).option(Merge.onCre [...]
+    g_VX100X_VX101X_mergeEXlabel_knows_out_marko_in_vadasX: [function({g, xx1}) { return g.addV("person").property(T.id,100).property("name","marko") }, function({g, xx1}) { return g.V(100).V(101).mergeE(xx1) }, function({g, xx1}) { return g.V() }, function({g, xx1}) { return g.E() }], 
+    g_mergeVXlabel_person_name_stephenX: [function({g, xx1}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1}) { return g.mergeV(xx1) }, function({g, xx1}) { return g.V().has("person","name","stephen") }], 
+    g_mergeVXlabel_person_name_markoX: [function({g, xx1}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1}) { return g.mergeV(xx1) }, function({g, xx1}) { return g.V().has("person","name","marko") }], 
+    g_mergeVXlabel_person_name_stephenX_optionXonCreate_label_person_name_stephen_age_19X_option: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.mergeV(xx1).option(Merge.onCreate,xx2) }, function({g, xx1, xx2}) { return g.V().has("person","name","stephen").has("age",19) }], 
+    g_mergeVXlabel_person_name_markoX_optionXonMatch_age_19X_option: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.mergeV(xx1).option(Merge.onMatch,xx2) }, function({g, xx1, xx2}) { return g.V().has("person","name","marko").has("age",19) }], 
+    g_withSideEffectXc_label_person_name_stephenX_withSideEffectXm_label_person_name_stephen_age_19X_mergeVXselectXcXX_optionXonCreate_selectXmXX_option: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.withSideEffect("c",xx1).withSideEffect("m",xx2).mergeV(__.select("c")).option(Merge.onCreate,__.select("m")) }, function({g, xx1, xx2}) { return g.V().has("person","name","stephen").has("age",19) }], 
+    g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_mergeVXselectXcXX_optionXonMatch_selectXmXX_option: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.withSideEffect("c",xx1).withSideEffect("m",xx2).mergeV(__.select("c")).option(Merge.onMatch,__.select("m")) }, function({g, xx1, xx2}) { return g.V().has("person","name","marko").has("age",19) }], 
+    g_mergeVXlabel_person_name_markoX_propertyXname_vadas_acl_publicX: [function({g, xx1}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1}) { return g.mergeV(xx1).property("name","vadas","acl","public") }, function({g, xx1}) { return g.V().properties("name").hasValue("vadas").has("acl","public") }], 
+    g_injectX0X_mergeVXlabel_person_name_stephenX: [function({g, xx1}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1}) { return g.inject(0).mergeV(xx1) }, function({g, xx1}) { return g.V().has("person","name","stephen") }], 
+    g_injectX0X_mergeVXlabel_person_name_markoX: [function({g, xx1}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1}) { return g.inject(0).mergeV(xx1) }, function({g, xx1}) { return g.V().has("person","name","marko") }], 
+    g_injectX0X_mergeVXlabel_person_name_stephenX_optionXonCreate_label_person_name_stephen_age_19X_option: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.inject(0).mergeV(xx1).option(Merge.onCreate,xx2) }, function({g, xx1, xx2}) { return g.V().has("person","name","stephen").has("age",19) }], 
+    g_injectX0X_mergeVXlabel_person_name_markoX_optionXonMatch_age_19X_option: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.inject(0).mergeV(xx1).option(Merge.onMatch,xx2) }, function({g, xx1, xx2}) { return g.V().has("person","name","marko").has("age",19) }], 
+    g_withSideEffectXc_label_person_name_stephenX_withSideEffectXm_label_person_name_stephen_age_19X_injectX0X_mergeVXselectXcXX_optionXonCreate_selectXmXX_option: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.withSideEffect("c",xx1).withSideEffect("m",xx2).inject(0).mergeV(__.select("c")).option(Merge.onCreate,__.select("m")) }, function({g, xx1, xx2}) { return g.V().has("person","name","s [...]
+    g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_injectX0X_mergeVXselectXcXX_optionXonMatch_selectXmXX_option: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.withSideEffect("c",xx1).withSideEffect("m",xx2).inject(0).mergeV(__.select("c")).option(Merge.onMatch,__.select("m")) }, function({g, xx1, xx2}) { return g.V().has("person","name","marko").has("age",19) }], 
+    g_injectX0X_mergeVXlabel_person_name_markoX_propertyXname_vadas_acl_publicX: [function({g, xx1}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1}) { return g.inject(0).mergeV(xx1).property("name","vadas","acl","public") }, function({g, xx1}) { return g.V().properties("name").hasValue("vadas").has("acl","public") }], 
+    g_injectXlabel_person_name_marko_label_person_name_stephenX_mergeVXidentityX: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.inject(xx1,xx2).mergeV(__.identity()) }, function({g, xx1, xx2}) { return g.V().has("person","name","stephen") }, function({g, xx1, xx2}) { return g.V().has("person","name","marko") }, function({g, xx1, xx2}) { return g.V() }], 
+    g_V_age_min: [function({g}) { return g.V().values("age").min() }], 
+    g_V_foo_min: [function({g}) { return g.V().values("foo").min() }], 
+    g_V_name_min: [function({g}) { return g.V().values("name").min() }], 
+    g_V_age_fold_minXlocalX: [function({g}) { return g.V().values("age").fold().min(Scope.local) }], 
+    g_V_aggregateXaX_byXageX_capXaX_minXlocalX: [function({g}) { return g.V().aggregate("a").by("age").cap("a").min(Scope.local) }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_minXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").min(Scope.local) }], 
+    g_V_aggregateXaX_byXageX_capXaX_unfold_min: [function({g}) { return g.V().aggregate("a").by("age").cap("a").unfold().min() }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_min: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").unfold().min() }], 
+    g_V_aggregateXaX_byXfooX_capXaX_minXlocalX: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").min(Scope.local) }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_minXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").min(Scope.local) }], 
+    g_V_aggregateXaX_byXfooX_capXaX_unfold_min: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").unfold().min() }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_min: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").unfold().min() }], 
+    g_V_foo_fold_minXlocalX: [function({g}) { return g.V().values("foo").fold().min(Scope.local) }], 
+    g_V_name_fold_minXlocalX: [function({g}) { return g.V().values("name").fold().min(Scope.local) }], 
+    g_V_repeatXbothX_timesX5X_age_min: [function({g}) { return g.V().repeat(__.both()).times(5).values("age").min() }], 
+    g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_minX: [function({g}) { return g.V().hasLabel("software").group().by("name").by(__.bothE().values("weight").min()) }], 
+    g_V_foo_injectX9999999999X_min: [function({g, xx1}) { return g.V().values("foo").inject(xx1).min() }], 
+    g_V_name_order: [function({g}) { return g.V().values("name").order() }], 
+    g_V_name_order_byXa1_b1X_byXb2_a2X: [function({g, c1, c2}) { return g.V().values("name").order().by(c1).by(c2) }], 
+    g_V_order_byXname_ascX_name: [function({g}) { return g.V().order().by("name",Order.asc).values("name") }], 
+    g_V_order_byXnameX_name: [function({g}) { return g.V().order().by("name").values("name") }], 
+    g_V_outE_order_byXweight_descX_weight: [function({g}) { return g.V().outE().order().by("weight",Order.desc).values("weight") }], 
+    g_V_order_byXname_a1_b1X_byXname_b2_a2X_name: [function({g, c1, c2}) { return g.V().order().by("name",c1).by("name",c2).values("name") }], 
+    g_V_asXaX_outXcreatedX_asXbX_order_byXshuffleX_selectXa_bX: [function({g}) { return g.V().as("a").out("created").as("b").order().by(Order.shuffle).select("a","b") }], 
+    g_V_both_hasLabelXpersonX_order_byXage_descX_limitX5X_name: [function({g}) { return g.V().both().hasLabel("person").order().by("age",Order.desc).limit(5).values("name") }], 
+    g_V_properties_order_byXkey_descX_key: [function({g}) { return g.V().properties().order().by(T.key,Order.desc).key() }], 
+    g_V_hasLabelXpersonX_order_byXvalueXageX_descX_name: [function({g, l1}) { return g.V().hasLabel("person").order().by(l1,Order.desc).values("name") }], 
+    g_V_hasLabelXpersonX_group_byXnameX_byXoutE_weight_sumX_orderXlocalX_byXvaluesX: [function({g}) { return g.V().hasLabel("person").group().by("name").by(__.outE().values("weight").sum()).order(Scope.local).by(Column.values) }], 
+    g_V_mapXbothE_weight_foldX_order_byXsumXlocalX_descX: [function({g}) { return g.V().map(__.bothE().values("weight").order().by(Order.asc).fold()).order().by(__.sum(Scope.local),Order.desc) }], 
+    g_V_group_byXlabelX_byXname_order_byXdescX_foldX: [function({g}) { return g.V().group().by(T.label).by(__.values("name").order().by(Order.desc).fold()) }], 
+    g_V_hasLabelXpersonX_group_byXnameX_byXoutE_weight_sumX_unfold_order_byXvalues_descX: [function({g}) { return g.V().hasLabel("person").group().by("name").by(__.outE().values("weight").sum()).unfold().order().by(Column.values,Order.desc) }], 
+    g_V_asXvX_mapXbothE_weight_foldX_sumXlocalX_asXsX_selectXv_sX_order_byXselectXsX_descX: [function({g}) { return g.V().as("v").map(__.bothE().values("weight").fold()).sum(Scope.local).as("s").select("v","s").order().by(__.select("s"),Order.desc) }], 
+    g_V_hasLabelXpersonX_fold_orderXlocalX_byXageX: [function({g}) { return g.V().hasLabel("person").fold().order(Scope.local).by("age") }], 
+    g_V_both_hasLabelXpersonX_order_byXage_descX_name: [function({g}) { return g.V().both().hasLabel("person").order().by("age",Order.desc).values("name") }], 
+    g_V_order_byXoutE_count_descX: [function({g}) { return g.V().order().by(__.outE().count(),Order.desc) }], 
+    g_V_hasLabelXpersonX_order_byXageX: [function({g}) { return g.V().hasLabel("person").order().by("age") }], 
+    g_V_order_byXageX: [function({g}) { return g.V().order().by("age") }], 
+    g_V_fold_orderXlocalX_byXageX: [function({g}) { return g.V().fold().order(Scope.local).by("age") }], 
+    g_V_fold_orderXlocalX_byXage_descX: [function({g}) { return g.V().fold().order(Scope.local).by("age",Order.desc) }], 
+    g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX: [function({g}) { return g.V().or(__.hasLabel("person"),__.has("software","name","lop")).order().by("age") }], 
+    g_withStrategiesXProductiveByStrategyX_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().or(__.hasLabel("person"),__.has("software","name","lop")).order().by("age") }], 
+    g_VX1X_hasXlabel_personX_mapXmapXint_ageXX_orderXlocalX_byXvalues_descX_byXkeys_ascX: [function({g, l1, v1}) { return g.V(v1).hasLabel("person").map(l1).order(Scope.local).by(Column.values,Order.desc).by(Column.keys,Order.asc) }], 
+    g_V_hasXsong_name_OHBOYX_outXfollowedByX_outXfollowedByX_order_byXperformancesX_byXsongType_descX: [function({g}) { return g.V().has("song","name","OH BOY").out("followedBy").out("followedBy").order().by("performances").by("songType",Order.desc).by("name") }], 
+    g_V_hasLabelXsongX_order_byXperformances_descX_byXnameX_rangeX110_120X_name: [function({g}) { return g.V().hasLabel("song").order().by("performances",Order.desc).by("name").range(110,120).values("name") }], 
+    g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold: [function({g, vid1}) { return g.V(vid1).elementMap().order(Scope.local).by(Column.keys,Order.desc).unfold() }], 
+    g_VX1X_elementMap_orderXlocalX_byXkeys_ascXunfold: [function({g, vid1}) { return g.V(vid1).elementMap().order(Scope.local).by(Column.keys,Order.asc).unfold() }], 
+    g_V_pageRank_hasXpageRankX: [function({g}) { return g.V().pageRank().has("gremlin.pageRankVertexProgram.pageRank") }], 
+    g_V_outXcreatedX_pageRank_withXedges_bothEX_withXpropertyName_projectRankX_withXtimes_0X_valueMapXname_projectRankX: [function({g}) { return g.V().out("created").pageRank().with_("~tinkerpop.pageRank.edges",__.bothE()).with_("~tinkerpop.pageRank.propertyName","projectRank").with_("~tinkerpop.pageRank.times",0).valueMap("name","projectRank") }], 
+    g_V_pageRank_order_byXpageRank_descX_byXnameX_name: [function({g}) { return g.V().pageRank().order().by("gremlin.pageRankVertexProgram.pageRank",Order.desc).by("name").values("name") }], 
+    g_V_pageRank_order_byXpageRank_descX_name_limitX2X: [function({g}) { return g.V().pageRank().order().by("gremlin.pageRankVertexProgram.pageRank",Order.desc).values("name").limit(2) }], 
+    g_V_pageRank_withXedges_outEXknowsXX_withXpropertyName_friendRankX_project_byXnameX_byXvaluesXfriendRankX_mathX: [function({g}) { return g.V().pageRank().with_("~tinkerpop.pageRank.edges",__.outE("knows")).with_("~tinkerpop.pageRank.propertyName","friendRank").project("name","friendRank").by("name").by(__.values("friendRank").math("ceil(_ * 100)")) }], 
+    g_V_hasLabelXpersonX_pageRank_withXpropertyName_kpageRankX_project_byXnameX_byXvaluesXpageRankX_mathX: [function({g}) { return g.V().hasLabel("person").pageRank().with_("~tinkerpop.pageRank.propertyName","pageRank").project("name","pageRank").by("name").by(__.values("pageRank").math("ceil(_ * 100)")) }], 
+    g_V_pageRank_withXpropertyName_pageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX_by_byXmathX: [function({g}) { return g.V().pageRank().with_("~tinkerpop.pageRank.propertyName","pageRank").as("a").out("knows").values("pageRank").as("b").select("a","b").by().by(__.math("ceil(_ * 100)")) }], 
+    g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_withXedges_inEXcreatedX_withXtimes_1X_withXpropertyName_priorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX: [function({g}) { return g.V().hasLabel("software").has("name","ripple").pageRank(1.0).with_("~tinkerpop.pageRank.edges",__.inE("created")).with_("~tinkerpop.pageRank.times",1).with_("~tinkerpop.pageRank.propertyName","priors").in_("created").union(__.both(),__.identity()).valueMap("name","priors") }], 
+    g_V_outXcreatedX_groupXmX_byXlabelX_pageRankX1X_withXpropertyName_pageRankX_withXedges_inEX_withXtimes_1X_inXcreatedX_groupXmX_byXpageRankX_capXmX: [function({g}) { return g.V().out("created").group("m").by(T.label).pageRank(1.0).with_("~tinkerpop.pageRank.propertyName","pageRank").with_("~tinkerpop.pageRank.edges",__.inE()).with_("~tinkerpop.pageRank.times",1).in_("created").group("m").by("pageRank").cap("m") }], 
+    g_VX1X_name_path: [function({g, vid1}) { return g.V(vid1).values("name").path() }], 
+    g_VX1X_out_path_byXageX_byXnameX: [function({g, vid1}) { return g.V(vid1).out().path().by("age").by("name") }], 
+    g_V_repeatXoutX_timesX2X_path_byXitX_byXnameX_byXlangX: [function({g}) { return g.V().repeat(__.out()).times(2).path().by().by("name").by("lang") }], 
+    g_V_out_out_path_byXnameX_byXageX: [function({g}) { return g.V().out().out().path().by("name").by("age") }], 
+    g_V_asXaX_hasXname_markoX_asXbX_hasXage_29X_asXcX_path: [function({g}) { return g.V().as("a").has("name","marko").as("b").has("age",29).as("c").path() }], 
+    g_VX1X_outEXcreatedX_inV_inE_outV_path: [function({g, vid1}) { return g.V(vid1).outE("created").inV().inE().outV().path() }], 
+    g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX: [function({g}) { return g.V().as("a").out().as("b").out().as("c").path().from_("b").to("c").by("name") }], 
+    g_VX1X_out_path_byXageX: [function({g, vid1}) { return g.V(vid1).out().path().by("age") }], 
+    g_withStrategiesXProductiveByStrategyX_VX1X_out_path_byXageX: [function({g, vid1}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V(vid1).out().path().by("age") }], 
+    g_injectX1_null_nullX_path: [function({g}) { return g.inject(1,null,null).path() }], 
+    g_injectX1_null_nullX_path_dedup: [function({g}) { return g.inject(1,null,null).path().dedup() }], 
+    g_V_peerPressure_hasXclusterX: [function({g}) { return g.V().peerPressure().has("gremlin.peerPressureVertexProgram.cluster") }], 
+    g_V_peerPressure_withXpropertyName_clusterX_withXedges_outEXknowsXX_pageRankX1X_byXrankX_withXedges_outEXknowsX_withXtimes_2X_group_byXclusterX_byXrank_sumX_limitX100X: [function({g}) { return g.V().peerPressure().with_("~tinkerpop.peerPressure.propertyName","cluster").with_("~tinkerpop.peerPressure.edges",__.outE("knows")).pageRank(1.0).with_("~tinkerpop.pageRank.propertyName","rank").with_("~tinkerpop.pageRank.edges",__.outE("knows")).with_("~tinkerpop.pageRank.times",1).group().by [...]
+    g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXedges_outEX_withyXpropertyName_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX: [function({g}) { return g.V().has("name","ripple").in_("created").peerPressure().with_("~tinkerpop.peerPressure.edges",__.outE()).with_("~tinkerpop.peerPressure.propertyName","cluster").repeat(__.union(__.identity(),__.both())).times(2).dedup().valueMap("name","cluster") }], 
+    g_V_hasLabelXpersonX_projectXa_bX_byXoutE_countX_byXageX: [function({g}) { return g.V().hasLabel("person").project("a","b").by(__.outE().count()).by("age") }], 
+    g_V_outXcreatedX_projectXa_bX_byXnameX_byXinXcreatedX_countX_order_byXselectXbX__descX_selectXaX: [function({g}) { return g.V().out("created").project("a","b").by("name").by(__.in_("created").count()).order().by(__.select("b"),Order.desc).select("a") }], 
+    g_V_valueMap_projectXxX_byXselectXnameXX: [function({g}) { return g.V().valueMap().project("x").by(__.select("name")) }], 
+    g_V_projectXa_bX_byXinE_countX_byXageX: [function({g}) { return g.V().project("a","b").by(__.inE().count()).by("age") }], 
+    g_withStrategiesXProductiveByStrategyX_V_projectXa_bX_byXinE_countX_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().project("a","b").by(__.inE().count()).by("age") }], 
+    g_V_hasXageX_propertiesXnameX: [function({g}) { return g.V().has("age").properties("name").value() }], 
+    g_V_hasXageX_propertiesXname_ageX_value: [function({g}) { return g.V().has("age").properties("name","age").value() }], 
+    g_V_hasXageX_propertiesXage_nameX_value: [function({g}) { return g.V().has("age").properties("age","name").value() }], 
+    g_V_propertiesXname_age_nullX_value: [function({g}) { return g.V().properties("name","age",null).value() }], 
+    g_V_valuesXname_age_nullX: [function({g}) { return g.V().values("name","age",null) }], 
+    g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX: [function({g, vid1}) { return g.V(vid1).as("a").out("knows").as("b").select("a","b") }], 
+    g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX_byXnameX: [function({g, vid1}) { return g.V(vid1).as("a").out("knows").as("b").select("a","b").by("name") }], 
+    g_VX1X_asXaX_outXknowsX_asXbX_selectXaX: [function({g, vid1}) { return g.V(vid1).as("a").out("knows").as("b").select("a") }], 
+    g_VX1X_asXaX_outXknowsX_asXbX_selectXaX_byXnameX: [function({g, vid1}) { return g.V(vid1).as("a").out("knows").as("b").select("a").by("name") }], 
+    g_V_asXaX_out_asXbX_selectXa_bX_byXnameX: [function({g}) { return g.V().as("a").out().as("b").select("a","b").by("name") }], 
+    g_V_asXaX_out_aggregateXxX_asXbX_selectXa_bX_byXnameX: [function({g}) { return g.V().as("a").out().aggregate("x").as("b").select("a","b").by("name") }], 
+    g_V_asXaX_name_order_asXbX_selectXa_bX_byXnameX_by_XitX: [function({g}) { return g.V().as("a").values("name").order().as("b").select("a","b").by("name").by() }], 
+    g_V_hasXname_gremlinX_inEXusesX_order_byXskill_ascX_asXaX_outV_asXbX_selectXa_bX_byXskillX_byXnameX: [function({g}) { return g.V().has("name","gremlin").inE("uses").order().by("skill",Order.asc).as("a").outV().as("b").select("a","b").by("skill").by("name") }], 
+    g_V_hasXname_isXmarkoXX_asXaX_selectXaX: [function({g}) { return g.V().has("name",__.is("marko")).as("a").select("a") }], 
+    g_V_label_groupCount_asXxX_selectXxX: [function({g}) { return g.V().label().groupCount().as("x").select("x") }], 
+    g_V_hasLabelXpersonX_asXpX_mapXbothE_label_groupCountX_asXrX_selectXp_rX: [function({g}) { return g.V().hasLabel("person").as("p").map(__.bothE().label().groupCount()).as("r").select("p","r") }], 
+    g_V_chooseXoutE_count_isX0X__asXaX__asXbXX_chooseXselectXaX__selectXaX__selectXbXX: [function({g, xx1}) { return g.V().choose(__.outE().count().is(xx1),__.as("a"),__.as("b")).choose(__.select("a"),__.select("a"),__.select("b")) }], 
+    g_VX1X_groupXaX_byXconstantXaXX_byXnameX_selectXaX_selectXaX: [function({g, vid1}) { return g.V(vid1).group("a").by(__.constant("a")).by(__.values("name")).barrier().select("a").select("a") }], 
+    g_VX1X_asXhereX_out_selectXhereX: [function({g, vid1}) { return g.V(vid1).as("here").out().select("here") }], 
+    g_VX4X_out_asXhereX_hasXlang_javaX_selectXhereX: [function({g, vid4}) { return g.V(vid4).as("here").out().select("here") }], 
+    g_VX4X_out_asXhereX_hasXlang_javaX_selectXhereX_name: [function({g, vid4}) { return g.V(vid4).out().as("here").has("lang","java").select("here").values("name") }], 
+    g_VX1X_outE_asXhereX_inV_hasXname_vadasX_selectXhereX: [function({g, vid1}) { return g.V(vid1).outE().as("here").inV().has("name","vadas").select("here") }], 
+    g_VX1X_outEXknowsX_hasXweight_1X_asXhereX_inV_hasXname_joshX_selectXhereX: [function({g, vid1}) { return g.V(vid1).outE("knows").has("weight",1.0).as("here").inV().has("name","josh").select("here") }], 
+    g_VX1X_outEXknowsX_asXhereX_hasXweight_1X_asXfakeX_inV_hasXname_joshX_selectXhereX: [function({g, vid1}) { return g.V(vid1).outE("knows").as("here").has("weight",1.0).as("fake").inV().has("name","josh").select("here") }], 
+    g_V_asXhereXout_name_selectXhereX: [function({g}) { return g.V().as("here").out().values("name").select("here") }], 
+    g_V_outXcreatedX_unionXasXprojectX_inXcreatedX_hasXname_markoX_selectXprojectX__asXprojectX_inXcreatedX_inXknowsX_hasXname_markoX_selectXprojectXX_groupCount_byXnameX: [function({g}) { return g.V().out("created").union(__.as("project").in_("created").has("name","marko").select("project"),__.as("project").in_("created").in_("knows").has("name","marko").select("project")).groupCount().by("name") }], 
+    g_V_untilXout_outX_repeatXin_asXaXX_selectXaX_byXtailXlocalX_nameX: [function({g}) { return g.V().until(__.out().out()).repeat(__.in_().as("a")).select("a").by(__.tail(Scope.local).values("name")) }], 
+    g_V_outE_weight_groupCount_selectXkeysX_unfold: [function({g}) { return g.V().outE().values("weight").groupCount().select(Column.keys).unfold() }], 
+    g_V_hasLabelXsoftwareX_asXnameX_asXlanguageX_asXcreatorsX_selectXname_language_creatorsX_byXnameX_byXlangX_byXinXcreatedX_name_fold_orderXlocalXX: [function({g}) { return g.V().hasLabel("software").as("name").as("language").as("creators").select("name","language","creators").by("name").by("lang").by(__.in_("created").values("name").fold().order(Scope.local)) }], 
+    g_V_outE_weight_groupCount_unfold_selectXkeysX_unfold: [function({g}) { return g.V().outE().values("weight").groupCount().unfold().select(Column.keys).unfold() }], 
+    g_V_outE_weight_groupCount_unfold_selectXvaluesX_unfold: [function({g}) { return g.V().outE().values("weight").groupCount().unfold().select(Column.values).unfold() }], 
+    g_V_untilXout_outX_repeatXin_asXaX_in_asXbXX_selectXa_bX_byXnameX: [function({g}) { return g.V().until(__.out().out()).repeat(__.in_().as("a").in_().as("b")).select("a","b").by("name") }], 
+    g_V_outE_weight_groupCount_selectXvaluesX_unfold: [function({g}) { return g.V().outE().values("weight").groupCount().select(Column.values).unfold() }], 
+    g_V_asXaX_whereXoutXknowsXX_selectXaX: [function({g}) { return g.V().as("a").where(__.out("knows")).select("a") }], 
+    g_VX1X_asXaX_repeatXout_asXaXX_timesX2X_selectXfirst_aX: [function({g, vid1}) { return g.V(vid1).as("a").repeat(__.out().as("a")).times(2).select(Pop.first,"a") }], 
+    g_V_asXaX_outXknowsX_asXbX_localXselectXa_bX_byXnameXX: [function({g}) { return g.V().as("a").out("knows").as("b").local(__.select("a","b").by("name")) }], 
+    g_VX1X_asXaX_repeatXout_asXaXX_timesX2X_selectXlast_aX: [function({g, vid1}) { return g.V(vid1).as("a").repeat(__.out().as("a")).times(2).select(Pop.last,"a") }], 
+    g_VX1X_outEXknowsX_asXhereX_hasXweight_1X_inV_hasXname_joshX_selectXhereX: [function({g, vid1}) { return g.V(vid1).outE("knows").as("here").has("weight",1.0).inV().has("name","josh").select("here") }], 
+    g_V_asXaX_hasXname_markoX_asXbX_asXcX_selectXa_b_cX_by_byXnameX_byXageX: [function({g}) { return g.V().as("a").has("name","marko").as("b").as("c").select("a","b","c").by().by("name").by("age") }], 
+    g_V_outE_weight_groupCount_selectXvaluesX_unfold_groupCount_selectXvaluesX_unfold: [function({g}) { return g.V().outE().values("weight").groupCount().select(Column.values).unfold().groupCount().select(Column.values).unfold() }], 
+    g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX: [function({g}) { return g.V().as("a").group("m").by().by(__.bothE().count()).barrier().select("m").select(__.select("a")) }], 
+    g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX_byXmathX_plus_XX: [function({g}) { return g.V().as("a").group("m").by().by(__.bothE().count()).barrier().select("m").select(__.select("a")).by(__.math("_+_")) }], 
+    g_V_asXaX_outXknowsX_asXaX_selectXall_constantXaXX: [function({g}) { return g.V().as("a").out("knows").as("a").select(Pop.all,__.constant("a")) }], 
+    g_V_selectXaX: [function({g}) { return g.V().select("a") }], 
+    g_V_selectXaX_count: [function({g}) { return g.V().select("a").count() }], 
+    g_V_selectXa_bX: [function({g}) { return g.V().select("a","b") }], 
+    g_V_valueMap_selectXaX: [function({g}) { return g.V().valueMap().select("a") }], 
+    g_V_valueMap_selectXa_bX: [function({g}) { return g.V().valueMap().select("a","b") }], 
+    g_V_selectXfirst_aX: [function({g}) { return g.V().select(Pop.first,"a") }], 
+    g_V_selectXfirst_a_bX: [function({g}) { return g.V().select(Pop.first,"a","b") }], 
+    g_V_valueMap_selectXfirst_aX: [function({g}) { return g.V().valueMap().select(Pop.first,"a") }], 
+    g_V_valueMap_selectXfirst_a_bX: [function({g}) { return g.V().valueMap().select(Pop.first,"a","b") }], 
+    g_V_selectXlast_aX: [function({g}) { return g.V().select(Pop.last,"a") }], 
+    g_V_selectXlast_a_bX: [function({g}) { return g.V().select(Pop.last,"a","b") }], 
+    g_V_valueMap_selectXlast_aX: [function({g}) { return g.V().valueMap().select(Pop.last,"a") }], 
+    g_V_valueMap_selectXlast_a_bX: [function({g}) { return g.V().valueMap().select(Pop.last,"a","b") }], 
+    g_V_selectXall_aX: [function({g}) { return g.V().select(Pop.all,"a") }], 
+    g_V_selectXall_a_bX: [function({g}) { return g.V().select(Pop.all,"a","b") }], 
+    g_V_valueMap_selectXall_aX: [function({g}) { return g.V().valueMap().select(Pop.all,"a") }], 
+    g_V_valueMap_selectXall_a_bX: [function({g}) { return g.V().valueMap().select(Pop.all,"a","b") }], 
+    g_V_asXa_bX_out_asXcX_path_selectXkeysX: [function({g}) { return g.V().as("a","b").out().as("c").path().select(Column.keys) }, function({g}) { return g.V().as("a","b").out().as("c").path().select(Column.keys) }], 
+    g_V_hasXperson_name_markoX_barrier_asXaX_outXknows_selectXaX: [function({g}) { return g.V().has("person","name","marko").barrier().as("a").out("knows").select("a") }], 
+    g_V_hasXperson_name_markoX_elementMapXnameX_asXaX_unionXidentity_identityX_selectXaX_selectXnameX: [function({g}) { return g.V().has("person","name","marko").elementMap("name").as("a").union(__.identity(),__.identity()).select("a").select("name") }], 
+    g_V_hasXperson_name_markoX_count_asXaX_unionXidentity_identityX_selectXaX: [function({g}) { return g.V().has("person","name","marko").count().as("a").union(__.identity(),__.identity()).select("a") }], 
+    g_V_hasXperson_name_markoX_path_asXaX_unionXidentity_identityX_selectXaX_unfold: [function({g}) { return g.V().has("person","name","marko").path().as("a").union(__.identity(),__.identity()).select("a").unfold() }], 
+    g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX: [function({g, eid11}) { return g.E(eid11).properties("weight").as("a").select("a").by(T.key) }], 
+    g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX: [function({g, eid11}) { return g.E(eid11).properties("weight").as("a").select("a").by(T.value) }], 
+    g_V_asXaX_selectXaX_byXageX: [function({g}) { return g.V().as("a").select("a").by("age") }], 
+    g_V_asXa_nX_selectXa_nX_byXageX_byXnameX: [function({g}) { return g.V().as("a","n").select("a","n").by("age").by("name") }], 
+    g_withStrategiesXProductiveByStrategyX_V_asXaX_selectXaX_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().as("a").select("a").by("age") }], 
+    g_withSideEffectXk_nullX_injectXxX_selectXkX: [function({g}) { return g.withSideEffect("k",null).inject("x").select("k") }], 
+    g_V_shortestPath: [function({g}) { return g.V().identity().shortestPath() }], 
+    g_V_both_dedup_shortestPath: [function({g}) { return g.V().both().dedup().shortestPath() }], 
+    g_V_shortestPath_edgesIncluded: [function({g}) { return g.V().identity().shortestPath().with_("~tinkerpop.shortestPath.includeEdges") }], 
+    g_V_shortestPath_directionXINX: [function({g}) { return g.V().identity().shortestPath().with_("~tinkerpop.shortestPath.edges",Direction.IN) }], 
+    g_V_shortestPath_edgesXoutEX: [function({g}) { return g.V().identity().shortestPath().with_("~tinkerpop.shortestPath.edges",__.outE()) }], 
+    g_V_shortestPath_edgesIncluded_edgesXoutEX: [function({g}) { return g.V().identity().shortestPath().with_("~tinkerpop.shortestPath.includeEdges").with_("~tinkerpop.shortestPath.edges",__.outE()) }], 
+    g_V_hasXname_markoX_shortestPath: [function({g}) { return g.V().has("name","marko").shortestPath() }], 
+    g_V_shortestPath_targetXhasXname_markoXX: [function({g}) { return g.V().identity().shortestPath().with_("~tinkerpop.shortestPath.target",__.has("name","marko")) }], 
+    g_V_shortestPath_targetXvaluesXnameX_isXmarkoXX: [function({g}) { return g.V().identity().shortestPath().with_("~tinkerpop.shortestPath.target",__.values("name").is("marko")) }], 
+    g_V_hasXname_markoX_shortestPath_targetXhasLabelXsoftwareXX: [function({g}) { return g.V().has("name","marko").shortestPath().with_("~tinkerpop.shortestPath.target",__.hasLabel("software")) }], 
+    g_V_hasXname_markoX_shortestPath_targetXhasXname_joshXX_distanceXweightX: [function({g}) { return g.V().has("name","marko").shortestPath().with_("~tinkerpop.shortestPath.target",__.has("name","josh")).with_("~tinkerpop.shortestPath.distance","weight") }], 
+    g_V_hasXname_danielX_shortestPath_targetXhasXname_stephenXX_edgesXbothEXusesXX: [function({g}) { return g.V().has("name","daniel").shortestPath().with_("~tinkerpop.shortestPath.target",__.has("name","stephen")).with_("~tinkerpop.shortestPath.edges",__.bothE("uses")) }], 
+    g_V_hasXsong_name_MIGHT_AS_WELLX_shortestPath_targetXhasXsong_name_MAYBE_YOU_KNOW_HOW_I_FEELXX_edgesXoutEXfollowedByXX_distanceXweightX: [function({g}) { return g.V().has("song","name","MIGHT AS WELL").shortestPath().with_("~tinkerpop.shortestPath.target",__.has("song","name","MAYBE YOU KNOW HOW I FEEL")).with_("~tinkerpop.shortestPath.edges",__.outE("followedBy")).with_("~tinkerpop.shortestPath.distance","weight") }], 
+    g_V_hasXname_markoX_shortestPath_maxDistanceX1X: [function({g}) { return g.V().has("name","marko").shortestPath().with_("~tinkerpop.shortestPath.maxDistance",1) }], 
+    g_V_hasXname_vadasX_shortestPath_distanceXweightX_maxDistanceX1_3X: [function({g}) { return g.V().has("name","vadas").shortestPath().with_("~tinkerpop.shortestPath.distance","weight").with_("~tinkerpop.shortestPath.maxDistance",1.3) }], 
+    g_V_age_sum: [function({g}) { return g.V().values("age").sum() }], 
+    g_V_foo_sum: [function({g}) { return g.V().values("foo").sum() }], 
+    g_V_age_fold_sumXlocalX: [function({g}) { return g.V().values("age").fold().sum(Scope.local) }], 
+    g_V_foo_fold_sumXlocalX: [function({g}) { return g.V().values("foo").fold().sum(Scope.local) }], 
+    g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_sumX: [function({g}) { return g.V().hasLabel("software").group().by("name").by(__.bothE().values("weight").sum()) }], 
+    g_V_aggregateXaX_byXageX_sumXlocalX: [function({g}) { return g.V().aggregate("a").by("age").cap("a").sum(Scope.local) }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_sumXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").sum(Scope.local) }], 
+    g_V_aggregateXaX_byXageX_capXaX_unfold_sum: [function({g}) { return g.V().aggregate("a").by("age").cap("a").unfold().sum() }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_sum: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").unfold().sum() }], 
+    g_V_aggregateXaX_byXfooX_sumXlocalX: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").sum(Scope.local) }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_sumXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").sum(Scope.local) }], 
+    g_V_aggregateXaX_byXfooX_capXaX_unfold_sum: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").unfold().sum() }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_sum: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").unfold().sum() }], 
+    g_injectXnull_10_5_nullX_sum: [function({g, xx1, xx2}) { return g.inject(null,xx1,xx2,null).sum() }], 
+    g_injectXlistXnull_10_5_nullXX_sumXlocalX: [function({g, xx1}) { return g.inject(xx1).sum(Scope.local) }], 
+    g_V_localXoutE_foldX_unfold: [function({g}) { return g.V().local(__.outE().fold()).unfold() }], 
+    g_V_valueMap_unfold_mapXkeyX: [function({g, l1}) { return g.V().valueMap().unfold().map(l1) }], 
+    g_VX1X_repeatXboth_simplePathX_untilXhasIdX6XX_path_byXnameX_unfold: [function({g, vid6, vid1}) { return g.V(vid1).repeat(__.both().simplePath()).until(__.hasId(vid6)).path().by("name").unfold() }], 
+    g_V_valueMap: [function({g}) { return g.V().valueMap() }], 
+    g_V_valueMapXtrueX: [function({g}) { return g.V().valueMap(true) }], 
+    g_V_valueMap_withXtokensX: [function({g}) { return g.V().valueMap().with_("~tinkerpop.valueMap.tokens") }], 
+    g_V_valueMapXname_ageX: [function({g}) { return g.V().valueMap("name","age") }], 
+    g_V_valueMapXtrue_name_ageX: [function({g}) { return g.V().valueMap(true,"name","age") }], 
+    g_V_valueMapXname_ageX_withXtokensX: [function({g}) { return g.V().valueMap("name","age").with_("~tinkerpop.valueMap.tokens") }], 
+    g_V_valueMapXname_ageX_withXtokens_labelsX_byXunfoldX: [function({g}) { return g.V().valueMap("name","age").with_("~tinkerpop.valueMap.tokens",2).by(__.unfold()) }], 
+    g_V_valueMapXname_ageX_withXtokens_idsX_byXunfoldX: [function({g}) { return g.V().valueMap("name","age").with_("~tinkerpop.valueMap.tokens",1).by(__.unfold()) }], 
+    g_VX1X_outXcreatedX_valueMap: [function({g, vid1}) { return g.V(vid1).out("created").valueMap() }], 
+    g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMapXtrueX: [function({g}) { return g.V().hasLabel("person").filter(__.outE("created")).valueMap(true) }], 
+    g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX: [function({g}) { return g.V().hasLabel("person").filter(__.outE("created")).valueMap().with_("~tinkerpop.valueMap.tokens") }], 
+    g_VX1X_valueMapXname_locationX_byXunfoldX_by: [function({g, vid1}) { return g.V(vid1).valueMap("name","location").by(__.unfold()).by() }], 
+    g_V_valueMapXname_age_nullX: [function({g}) { return g.V().valueMap("name","age",null) }], 
+    g_V_valueMapXname_ageX_byXisXxXXbyXunfoldX: [function({g}) { return g.V().valueMap("name","age").by(__.is("x")).by(__.unfold()) }], 
+    g_VXnullX: [function({g}) { return g.V(null) }], 
+    g_VXlistXnullXX: [function({g, xx1}) { return g.V(xx1) }], 
+    g_VX1_nullX: [function({g, vid1}) { return g.V(vid1,null) }], 
+    g_VXlistX1_2_3XX_name: [function({g, xx1}) { return g.V(xx1).values("name") }], 
+    g_VXlistXv1_v2_v3XX_name: [function({g, xx1}) { return g.V(xx1).values("name") }], 
+    g_V: [function({g}) { return g.V() }], 
+    g_VXv1X_out: [function({g, v1}) { return g.V(v1).out() }], 
+    g_VX1X_out: [function({g, vid1}) { return g.V(vid1).out() }], 
+    g_VX2X_in: [function({g, vid2}) { return g.V(vid2).in_() }], 
+    g_VX4X_both: [function({g, vid4}) { return g.V(vid4).both() }], 
+    g_E: [function({g}) { return g.E() }], 
+    g_EX11X: [function({g, eid11}) { return g.E(eid11) }], 
+    g_EX11AsStringX: [function({g, eid11}) { return g.E(eid11) }], 
+    g_EXe11X: [function({g, e11}) { return g.E(e11) }], 
+    g_EXe7_e11X: [function({g, e7, e11}) { return g.E(e7,e11) }], 
+    g_EXlistXe7_e11XX: [function({g, xx1}) { return g.E(xx1) }], 
+    g_EXnullX: [function({g}) { return g.E(null) }], 
+    g_EXlistXnullXX: [function({g, xx1}) { return g.E(xx1) }], 
+    g_EX11_nullX: [function({g, eid11}) { return g.E(eid11,null) }], 
+    g_VX1X_outE: [function({g, vid1}) { return g.V(vid1).outE() }], 
+    g_VX2X_outE: [function({g, vid2}) { return g.V(vid2).inE() }], 
+    g_VX4X_bothEXcreatedX: [function({g, vid4}) { return g.V(vid4).bothE("created") }], 
+    g_VX4X_bothE: [function({g, vid4}) { return g.V(vid4).bothE() }], 
+    g_VX1X_outE_inV: [function({g, vid1}) { return g.V(vid1).both() }], 
+    g_VX2X_inE_outV: [function({g, vid2}) { return g.V(vid2).inE().outV() }], 
+    g_V_outE_hasXweight_1X_outV: [function({g}) { return g.V().outE().has("weight",1.0).outV() }], 
+    g_V_out_outE_inV_inE_inV_both_name: [function({g}) { return g.V().out().outE().inV().inE().inV().both().values("name") }], 
+    g_VX1X_outEXknowsX_bothV_name: [function({g, vid1}) { return g.V(vid1).outE("knows").bothV().values("name") }], 
+    g_VX1X_outE_otherV: [function({g, vid1}) { return g.V(vid1).outE().otherV() }], 
+    g_VX4X_bothE_otherV: [function({g, vid4}) { return g.V(vid4).bothE().otherV() }], 
+    g_VX4X_bothE_hasXweight_lt_1X_otherV: [function({g, vid4}) { return g.V(vid4).bothE().has("weight",P.lt(1.0)).otherV() }], 
+    g_VX2X_inE: [function({g, vid2}) { return g.V(vid2).bothE() }], 
+    get_g_VX1X_outE_otherV: [function({g, vid1}) { return g.V(vid1).outE().otherV() }], 
+    g_VX1X_outXknowsX: [function({g, vid1}) { return g.V(vid1).out("knows") }], 
+    g_VX1AsStringX_outXknowsX: [function({g, vid1}) { return g.V(vid1).out("knows") }], 
+    g_VX1X_outXknows_createdX: [function({g, vid1}) { return g.V(vid1).out("knows","created") }], 
+    g_VX1X_outEXknowsX_inV: [function({g, vid1}) { return g.V(vid1).outE("knows").inV() }], 
+    g_VX1X_outEXknows_createdX_inV: [function({g, vid1}) { return g.V(vid1).outE("knows","created").inV() }], 
+    g_V_out_out: [function({g}) { return g.V().out().out() }], 
+    g_VX1X_out_out_out: [function({g, vid1}) { return g.V(vid1).out().out().out() }], 
+    g_VX1X_out_name: [function({g, vid1}) { return g.V(vid1).out().values("name") }], 
+    g_VX1X_to_XOUT_knowsX: [function({g, vid1}) { return g.V(vid1).to(Direction.OUT,"knows") }], 
+    g_VX1_2_3_4X_name: [function({g, vid4, vid3, vid2, vid1}) { return g.addV("person").property("name","marko").property("age",29).as("marko").addV("person").property("name","vadas").property("age",27).as("vadas").addV("software").property("name","lop").property("lang","java").as("lop").addV("person").property("name","josh").property("age",32).as("josh").addV("software").property("name","ripple").property("lang","java").as("ripple").addV("person").property("name","peter").property("age" [...]
+    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") }], 
+    g_injectX1X_VXnullX: [function({g}) { return g.inject(1).V(null) }], 
+    g_injectX1X_VX1_nullX: [function({g, vid1}) { return g.inject(1).V(vid1,null) }], 
+    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") }], 
+    g_V_out_aggregateXaX_path: [function({g}) { return g.V().out().aggregate("a").path() }], 
+    g_V_hasLabelXpersonX_aggregateXxX_byXageX_capXxX_asXyX_selectXyX: [function({g}) { return g.V().hasLabel("person").aggregate("x").by("age").cap("x").as("y").select("y") }], 
+    g_V_aggregateXxX_byXageX_capXxX: [function({g}) { return g.V().aggregate("x").by("age").cap("x") }], 
+    g_V_aggregateXlocal_xX_byXageX_capXxX: [function({g}) { return g.V().aggregate(Scope.local,"x").by("age").cap("x") }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXlocal_xX_byXageX_capXxX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate(Scope.local,"x").by("age").cap("x") }], 
+    g_V_aggregateXlocal_a_nameX_out_capXaX: [function({g}) { return g.V().aggregate(Scope.local,"a").by("name").out().cap("a") }], 
+    g_VX1X_aggregateXlocal_aX_byXnameX_out_aggregateXlocal_aX_byXnameX_name_capXaX: [function({g, vid1}) { return g.V(vid1).aggregate(Scope.local,"a").by("name").out().aggregate(Scope.local,"a").by("name").values("name").cap("a") }], 
+    g_withSideEffectXa_setX_V_both_name_aggregateXlocal_aX_capXaX: [function({g, xx1}) { return g.withSideEffect("a",xx1).V().both().values("name").aggregate(Scope.local,"a").cap("a") }], 
+    g_V_aggregateXlocal_aX_byXoutEXcreatedX_countX_out_out_aggregateXlocal_aX_byXinEXcreatedX_weight_sumX: [function({g}) { return g.V().aggregate(Scope.local,"a").by(__.outE("created").count()).out().out().aggregate(Scope.local,"a").by(__.inE("created").values("weight").sum()).cap("a") }], 
+    g_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX: [function({g}) { return g.V().aggregate("x").by(__.values("age").is(P.gt(29))).cap("x") }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("x").by(__.values("age").is(P.gt(29))).cap("x") }], 
+    g_V_aggregateXxX_byXout_order_byXnameXX_capXxX: [function({g}) { return g.V().aggregate("x").by(__.out().order().by("name")).cap("x") }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXout_order_byXnameXX_capXxX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("x").by(__.out().order().by("name")).cap("x") }], 
+    g_V_fail: [function({g}) { return g.V().fail() }], 
+    g_V_failXmsgX: [function({g}) { return g.V().fail("msg") }], 
+    g_V_unionXout_failX: [function({g}) { return g.V().union(__.out(),__.fail()) }], 
+    g_V_group_byXnameX: [function({g}) { return g.V().group().by("name") }], 
+    g_V_group_byXageX: [function({g}) { return g.V().group().by("age") }], 
+    g_withStrategiesXProductiveByStrategyX_V_group_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().group().by("age") }], 
+    g_V_group_byXnameX_byXageX: [function({g}) { return g.V().group().by("name").by("age") }], 
+    g_V_group_byXnameX_by: [function({g}) { return g.V().group().by("name").by() }], 
+    g_V_groupXaX_byXnameX_capXaX: [function({g}) { return g.V().group("a").by("name").cap("a") }], 
+    g_V_hasXlangX_groupXaX_byXlangX_byXnameX_out_capXaX: [function({g}) { return g.V().has("lang").group("a").by("lang").by("name").out().cap("a") }], 
+    g_V_hasXlangX_group_byXlangX_byXcountX: [function({g}) { return g.V().has("lang").group().by("lang").by(__.count()) }], 
+    g_V_repeatXout_groupXaX_byXnameX_byXcountX_timesX2X_capXaX: [function({g}) { return g.V().repeat(__.out().group("a").by("name").by(__.count())).times(2).cap("a") }], 
+    g_V_group_byXoutE_countX_byXnameX: [function({g}) { return g.V().order().by("name").group().by(__.outE().count()).by("name") }], 
+    g_V_groupXaX_byXlabelX_byXoutE_weight_sumX_capXaX: [function({g}) { return g.V().group("a").by(T.label).by(__.outE().values("weight").sum()).cap("a") }], 
+    g_V_repeatXbothXfollowedByXX_timesX2X_group_byXsongTypeX_byXcountX: [function({g}) { return g.V().repeat(__.both("followedBy")).times(2).group().by("songType").by(__.count()) }], 
+    g_V_repeatXbothXfollowedByXX_timesX2X_groupXaX_byXsongTypeX_byXcountX_capXaX: [function({g}) { return g.V().repeat(__.both("followedBy")).times(2).group("a").by("songType").by(__.count()).cap("a") }], 
+    g_V_group_byXname_substring_1X_byXconstantX1XX: [function({g, l1}) { return g.V().group().by(l1).by(__.constant(1)) }], 
+    g_V_groupXaX_byXname_substring_1X_byXconstantX1XX_capXaX: [function({g, l1}) { return g.V().group("a").by(l1).by(__.constant(1)).cap("a") }], 
+    g_V_out_group_byXlabelX_selectXpersonX_unfold_outXcreatedX_name_limitX2X: [function({g}) { return g.V().out().group().by(T.label).select("person").unfold().out("created").values("name").limit(2) }], 
+    g_V_hasLabelXsongX_group_byXnameX_byXproperties_groupCount_byXlabelXX: [function({g}) { return g.V().hasLabel("song").group().by("name").by(__.properties().groupCount().by(T.label)) }], 
+    g_V_hasLabelXsongX_groupXaX_byXnameX_byXproperties_groupCount_byXlabelXX_out_capXaX: [function({g}) { return g.V().hasLabel("song").group("a").by("name").by(__.properties().groupCount().by(T.label)).out().cap("a") }], 
+    g_V_outXfollowedByX_group_byXsongTypeX_byXbothE_group_byXlabelX_byXweight_sumXX: [function({g}) { return g.V().out("followedBy").group().by("songType").by(__.bothE().group().by(T.label).by(__.values("weight").sum())) }], 
+    g_V_groupXmX_byXnameX_byXinXknowsX_nameX_capXmX: [function({g}) { return g.V().group("m").by("name").by(__.in_("knows").values("name")).cap("m") }], 
+    g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX: [function({g}) { return g.V().group().by(T.label).by(__.bothE().group("a").by(T.label).by(__.values("weight").sum()).values("weight").sum()) }], 
+    g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX: [function({g, xx1}) { return g.withSideEffect("a",xx1).V().group("a").by("name").by(__.outE().label().fold()).cap("a").unfold().group().by(Column.keys).by(__.select(Column.values).order(Scope.local).by(Order.asc)) }], 
+    g_V_hasLabelXpersonX_asXpX_outXcreatedX_group_byXnameX_byXselectXpX_valuesXageX_sumX: [function({g}) { return g.V().hasLabel("person").as("p").out("created").group().by("name").by(__.select("p").values("age").sum()) }], 
+    g_V_hasLabelXpersonX_asXpX_outXcreatedX_groupXaX_byXnameX_byXselectXpX_valuesXageX_sumX_capXaX: [function({g}) { return g.V().hasLabel("person").as("p").out("created").group("a").by("name").by(__.select("p").values("age").sum()).cap("a") }], 
+    g_V_group_byXlabelX_byXlabel_countX: [function({g}) { return g.V().group().by(__.label()).by(__.label().count()) }], 
+    g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX: [function({g}) { return g.V().group("m").by(__.label()).by(__.label().count()).cap("m") }], 
+    g_V_outXcreatedX_groupCount_byXnameX: [function({g}) { return g.V().out("created").groupCount().by("name") }], 
+    g_V_groupCount_byXageX: [function({g}) { return g.V().groupCount().by("age") }], 
+    g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().groupCount().by("age") }], 
+    g_V_outXcreatedX_name_groupCount: [function({g}) { return g.V().out("created").values("name").groupCount() }], 
+    g_V_outXcreatedX_groupCountXaX_byXnameX_capXaX: [function({g}) { return g.V().out("created").groupCount("a").by("name").cap("a") }], 
+    g_V_outXcreatedX_name_groupCountXaX_capXaX: [function({g}) { return g.V().out("created").values("name").groupCount("a").cap("a") }], 
+    g_V_repeatXout_groupCountXaX_byXnameXX_timesX2X_capXaX: [function({g}) { return g.V().repeat(__.out().groupCount("a").by("name")).times(2).cap("a") }], 
+    g_V_both_groupCountXaX_byXlabelX_asXbX_barrier_whereXselectXaX_selectXsoftwareX_isXgtX2XXX_selectXbX_name: [function({g}) { return g.V().both().groupCount("a").by(T.label).as("b").barrier().where(__.select("a").select("software").is(P.gt(2))).select("b").values("name") }], 
+    g_V_unionXoutXknowsX__outXcreatedX_inXcreatedXX_groupCount_selectXvaluesX_unfold_sum: [function({g}) { return g.V().union(__.out("knows"),__.out("created").in_("created")).groupCount().select(Column.values).unfold().sum() }], 
+    g_V_hasXnoX_groupCount: [function({g}) { return g.V().has("no").groupCount() }], 
+    g_V_hasXnoX_groupCountXaX_capXaX: [function({g}) { return g.V().has("no").groupCount("a").cap("a") }], 
+    g_V_unionXrepeatXoutX_timesX2X_groupCountXmX_byXlangXX__repeatXinX_timesX2X_groupCountXmX_byXnameXX_capXmX: [function({g}) { return g.V().union(__.repeat(__.out()).times(2).groupCount("m").by("lang"),__.repeat(__.in_()).times(2).groupCount("m").by("name")).cap("m") }], 
+    g_V_outXcreatedX_groupCountXxX_capXxX: [function({g}) { return g.V().out("created").groupCount("x").cap("x") }], 
+    g_V_groupCount_byXbothE_countX: [function({g}) { return g.V().groupCount().by(__.bothE().count()) }], 
+    g_V_both_groupCountXaX_out_capXaX_selectXkeysX_unfold_both_groupCountXaX_capXaX: [function({g}) { return g.V().both().groupCount("a").out().cap("a").select(Column.keys).unfold().both().groupCount("a").cap("a") }], 
+    g_V_hasXperson_name_markoX_bothXknowsX_groupCount_byXvaluesXnameX_foldX: [function({g}) { return g.V().has("person","name","marko").both("knows").groupCount().by(__.values("name").fold()) }], 
+    g_VX1X_out_injectXv2X_name: [function({g, vid1, v2}) { return g.V(vid1).out().inject(v2).values("name") }], 
+    g_VX1X_out_name_injectXdanielX_asXaX_mapXlengthX_path: [function({g, l1, vid1}) { return g.V(vid1).out().values("name").inject("daniel").as("a").map(l1).path() }], 
+    g_VX1X_injectXg_VX4XX_out_name: [function({g, vid1, v4}) { return g.V(vid1).inject(v4).out().values("name") }], 
+    g_injectXnull_1_3_nullX: [function({g}) { return g.inject(null,1,3,null) }], 
+    g_injectX10_20_null_20_10_10X_groupCountXxX_dedup_asXyX_projectXa_bX_by_byXselectXxX_selectXselectXyXXX: [function({g}) { return g.inject(10,20,null,20,10,10).groupCount("x").dedup().as("y").project("a","b").by().by(__.select("x").select(__.select("y"))) }], 
+    g_injectXname_marko_age_nullX_selectXname_ageX: [function({g, xx1}) { return g.inject(xx1).select("name","age") }], 
+    g_injectXnull_nullX: [function({g}) { return g.inject(null,null) }], 
+    g_injectXnullX: [function({g}) { return g.inject(null) }], 
+    g_inject: [function({g}) { return g.inject() }], 
+    g_VX1X_valuesXageX_injectXnull_nullX: [function({g, xx1}) { return g.V(xx1).values("age").inject(null,null) }], 
+    g_VX1X_valuesXageX_injectXnullX: [function({g, xx1}) { return g.V(xx1).values("age").inject(null) }], 
+    g_VX1X_valuesXageX_inject: [function({g, xx1}) { return g.V(xx1).values("age").inject() }], 
+    g_injectXnull_1_3_nullX_asXaX_selectXaX: [function({g}) { return g.inject(null,1,3,null).as("a").select("a") }], 
+    g_io_readXkryoX: [function({g}) { return g.io("data/tinkerpop-modern.kryo").read() }, function({g}) { return g.V() }, function({g}) { return g.E() }], 
+    g_io_read_withXreader_gryoX: [function({g}) { return g.io("data/tinkerpop-modern.kryo").with_("~tinkerpop.io.reader","gryo").read() }, function({g}) { return g.V() }, function({g}) { return g.E() }], 
+    g_io_readXgraphsonX: [function({g}) { return g.io("data/tinkerpop-modern.json").read() }, function({g}) { return g.V() }, function({g}) { return g.E() }], 
+    g_io_read_withXreader_graphsonX: [function({g}) { return g.io("data/tinkerpop-modern.json").with_("~tinkerpop.io.reader","graphson").read() }, function({g}) { return g.V() }, function({g}) { return g.E() }], 
+    g_io_readXgraphmlX: [function({g}) { return g.io("data/tinkerpop-modern.xml").read() }, function({g}) { return g.V() }, function({g}) { return g.E() }], 
+    g_io_read_withXreader_graphmlX: [function({g}) { return g.io("data/tinkerpop-modern.xml").with_("~tinkerpop.io.reader","graphml").read() }, function({g}) { return g.V() }, function({g}) { return g.E() }], 
+    g_withSackXhelloX_V_outE_sackXassignX_byXlabelX_inV_sack: [function({g}) { return g.withSack("hello").V().outE().sack(Operator.assign).by(T.label).inV().sack() }], 
+    g_withSackX0X_V_outE_sackXsumX_byXweightX_inV_sack_sum: [function({g}) { return g.withSack(0.0).V().outE().sack(Operator.sum).by("weight").inV().sack().sum() }], 
+    g_withSackX0X_V_repeatXoutE_sackXsumX_byXweightX_inVX_timesX2X_sack: [function({g}) { return g.withSack(0.0).V().repeat(__.outE().sack(Operator.sum).by("weight").inV()).times(2).sack() }], 
+    g_withBulkXfalseX_withSackX1_sumX_VX1X_localXoutEXknowsX_barrierXnormSackX_inVX_inXknowsX_barrier_sack: [function({g, vid1}) { return g.withBulk(false).withSack(1.0,Operator.sum).V(vid1).local(__.outE("knows").barrier(Barrier.normSack).inV()).in_("knows").barrier().sack() }], 
+    g_withBulkXfalseX_withSackX1_sumX_V_out_barrier_sack: [function({g}) { return g.withBulk(false).withSack(1,Operator.sum).V().out().barrier().sack() }], 
+    g_withSackX1_sumX_VX1X_localXoutXknowsX_barrierXnormSackXX_inXknowsX_barrier_sack: [function({g, vid1}) { return g.withSack(1.0,Operator.sum).V(vid1).local(__.out("knows").barrier(Barrier.normSack)).in_("knows").barrier().sack() }], 
+    g_V_sackXassignX_byXageX_sack: [function({g}) { return g.V().sack(Operator.assign).by("age").sack() }], 
+    g_V_hasXageX_groupCountXaX_byXnameX_out_capXaX: [function({g}) { return g.V().has("age").groupCount("a").by("name").out().cap("a") }], 
+    g_V_storeXa_nameX_out_capXaX: [function({g}) { return g.V().store("a").by("name").out().cap("a") }], 
+    g_VX1X_storeXaX_byXnameX_out_storeXaX_byXnameX_name_capXaX: [function({g, vid1}) { return g.V(vid1).store("a").by("name").out().store("a").by("name").values("name").cap("a") }], 
+    g_withSideEffectXa_setX_V_both_name_storeXaX_capXaX: [function({g, xx1}) { return g.withSideEffect("a",xx1).V().both().values("name").store("a").cap("a") }], 
+    g_V_storeXaX_byXoutEXcreatedX_countX_out_out_storeXaX_byXinEXcreatedX_weight_sumX: [function({g}) { return g.V().store("a").by(__.outE("created").count()).out().out().store("a").by(__.inE("created").values("weight").sum()).cap("a") }], 
+}
+
+exports.gremlin = gremlins
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4
index 9021c36..1462fb5 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -136,8 +136,8 @@ traversalSourceSpawnMethod_mergeV
     ;
 
 traversalSourceSpawnMethod_mergeE
-    : 'mergeE' LPAREN genericLiteralMap RPAREN
-    | 'mergeE' LPAREN nestedTraversal RPAREN
+    : 'mergeE' LPAREN genericLiteralMap RPAREN #traversalSourceSpawnMethod_mergeE_Map
+    | 'mergeE' LPAREN nestedTraversal RPAREN #traversalSourceSpawnMethod_mergeE_Traversal
     ;
 
 chainedTraversal
@@ -1340,6 +1340,7 @@ genericLiteral
 	| traversalCardinality
 	| traversalDirection
 	| traversalOptionParent
+	| structureVertex
 	| genericLiteralCollection
 	| genericLiteralRange
 	| nestedTraversal
diff --git a/gremlin-language/src/main/java/org/apache/tinkerpop/gremlin/language/corpus/DocumentationReader.java b/gremlin-language/src/main/java/org/apache/tinkerpop/gremlin/language/corpus/DocumentationReader.java
index ba7c749..6c091e5 100644
--- a/gremlin-language/src/main/java/org/apache/tinkerpop/gremlin/language/corpus/DocumentationReader.java
+++ b/gremlin-language/src/main/java/org/apache/tinkerpop/gremlin/language/corpus/DocumentationReader.java
@@ -105,6 +105,8 @@ public class DocumentationReader {
                 replace("vMarko", "\"marko\"").
                 replace("vPeter", "\"peter\"").
                 replace("vStephen", "\"stephen\"").
+                replace("v1", "new Vertex(1,\"vertex\")").
+                replace("v2", "new Vertex(2,\"vertex\")").
                 replace("input.head()", "\"head\"").
                 replace("input.tail().size()", "6").
                 replace("input.tail()", "\"tail\"").
diff --git a/gremlin-language/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ReferenceGrammarTest.java b/gremlin-language/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ReferenceGrammarTest.java
index 46e0467..730291a 100644
--- a/gremlin-language/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ReferenceGrammarTest.java
+++ b/gremlin-language/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ReferenceGrammarTest.java
@@ -49,10 +49,20 @@ public class ReferenceGrammarTest extends AbstractGrammarTest {
     private static final String featureDir = Paths.get("..", "gremlin-test", "features").toString();
     private static final String docsDir = Paths.get("..", "docs", "src").toString();
 
-    private static final Pattern vertexPattern = Pattern.compile(".*v\\d.*");
     private static final Pattern edgePattern = Pattern.compile(".*e\\d.*");
 
     private static final List<Pair<Pattern, BiFunction<String,String,String>>> stringMatcherConverters = new ArrayList<Pair<Pattern, BiFunction<String,String,String>>>() {{
+        add(Pair.with(Pattern.compile("m\\[(.*)\\]"), (k,v) -> {
+            // can't handled embedded maps because of the string replace below on the curly braces
+            final String[] items = v.replace("{", "").replace("}", "").split(",");
+            final String listItems = Stream.of(items).map(String::trim).map(x -> {
+                final String[] pair = x.split(":");
+                final String convertedKey = String.format("%s", pair[0]);
+                final String convertedValue = String.format("%s", pair[1]);
+                return String.format("%s:%s", convertedKey, convertedValue);
+            }).collect(Collectors.joining(","));
+            return String.format("[%s]", listItems);
+        }));
         add(Pair.with(Pattern.compile("l\\[\\]"), (k,v) -> "[]"));
         add(Pair.with(Pattern.compile("l\\[(.*)\\]"), (k,v) -> {
             final String[] items = v.split(",");
@@ -60,6 +70,7 @@ public class ReferenceGrammarTest extends AbstractGrammarTest {
             return String.format("[%s]", listItems);
         }));
         add(Pair.with(Pattern.compile("v\\[(.+)\\]"), (k,v) -> "\"1\""));
+        add(Pair.with(Pattern.compile("v(\\d)"), (k,v) -> String.format("new Vertex(%s)", v)));
         add(Pair.with(Pattern.compile("e\\[(.+)\\]"), (k,v) -> "\"1\""));
         add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.?.*"), (k,v) -> v));
         add(Pair.with(Pattern.compile("m\\[(.*)\\]"), (k,v) -> v.replace('{','[').replace('}', ']')));
@@ -85,11 +96,12 @@ public class ReferenceGrammarTest extends AbstractGrammarTest {
 
     @Test
     public void test_parse() {
+        // can't handle maps with complex embedded types at the moment - basically one Gremlin statement at this point
+        assumeThat("Complex embedded types are not supported", query.contains("l[\"666\"]"), is(false));
         assumeThat("Lambdas are not supported", query.contains("Lambda.function("), is(false));
         // start of a closure
         assumeThat("Lambdas are not supported", query.contains("{"), is(false));
         assumeThat("withComputer() step is not supported", query.startsWith("g.withComputer("), is(false));
-        assumeThat("Vertex instances are not supported", vertexPattern.matcher(query).matches(), is(false));
         assumeThat("Edge instances are not supported", edgePattern.matcher(query).matches(), is(false));
         assumeThat("fill() terminator is not supported", query.contains("fill("), is(false));
         assumeThat("withoutStrategies() is not supported", query.contains("withoutStrategies("), is(false));
diff --git a/gremlin-python/build/generate.groovy b/gremlin-python/build/generate.groovy
index f0a3d45..a633cd7 100644
--- a/gremlin-python/build/generate.groovy
+++ b/gremlin-python/build/generate.groovy
@@ -31,6 +31,16 @@ import java.nio.file.Paths
 
 import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal
 
+// getting an exception like:
+// > InvocationTargetException: javax.script.ScriptException: groovy.lang.MissingMethodException: No signature of
+// > method: org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal.mergeE() is applicable for
+// > argument types: (String) values: [4ffdea36-4a0e-4681-acba-e76875d1b25b]
+// usually means bindings are not being extracted properly by VarAsBindingASTTransformation which typically happens
+// when a step is taking an argument that cannot properly resolve to the type required by the step itself. there are
+// special cases in that VarAsBindingASTTransformation class which might need to be adjusted. Editing the
+// GremlinGroovyScriptEngineTest#shouldProduceBindingsForVars() with the failing step and argument can typically make
+// this issue relatively easy to debug and enforce.
+
 // file is overwritten on each generation
 radishGremlinFile = new File("${projectBaseDir}/gremlin-python/src/main/python/radish/gremlin.py")
 
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 850ee7e..bcfde18 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -471,6 +471,30 @@ world.gremlins = {
     'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_mean': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').unfold().mean())], 
     'g_injectXnull_10_20_nullX_mean': [(lambda g, xx1=None,xx2=None:g.inject(None,xx1,xx2,None).mean())], 
     'g_injectXlistXnull_10_20_nullXX_meanXlocalX': [(lambda g, xx1=None:g.inject(xx1).mean(Scope.local))], 
+    'g_V_mergeEXlabel_self_weight_05X': [(lambda g, xx1=None:g.addV('person').property('name','marko').property('age',29)), (lambda g, xx1=None:g.V().mergeE(xx1)), (lambda g, xx1=None:g.E().hasLabel('self').has('weight',float(0.5)))], 
+    'g_mergeEXlabel_knows_out_marko_in_vadasX': [(lambda g, xx1=None:g.addV('person').property(T.id_,100).property('name','marko').addV('person').property(T.id_,101).property('name','vadas')), (lambda g, xx1=None:g.mergeE(xx1)), (lambda g, xx1=None:g.V().has('person','name','marko').out('knows').has('person','name','vadas'))], 
+    'g_mergeEXlabel_knows_out_marko_in_vadas_weight_05X_exists': [(lambda g, xx1=None:g.addV('person').property(T.id_,100).property('name','marko').as_('a').addV('person').property(T.id_,101).property('name','vadas').as_('b').addE('knows').from_('a').to('b')), (lambda g, xx1=None:g.mergeE(xx1)), (lambda g, xx1=None:g.V().has('person','name','marko').outE('knows').has('weight',float(0.5)).inV().has('person','name','vadas')), (lambda g, xx1=None:g.V().has('person','name','marko').outE('kno [...]
+    'g_mergeEXlabel_knows_out_marko_in_vadas_weight_05X': [(lambda g, xx1=None:g.mergeE(xx1)), (lambda g, xx1=None:g.V()), (lambda g, xx1=None:g.E().hasLabel('knows').has('weight',float(0.5)))], 
+    'g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX': [(lambda g, xx1=None,xx3=None,xx2=None:g.mergeE(xx1).option(Merge.onCreate,xx2).option(Merge.onMatch,xx3)), (lambda g, xx1=None,xx3=None,xx2=None:g.V()), (lambda g, xx1=None,xx3=None,xx2=None:g.E().hasLabel('knows').has('created','Y')), (lambda g, xx1=None,xx3=None,xx2=None:g.E().hasLabel('knows').has('created','N'))], 
+    'g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists': [(lambda g, xx1=None,xx3=None,xx2=None:g.addV('person').property(T.id_,100).property('name','marko').as_('a').addV('person').property(T.id_,101).property('name','vadas').as_('b').addE('knows').from_('a').to('b')), (lambda g, xx1=None,xx3=None,xx2=None:g.mergeE(xx1).option(Merge.onCreate,xx2).option(Merge.onMatch,xx3)), (lambda g, xx1=None,xx3=None,xx2=None:g.V()), (lambda g, xx1=No [...]
+    'g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated': [(lambda g, xx1=None,xx3=None,xx2=None:g.addV('person').property(T.id_,100).property('name','marko').as_('a').addV('person').property(T.id_,101).property('name','vadas').as_('b').addE('knows').from_('a').to('b').property('created','Y')), (lambda g, xx1=None,xx3=None,xx2=None:g.mergeE(xx1).option(Merge.onCreate,xx2).option(Merge.onMatch,xx3)), (lambda g, xx1=None,xx3=None,xx [...]
+    'g_V_hasXperson_name_marko_X_mergeEXlabel_knowsX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated': [(lambda g, xx1=None,xx3=None,xx2=None:g.addV('person').property(T.id_,100).property('name','marko').as_('a').addV('person').property(T.id_,101).property('name','vadas').as_('b').addE('knows').from_('a').to('b').property('created','Y').addE('knows').from_('a').to('b')), (lambda g, xx1=None,xx3=None,xx2=None:g.V().has('person','name','marko').mergeE(xx1).option(Merge. [...]
+    'g_VX100X_VX101X_mergeEXlabel_knows_out_marko_in_vadasX': [(lambda g, xx1=None:g.addV('person').property(T.id_,100).property('name','marko')), (lambda g, xx1=None:g.V(100).V(101).mergeE(xx1)), (lambda g, xx1=None:g.V()), (lambda g, xx1=None:g.E())], 
+    'g_mergeVXlabel_person_name_stephenX': [(lambda g, xx1=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None:g.mergeV(xx1)), (lambda g, xx1=None:g.V().has('person','name','stephen'))], 
+    'g_mergeVXlabel_person_name_markoX': [(lambda g, xx1=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None:g.mergeV(xx1)), (lambda g, xx1=None:g.V().has('person','name','marko'))], 
+    'g_mergeVXlabel_person_name_stephenX_optionXonCreate_label_person_name_stephen_age_19X_option': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.mergeV(xx1).option(Merge.onCreate,xx2)), (lambda g, xx1=None,xx2=None:g.V().has('person','name','stephen').has('age',19))], 
+    'g_mergeVXlabel_person_name_markoX_optionXonMatch_age_19X_option': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.mergeV(xx1).option(Merge.onMatch,xx2)), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko').has('age',19))], 
+    'g_withSideEffectXc_label_person_name_stephenX_withSideEffectXm_label_person_name_stephen_age_19X_mergeVXselectXcXX_optionXonCreate_selectXmXX_option': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.withSideEffect('c',xx1).withSideEffect('m',xx2).mergeV(__.select('c')).option(Merge.onCreate,__.select('m'))), (lambda g, xx1=None,xx2=None:g.V().has('person','name','stephen').has('age',19))], 
+    'g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_mergeVXselectXcXX_optionXonMatch_selectXmXX_option': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.withSideEffect('c',xx1).withSideEffect('m',xx2).mergeV(__.select('c')).option(Merge.onMatch,__.select('m'))), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko').has('age',19))], 
+    'g_mergeVXlabel_person_name_markoX_propertyXname_vadas_acl_publicX': [(lambda g, xx1=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None:g.mergeV(xx1).property('name','vadas','acl','public')), (lambda g, xx1=None:g.V().properties('name').hasValue('vadas').has('acl','public'))], 
+    'g_injectX0X_mergeVXlabel_person_name_stephenX': [(lambda g, xx1=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None:g.inject(0).mergeV(xx1)), (lambda g, xx1=None:g.V().has('person','name','stephen'))], 
+    'g_injectX0X_mergeVXlabel_person_name_markoX': [(lambda g, xx1=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None:g.inject(0).mergeV(xx1)), (lambda g, xx1=None:g.V().has('person','name','marko'))], 
+    'g_injectX0X_mergeVXlabel_person_name_stephenX_optionXonCreate_label_person_name_stephen_age_19X_option': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.inject(0).mergeV(xx1).option(Merge.onCreate,xx2)), (lambda g, xx1=None,xx2=None:g.V().has('person','name','stephen').has('age',19))], 
+    'g_injectX0X_mergeVXlabel_person_name_markoX_optionXonMatch_age_19X_option': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.inject(0).mergeV(xx1).option(Merge.onMatch,xx2)), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko').has('age',19))], 
+    'g_withSideEffectXc_label_person_name_stephenX_withSideEffectXm_label_person_name_stephen_age_19X_injectX0X_mergeVXselectXcXX_optionXonCreate_selectXmXX_option': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.withSideEffect('c',xx1).withSideEffect('m',xx2).inject(0).mergeV(__.select('c')).option(Merge.onCreate,__.select('m'))), (lambda g, xx1=None,xx2=None:g.V().has('person','name','stephen').ha [...]
+    'g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_injectX0X_mergeVXselectXcXX_optionXonMatch_selectXmXX_option': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.withSideEffect('c',xx1).withSideEffect('m',xx2).inject(0).mergeV(__.select('c')).option(Merge.onMatch,__.select('m'))), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko').has('age',19))], 
+    'g_injectX0X_mergeVXlabel_person_name_markoX_propertyXname_vadas_acl_publicX': [(lambda g, xx1=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None:g.inject(0).mergeV(xx1).property('name','vadas','acl','public')), (lambda g, xx1=None:g.V().properties('name').hasValue('vadas').has('acl','public'))], 
+    'g_injectXlabel_person_name_marko_label_person_name_stephenX_mergeVXidentityX': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.inject(xx1,xx2).mergeV(__.identity())), (lambda g, xx1=None,xx2=None:g.V().has('person','name','stephen')), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko')), (lambda g, xx1=None,xx2=None:g.V())], 
     'g_V_age_min': [(lambda g:g.V().age.min_())], 
     'g_V_foo_min': [(lambda g:g.V().foo.min_())], 
     'g_V_name_min': [(lambda g:g.V().name.min_())], 
diff --git a/gremlin-test/features/map/MergeEdge.feature b/gremlin-test/features/map/MergeEdge.feature
new file mode 100644
index 0000000..65173ce
--- /dev/null
+++ b/gremlin-test/features/map/MergeEdge.feature
@@ -0,0 +1,184 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+@StepClassMap @StepMergeE
+Feature: Step - mergeE()
+
+  Scenario: g_V_mergeEXlabel_self_weight_05X
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property("name", "marko").property("age", 29)
+      """
+    And using the parameter xx1 defined as "m[{\"t[label]\": \"self\", \"weight\":\"d[0.5].d\"}]"
+    And the traversal of
+      """
+      g.V().mergeE(xx1)
+      """
+    When iterated to list
+    Then the result should have a count of 1
+    And the graph should return 1 for count of "g.E().hasLabel(\"self\").has(\"weight\",0.5)"
+
+  @AllowUserSuppliedIds
+  Scenario: g_mergeEXlabel_knows_out_marko_in_vadasX
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property(T.id, 100).property("name", "marko").
+        addV("person").property(T.id, 101).property("name", "vadas")
+      """
+    And using the parameter xx1 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[100]\", \"D[IN]\":\"v[101]\"}]"
+    And the traversal of
+      """
+      g.mergeE(xx1)
+      """
+    When iterated to list
+    Then the result should have a count of 1
+    And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"marko\").out(\"knows\").has(\"person\",\"name\",\"vadas\")"
+
+  @AllowUserSuppliedIds
+  Scenario: g_mergeEXlabel_knows_out_marko_in_vadas_weight_05X_exists
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property(T.id, 100).property("name", "marko").as("a").
+        addV("person").property(T.id, 101).property("name", "vadas").as("b").
+        addE("knows").from("a").to("b")
+      """
+    And using the parameter xx1 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[100]\", \"D[IN]\":\"v[101]\", \"weight\":\"d[0.5].d\"}]"
+    And the traversal of
+      """
+      g.mergeE(xx1)
+      """
+    When iterated to list
+    Then the result should have a count of 1
+    And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"marko\").outE(\"knows\").has(\"weight\",0.5).inV().has(\"person\",\"name\",\"vadas\")"
+    And the graph should return 2 for count of "g.V().has(\"person\",\"name\",\"marko\").outE(\"knows\").inV().has(\"person\",\"name\",\"vadas\")"
+
+  @AllowUserSuppliedIds
+  Scenario: g_mergeEXlabel_knows_out_marko_in_vadas_weight_05X
+    Given the empty graph
+    And using the parameter xx1 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[100]\", \"D[IN]\":\"v[101]\", \"weight\":\"d[0.5].d\"}]"
+    And the traversal of
+      """
+      g.mergeE(xx1)
+      """
+    When iterated to list
+    Then the result should have a count of 1
+    And the graph should return 2 for count of "g.V()"
+    And the graph should return 1 for count of "g.E().hasLabel(\"knows\").has(\"weight\",0.5)"
+
+  @AllowUserSuppliedIds
+  Scenario: g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX
+    Given the empty graph
+    And using the parameter xx1 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[100]\", \"D[IN]\":\"v[101]\"}]"
+    And using the parameter xx2 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[100]\", \"D[IN]\":\"v[101]\", \"created\":\"Y\"}]"
+    And using the parameter xx3 defined as "m[{\"t[label]\": \"knows\", \"created\":\"N\"}]"
+    And the traversal of
+      """
+      g.mergeE(xx1).option(Merge.onCreate,xx2).option(Merge.onMatch,xx3)
+      """
+    When iterated to list
+    Then the result should have a count of 1
+    And the graph should return 2 for count of "g.V()"
+    And the graph should return 1 for count of "g.E().hasLabel(\"knows\").has(\"created\",\"Y\")"
+    And the graph should return 0 for count of "g.E().hasLabel(\"knows\").has(\"created\",\"N\")"
+
+  @AllowUserSuppliedIds
+  Scenario: g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property(T.id, 100).property("name", "marko").as("a").
+        addV("person").property(T.id, 101).property("name", "vadas").as("b").
+        addE("knows").from("a").to("b")
+      """
+    And using the parameter xx1 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[100]\", \"D[IN]\":\"v[101]\"}]"
+    And using the parameter xx2 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[100]\", \"D[IN]\":\"v[101]\",\"created\":\"Y\"}]"
+    And using the parameter xx3 defined as "m[{\"created\":\"N\"}]"
+    And the traversal of
+      """
+      g.mergeE(xx1).option(Merge.onCreate,xx2).option(Merge.onMatch,xx3)
+      """
+    When iterated to list
+    Then the result should have a count of 1
+    And the graph should return 2 for count of "g.V()"
+    And the graph should return 0 for count of "g.E().hasLabel(\"knows\").has(\"created\",\"Y\")"
+    And the graph should return 1 for count of "g.E().hasLabel(\"knows\").has(\"created\",\"N\")"
+
+  @AllowUserSuppliedIds
+  Scenario: g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property(T.id, 100).property("name", "marko").as("a").
+        addV("person").property(T.id, 101).property("name", "vadas").as("b").
+        addE("knows").from("a").to("b").property("created","Y")
+      """
+    And using the parameter xx1 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[100]\", \"D[IN]\":\"v[101]\"}]"
+    And using the parameter xx2 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[100]\", \"D[IN]\":\"v[101]\",\"created\":\"Y\"}]"
+    And using the parameter xx3 defined as "m[{\"created\":\"N\"}]"
+    And the traversal of
+      """
+      g.mergeE(xx1).option(Merge.onCreate,xx2).option(Merge.onMatch,xx3)
+      """
+    When iterated to list
+    Then the result should have a count of 1
+    And the graph should return 2 for count of "g.V()"
+    And the graph should return 0 for count of "g.E().hasLabel(\"knows\").has(\"created\",\"Y\")"
+    And the graph should return 1 for count of "g.E().hasLabel(\"knows\").has(\"created\",\"N\")"
+
+  @AllowUserSuppliedIds
+  Scenario: g_V_hasXperson_name_marko_X_mergeEXlabel_knowsX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property(T.id, 100).property("name", "marko").as("a").
+        addV("person").property(T.id, 101).property("name", "vadas").as("b").
+        addE("knows").from("a").to("b").property("created","Y").
+        addE("knows").from("a").to("b")
+      """
+    And using the parameter xx1 defined as "m[{\"t[label]\": \"knows\"}]"
+    And using the parameter xx2 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[100]\", \"D[IN]\":\"v[101]\",\"created\":\"Y\"}]"
+    And using the parameter xx3 defined as "m[{\"created\":\"N\"}]"
+    And the traversal of
+      """
+      g.V().has("person","name","marko").mergeE(xx1).option(Merge.onCreate,xx2).option(Merge.onMatch,xx3)
+      """
+    When iterated to list
+    Then the result should have a count of 2
+    And the graph should return 2 for count of "g.V()"
+    And the graph should return 2 for count of "g.E()"
+    And the graph should return 0 for count of "g.E().hasLabel(\"knows\").has(\"created\",\"Y\")"
+    And the graph should return 2 for count of "g.E().hasLabel(\"knows\").has(\"created\",\"N\")"
+
+  @AllowUserSuppliedIds
+  Scenario: g_VX100X_VX101X_mergeEXlabel_knows_out_marko_in_vadasX
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property(T.id, 100).property("name", "marko")
+      """
+    And using the parameter xx1 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[100]\", \"D[IN]\":\"v[101]\"}]"
+    And the traversal of
+      """
+      g.V(100).V(101).mergeE(xx1)
+      """
+    When iterated to list
+    Then the result should have a count of 0
+    And the graph should return 1 for count of "g.V()"
+    And the graph should return 0 for count of "g.E()"
\ No newline at end of file
diff --git a/gremlin-test/features/map/MergeVertex.feature b/gremlin-test/features/map/MergeVertex.feature
index 1f8ae9d..385f2f8 100644
--- a/gremlin-test/features/map/MergeVertex.feature
+++ b/gremlin-test/features/map/MergeVertex.feature
@@ -55,7 +55,7 @@ Feature: Step - mergeV()
       g.addV("person").property("name", "marko").property("age", 29).as("marko")
       """
     And using the parameter xx1 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\"}]"
-    And using the parameter xx2 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\", \"age\": 19}]"
+    And using the parameter xx2 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\", \"age\": \"d[19].i\"}]"
     And the traversal of
       """
       g.mergeV(xx1).option(Merge.onCreate,xx2)
@@ -71,7 +71,7 @@ Feature: Step - mergeV()
       g.addV("person").property("name", "marko").property("age", 29).as("marko")
       """
     And using the parameter xx1 defined as "m[{\"t[label]\": \"person\", \"name\":\"marko\"}]"
-    And using the parameter xx2 defined as "m[{\"age\": 19}]"
+    And using the parameter xx2 defined as "m[{\"age\": \"d[19].i\"}]"
     And the traversal of
       """
       g.mergeV(xx1).option(Merge.onMatch,xx2)
@@ -87,7 +87,7 @@ Feature: Step - mergeV()
       g.addV("person").property("name", "marko").property("age", 29).as("marko")
       """
     And using the parameter xx1 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\"}]"
-    And using the parameter xx2 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\", \"age\": 19}]"
+    And using the parameter xx2 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\", \"age\": \"d[19].i\"}]"
     And the traversal of
       """
       g.withSideEffect("c", xx1).
@@ -105,7 +105,7 @@ Feature: Step - mergeV()
       g.addV("person").property("name", "marko").property("age", 29).as("marko")
       """
     And using the parameter xx1 defined as "m[{\"t[label]\": \"person\", \"name\":\"marko\"}]"
-    And using the parameter xx2 defined as "m[{\"age\": 19}]"
+    And using the parameter xx2 defined as "m[{\"age\": \"d[19].i\"}]"
     And the traversal of
       """
       g.withSideEffect("c", xx1).
@@ -169,7 +169,7 @@ Feature: Step - mergeV()
       g.addV("person").property("name", "marko").property("age", 29).as("marko")
       """
     And using the parameter xx1 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\"}]"
-    And using the parameter xx2 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\", \"age\": 19}]"
+    And using the parameter xx2 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\", \"age\": \"d[19].i\"}]"
     And the traversal of
       """
       g.inject(0).mergeV(xx1).option(Merge.onCreate,xx2)
@@ -185,7 +185,7 @@ Feature: Step - mergeV()
       g.addV("person").property("name", "marko").property("age", 29).as("marko")
       """
     And using the parameter xx1 defined as "m[{\"t[label]\": \"person\", \"name\":\"marko\"}]"
-    And using the parameter xx2 defined as "m[{\"age\": 19}]"
+    And using the parameter xx2 defined as "m[{\"age\": \"d[19].i\"}]"
     And the traversal of
       """
       g.inject(0).mergeV(xx1).option(Merge.onMatch,xx2)
@@ -201,7 +201,7 @@ Feature: Step - mergeV()
       g.addV("person").property("name", "marko").property("age", 29).as("marko")
       """
     And using the parameter xx1 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\"}]"
-    And using the parameter xx2 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\", \"age\": 19}]"
+    And using the parameter xx2 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\", \"age\": \"d[19].i\"}]"
     And the traversal of
       """
       g.withSideEffect("c", xx1).
@@ -219,7 +219,7 @@ Feature: Step - mergeV()
       g.addV("person").property("name", "marko").property("age", 29).as("marko")
       """
     And using the parameter xx1 defined as "m[{\"t[label]\": \"person\", \"name\":\"marko\"}]"
-    And using the parameter xx2 defined as "m[{\"age\": 19}]"
+    And using the parameter xx2 defined as "m[{\"age\": \"d[19].i\"}]"
     And the traversal of
       """
       g.withSideEffect("c", xx1).
diff --git a/gremlin-test/features/sideEffect/Group.feature b/gremlin-test/features/sideEffect/Group.feature
index d4d3867..b8e7b5c 100644
--- a/gremlin-test/features/sideEffect/Group.feature
+++ b/gremlin-test/features/sideEffect/Group.feature
@@ -266,7 +266,7 @@ Feature: Step - group()
   # The post-ordering really isn't really right but works around TINKERPOP-2600
   Scenario: g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX
     Given the modern graph
-    And using the parameter xx1 defined as "m[{\"marko\":[\"666\"], \"noone\":[\"blah\"]}]"
+    And using the parameter xx1 defined as "m[{\"marko\":l[\"666\"], \"noone\":l[\"blah\"]}]"
     And the traversal of
       """
       g.withSideEffect("a", xx1).V().group("a").by("name").by(__.outE().label().fold()).cap("a").unfold().group().by(keys).by(select(values).order(Scope.local).by(Order.asc))
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 340d984..4789fd0 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
@@ -38,6 +38,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSo
 import org.apache.tinkerpop.gremlin.structure.Direction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.apache.tinkerpop.shaded.jackson.databind.JsonNode;
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
@@ -62,10 +63,12 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.function.Function;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -86,13 +89,21 @@ public final class StepDefinition {
     private static final Pattern edgeTripletPattern = Pattern.compile("(.+)-(.+)->(.+)");
     private static final Pattern ioPattern = Pattern.compile("g\\.io\\(\"(.*)\"\\).*");
     private List<Pair<Pattern, Function<String,String>>> stringMatcherConverters = new ArrayList<Pair<Pattern, Function<String,String>>>() {{
-        // expects json so that should port to the Gremlin script form - replace curly json braces with square ones
-        // for Gremlin sake. allow for support of T as keys in maps, though this is starting to get a big ugly.
-        add(Pair.with(Pattern.compile("m\\[(.*)\\]"), s ->
-                s.replace("\"t[label]\"", "T.label").
-                        replace("\"t[id]\"", "T.id").
-                        replace('{','[').replace('}', ']')));
-
+        // expects json so that should port to the Gremlin script form
+        add(Pair.with(Pattern.compile("m\\[(.*)\\]"), s -> {
+            // can't handled embedded maps because of the string replace below on the curly braces
+            final String[] items = s.replace("{", "").replace("}", "").split(",");
+            final String listItems = Stream.of(items).map(String::trim).map(x -> {
+                final String[] pair = x.split(":");
+
+                // if wrapping double quotes aren't removed they end up re-wrapping again for pure string values
+                // on conversion
+                final String convertedKey = convertToString(pair[0].trim().replace("\"", ""));
+                final String convertedValue = convertToString(pair[1].trim().replace("\"", ""));
+                return String.format("%s:%s", convertedKey, convertedValue);
+            }).collect(Collectors.joining(","));
+            return String.format("[%s]", listItems);
+        }));
         add(Pair.with(Pattern.compile("l\\[\\]"), s -> "[]"));
         add(Pair.with(Pattern.compile("l\\[(.*)\\]"), s -> {
             final String[] items = s.split(",");
@@ -110,9 +121,12 @@ public final class StepDefinition {
 
         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()));
+        add(Pair.with(Pattern.compile("v\\[(.+)\\]"), s -> {
+            final Iterator<Object> itty = g.V().has("name", s).id();
+            return String.format("new Vertex(\"%s\",\"%s\")", itty.hasNext() ? itty.next() : s, Vertex.DEFAULT_LABEL);
+        }));
         add(Pair.with(Pattern.compile("e\\[(.+)\\]\\.id"), s -> getEdgeIdString(g, s)));
         add(Pair.with(Pattern.compile("e\\[(.+)\\]\\.sid"), s -> getEdgeIdString(g, s)));
-
         add(Pair.with(Pattern.compile("t\\[(.*)\\]"), s -> String.format("T.%s", s)));
         add(Pair.with(Pattern.compile("D\\[(.*)\\]"), s -> String.format("Direction.%s", s)));