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 2016/12/02 11:32:22 UTC

[02/50] tinkerpop git commit: sorry for the late tweak. Here is the thing. With then new Bindings model, you don't need withBindings() in Gremlin-Java. And, moreoever, it was never used in Gremlin-Python (or any script-based GLV). Thus, its pointless. De

sorry for the late tweak. Here is the thing. With then new Bindings model, you don't need withBindings() in Gremlin-Java. And, moreoever, it was never used in Gremlin-Python (or any script-based GLV). Thus, its pointless. Deprecated it. Updated the docs accordingly. Also added more test cases to BytecodeTest and test_traversal.py to ensure that both Gremlin-Java bindings and Gremlin-Python bindings have the same look and feel to the user.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/987e6ab4
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/987e6ab4
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/987e6ab4

Branch: refs/heads/TINKERPOP-1562
Commit: 987e6ab4f2ca643a5eb181f4b52417bf9814fcbd
Parents: b70ba90
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Nov 30 10:14:01 2016 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Nov 30 10:14:01 2016 -0700

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../src/reference/gremlin-applications.asciidoc |  6 +--
 docs/src/reference/gremlin-variants.asciidoc    |  5 ---
 .../gremlin-language-variants/index.asciidoc    |  3 --
 .../gremlin/process/traversal/Bindings.java     | 41 ++++++++++++++------
 .../gremlin/process/traversal/Bytecode.java     | 10 ++---
 .../process/traversal/TraversalSource.java      |  7 ++--
 .../dsl/graph/GraphTraversalSource.java         |  4 +-
 .../gremlin/process/traversal/BytecodeTest.java |  8 ++--
 .../python/GraphTraversalSourceGenerator.groovy |  2 -
 .../python/TraversalSourceGenerator.groovy      |  6 +++
 .../gremlin_python/process/graph_traversal.py   |  2 -
 .../jython/gremlin_python/process/traversal.py  |  6 +++
 .../main/jython/tests/process/test_traversal.py | 13 +++++++
 14 files changed, 72 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 10a0604..237b7ce 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Deprecated `TraversalSource.withBindings()` as it is no longer needed in Gremlin-Java and never was needed for other variants.
 * Fixed a bug in Gremlin-Java `Bytecode` where anonymous traversals were not aware of parent bindings.
 * Fixed a bug in Gremlin-Java GraphSON deserialization around `P.within()` and `P.without()`.
 * Converted Spark process suite tests to "integration" tests.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/docs/src/reference/gremlin-applications.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index c452a0f..f7ba2b5 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -939,13 +939,13 @@ times and sizing) can be done in the Gremlin Server configuration file as descri
 Finally, Gremlin `Bytecode` supports the encoding of bindings which allow GremlinServer to cache traversals that will
 be reused over and over again save that some parameterization may change. Thus, instead of translating, compiling, and
 then executing each submitted bytecode, it is possible to simply execute. To express bindings in Gremlin-Java and
-Gremlin-Groovy, use the `withBindings()` traversal source method.
+Gremlin-Groovy, use `Bindings`.
 
 [gremlin-groovy]
 ----
 cluster = Cluster.open('conf/remote-objects.yaml')
-b = new Bindings()
-g = EmptyGraph.instance().traversal().withBindings(b).withRemote(DriverRemoteConnection.using(cluster, "g"))
+b = Bindings.instance()
+g = EmptyGraph.instance().traversal().withRemote(DriverRemoteConnection.using(cluster, "g"))
 g.V(b.of('id',1)).out('created').values('name')
 g.V(b.of('id',4)).out('created').values('name')
 g.V(b.of('id',4)).out('created').values('name').getBytecode()

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/docs/src/reference/gremlin-variants.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc
index 853b087..39b5558 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -265,11 +265,6 @@ g.V(('id',1)).out('created').name.toList()
 g.V(('id',4)).out('created').name.toList()
 ----
 
-NOTE: The Gremlin `withBindings()` traversal source step is not needed. Typically `withBindings()` is only required
-in statically typed languages where bindings need to have the same typing as the `Traversal` API. However, if desired,
-it is possible to use the `withBindings()`-model as Gremlin-Python's `Bindings.of()` simply returns a 2-tuple of `(str,object)`
-(see <<connecting-via-remotegraph,`Bindings`>>).
-
 Traversal Strategies
 ~~~~~~~~~~~~~~~~~~~~
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/docs/src/tutorials/gremlin-language-variants/index.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/tutorials/gremlin-language-variants/index.asciidoc b/docs/src/tutorials/gremlin-language-variants/index.asciidoc
index 533aa04..abd402b 100644
--- a/docs/src/tutorials/gremlin-language-variants/index.asciidoc
+++ b/docs/src/tutorials/gremlin-language-variants/index.asciidoc
@@ -346,7 +346,6 @@ class GraphTraversalSourceGenerator {
                 findAll { GraphTraversalSource.class.equals(it.returnType) }.
                 findAll {
                     !it.name.equals("clone") &&
-                            !it.name.equals(TraversalSource.Symbols.withBindings) &&
                             !it.name.equals(TraversalSource.Symbols.withRemote)
                 }.
                 collect { SymbolHelper.toPython(it.name) }.
@@ -365,8 +364,6 @@ class GraphTraversalSourceGenerator {
     source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
     source.traversal_strategies.add_strategies([RemoteStrategy(remote_connection)])
     return source
-  def withBindings(self, bindings):
-    return self
 """)
         GraphTraversalSource.getMethods(). // SPAWN STEPS
                 findAll { GraphTraversal.class.equals(it.returnType) }.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bindings.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bindings.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bindings.java
index 3359942..d399bb2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bindings.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bindings.java
@@ -19,7 +19,6 @@
 
 package org.apache.tinkerpop.gremlin.process.traversal;
 
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -30,8 +29,8 @@ import java.util.Map;
  * For instance:
  * <p>
  * <code>
- * b = new Bindings()
- * g = graph.traversal().withBindings(b)
+ * b = Bindings.instance()
+ * g = graph.traversal()
  * g.V().out(b.of("a","knows"))
  * // bindings can be reused over and over
  * g.V().out("knows").in(b.of("a","created"))
@@ -42,26 +41,44 @@ import java.util.Map;
  */
 public final class Bindings {
 
+    private static final Bindings INSTANCE = new Bindings();
     private static final ThreadLocal<Map<Object, String>> MAP = new ThreadLocal<>();
 
+    /**
+     * @deprecated Since 3.2.4. Instead, use {@link Bindings#instance()}.
+     */
+    @Deprecated
+    public Bindings() {
+
+    }
+
     public <V> V of(final String variable, final V value) {
-        if (null == MAP.get())
-            MAP.set(new HashMap<>());
-        MAP.get().put(value, variable);
+        Map<Object, String> map = MAP.get();
+        if (null == map) {
+            map = new HashMap<>();
+            MAP.set(map);
+        }
+        map.put(value, variable);
         return value;
     }
 
-    protected <V> String getBoundVariable(final V value) {
-        return null == MAP.get() ? null : MAP.get().get(value);
+    protected static <V> String getBoundVariable(final V value) {
+        final Map<Object, String> map = MAP.get();
+        return null == map ? null : map.get(value);
+    }
+
+    protected static void clear() {
+        final Map<Object, String> map = MAP.get();
+        if (null != map)
+            map.clear();
     }
 
-    protected void clear() {
-        if (null != MAP.get())
-            MAP.get().clear();
+    public static Bindings instance() {
+        return INSTANCE;
     }
 
     @Override
     public String toString() {
-        return null == MAP.get() ? Collections.emptyMap().toString() : MAP.get().toString();
+        return "bindings[" + Thread.currentThread().getName() + "]";
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java
index 11f6341..7ea5f6f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java
@@ -52,7 +52,6 @@ public final class Bytecode implements Cloneable, Serializable {
 
     private List<Instruction> sourceInstructions = new ArrayList<>();
     private List<Instruction> stepInstructions = new ArrayList<>();
-    private final transient Bindings bindings = new Bindings();
 
     /**
      * Add a {@link TraversalSource} instruction to the bytecode.
@@ -69,10 +68,9 @@ public final class Bytecode implements Cloneable, Serializable {
                         (Class) arguments[i];
             }
             this.sourceInstructions.add(new Instruction(sourceName, classes));
-        } else if (!sourceName.equals(TraversalSource.Symbols.withBindings)) {
+        } else
             this.sourceInstructions.add(new Instruction(sourceName, flattenArguments(arguments)));
-        }
-        this.bindings.clear();
+        Bindings.clear();
     }
 
     /**
@@ -83,7 +81,7 @@ public final class Bytecode implements Cloneable, Serializable {
      */
     public void addStep(final String stepName, final Object... arguments) {
         this.stepInstructions.add(new Instruction(stepName, flattenArguments(arguments)));
-        this.bindings.clear();
+        Bindings.clear();
     }
 
     /**
@@ -271,7 +269,7 @@ public final class Bytecode implements Cloneable, Serializable {
 
     private final Object convertArgument(final Object argument, final boolean searchBindings) {
         if (searchBindings) {
-            final String variable = this.bindings.getBoundVariable(argument);
+            final String variable = Bindings.getBoundVariable(argument);
             if (null != variable)
                 return new Binding<>(variable, convertArgument(argument, false));
         }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
index df1d89a..32c034a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
@@ -84,6 +84,7 @@ public interface TraversalSource extends Cloneable, AutoCloseable {
             // static fields only
         }
 
+        @Deprecated
         public static final String withBindings = "withBindings";
         public static final String withSack = "withSack";
         public static final String withStrategies = "withStrategies";
@@ -133,11 +134,11 @@ public interface TraversalSource extends Cloneable, AutoCloseable {
      *
      * @param bindings the bindings instance to use
      * @return a new traversal source with set bindings
+     * @deprecated Since 3.2.4, simply use {@link Bindings} without reference to a {@link TraversalSource}.
      */
+    @Deprecated
     public default TraversalSource withBindings(final Bindings bindings) {
-        final TraversalSource clone = this.clone();
-        clone.getBytecode().addSource(Symbols.withBindings, bindings);
-        return clone;
+        return this;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
----------------------------------------------------------------------
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 362c571..af78add 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
@@ -45,7 +45,6 @@ import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
@@ -134,10 +133,11 @@ public class GraphTraversalSource implements TraversalSource {
     }
 
     @Override
+    @Deprecated
     public GraphTraversalSource withBindings(final Bindings bindings) {
         return (GraphTraversalSource) TraversalSource.super.withBindings(bindings);
     }
-    
+
     @Override
     public GraphTraversalSource withComputer(final Computer computer) {
         return (GraphTraversalSource) TraversalSource.super.withComputer(computer);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/BytecodeTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/BytecodeTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/BytecodeTest.java
index ea81bdc..e1a31c4 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/BytecodeTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/BytecodeTest.java
@@ -82,8 +82,8 @@ public class BytecodeTest {
 
     @Test
     public void shouldIncludeBindingsInEquality() {
-        final Bindings b = new Bindings();
-        final GraphTraversalSource g = EmptyGraph.instance().traversal().withBindings(b);
+        final Bindings b = Bindings.instance();
+        final GraphTraversalSource g = EmptyGraph.instance().traversal();
 
         final Bytecode bytecode1 = g.V().out(b.of("a", "created")).asAdmin().getBytecode();
         final Bytecode bytecode2 = g.V().out(b.of("a", "knows")).asAdmin().getBytecode();
@@ -103,8 +103,8 @@ public class BytecodeTest {
 
     @Test
     public void shouldIncludeBindingsInNestedTraversals() {
-        final Bindings b = new Bindings();
-        final GraphTraversalSource g = EmptyGraph.instance().traversal().withBindings(b);
+        final Bindings b = Bindings.instance();
+        final GraphTraversalSource g = EmptyGraph.instance().traversal();
         final Bytecode bytecode = g.V().in(b.of("a","created")).where(__.out(b.of("b","knows")).has("age",b.of("c",P.gt(32))).map(__.values(b.of("d","name")))).asAdmin().getBytecode();
         assertEquals(4, bytecode.getBindings().size());
         assertEquals("created", bytecode.getBindings().get("a"));

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GraphTraversalSourceGenerator.groovy
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GraphTraversalSourceGenerator.groovy b/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GraphTraversalSourceGenerator.groovy
index ed377bd..0d36581 100644
--- a/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GraphTraversalSourceGenerator.groovy
+++ b/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GraphTraversalSourceGenerator.groovy
@@ -102,8 +102,6 @@ under the License.
     source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
     source.traversal_strategies.add_strategies([RemoteStrategy(remote_connection)])
     return source
-  def withBindings(self, bindings):
-    return self
   def withComputer(self,graph_computer=None, workers=None, result=None, persist=None, vertices=None, edges=None, configuration=None):
     return self.withStrategies(VertexProgramStrategy(graph_computer,workers,result,persist,vertices,edges,configuration))
 """)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy b/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy
index a3684cb..b6f25e3 100644
--- a/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy
+++ b/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy
@@ -310,6 +310,12 @@ class Binding(object):
     def __init__(self,key,value):
         self.key = key
         self.value = value
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.key == other.key and self.value == other.value
+    def __hash__(self):
+        return hash(self.key) + hash(self.value)
+    def __repr__(self):
+        return "binding[" + self.key + "=" + str(self.value) + "]"
 
 """)
         //////////////

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
index 6165ed3..ceb4cb4 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
@@ -62,8 +62,6 @@ class GraphTraversalSource(object):
     source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
     source.traversal_strategies.add_strategies([RemoteStrategy(remote_connection)])
     return source
-  def withBindings(self, bindings):
-    return self
   def withComputer(self,graph_computer=None, workers=None, result=None, persist=None, vertices=None, edges=None, configuration=None):
     return self.withStrategies(VertexProgramStrategy(graph_computer,workers,result,persist,vertices,edges,configuration))
   def E(self, *args):

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
index d30db35..a7b6118 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
@@ -373,4 +373,10 @@ class Binding(object):
     def __init__(self,key,value):
         self.key = key
         self.value = value
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.key == other.key and self.value == other.value
+    def __hash__(self):
+        return hash(self.key) + hash(self.value)
+    def __repr__(self):
+        return "binding[" + self.key + "=" + str(self.value) + "]"
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/987e6ab4/gremlin-python/src/main/jython/tests/process/test_traversal.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/process/test_traversal.py b/gremlin-python/src/main/jython/tests/process/test_traversal.py
index 0f25190..e68b1e2 100644
--- a/gremlin-python/src/main/jython/tests/process/test_traversal.py
+++ b/gremlin-python/src/main/jython/tests/process/test_traversal.py
@@ -24,6 +24,8 @@ from unittest import TestCase
 
 from gremlin_python.structure.graph import Graph
 from gremlin_python.process.traversal import P
+from gremlin_python.process.traversal import Binding
+from gremlin_python.process.graph_traversal import __
 
 
 class TestTraversal(TestCase):
@@ -52,6 +54,17 @@ class TestTraversal(TestCase):
         assert 1 == len(bytecode.step_instructions[0])
         assert 1 == len(bytecode.step_instructions[1])
         assert 2 == len(bytecode.step_instructions[2])
+        ##
+        bytecode = g.V(('a',[1,2,3])).out(('b','created')).where(__.in_(('c','created'),('d','knows')).count().is_(('e',P.gt(2)))).bytecode
+        assert 5 == len(bytecode.bindings.keys())
+        assert [1,2,3] == bytecode.bindings['a']
+        assert 'created' == bytecode.bindings['b']
+        assert 'created' == bytecode.bindings['c']
+        assert 'knows' == bytecode.bindings['d']
+        assert P.gt(2) == bytecode.bindings['e']
+        assert Binding('b','created') == bytecode.step_instructions[1][1]
+        assert 'binding[b=created]' == str(bytecode.step_instructions[1][1])
+        assert isinstance(hash(bytecode.step_instructions[1][1]),int)
 
     def test_P(self):
         # verify that the order of operations is respected