summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorLarry Hastings <larry@hastings.org>2013-11-23 22:49:22 (GMT)
committerLarry Hastings <larry@hastings.org>2013-11-23 22:49:22 (GMT)
commit3a9079742f2d71e6968823e155f3778473113538 (patch)
tree742dd59d633f184a06858baec56ab83c20192e59 /Lib
parent8d0d369067462080f5ea9d50416a12bee0ef3a6a (diff)
downloadcpython-3a9079742f2d71e6968823e155f3778473113538.zip
cpython-3a9079742f2d71e6968823e155f3778473113538.tar.gz
cpython-3a9079742f2d71e6968823e155f3778473113538.tar.bz2
Issue #19722: Added opcode.stack_effect(), which accurately
computes the stack effect of bytecode instructions.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/opcode.py13
-rw-r--r--Lib/test/test__opcode.py22
2 files changed, 35 insertions, 0 deletions
diff --git a/Lib/opcode.py b/Lib/opcode.py
index 78d1229..0bd1ee6 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -8,6 +8,19 @@ __all__ = ["cmp_op", "hasconst", "hasname", "hasjrel", "hasjabs",
"haslocal", "hascompare", "hasfree", "opname", "opmap",
"HAVE_ARGUMENT", "EXTENDED_ARG", "hasnargs"]
+# It's a chicken-and-egg I'm afraid:
+# We're imported before _opcode's made.
+# With exception unheeded
+# (stack_effect is not needed)
+# Both our chickens and eggs are allayed.
+# --Larry Hastings, 2013/11/23
+
+try:
+ from _opcode import stack_effect
+ __all__.append('stack_effect')
+except ImportError:
+ pass
+
cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
'is not', 'exception match', 'BAD')
diff --git a/Lib/test/test__opcode.py b/Lib/test/test__opcode.py
new file mode 100644
index 0000000..cab8769
--- /dev/null
+++ b/Lib/test/test__opcode.py
@@ -0,0 +1,22 @@
+import dis
+import _opcode
+from test.support import run_unittest
+import unittest
+
+class OpcodeTests(unittest.TestCase):
+
+ def test_stack_effect(self):
+ self.assertEqual(_opcode.stack_effect(dis.opmap['POP_TOP']), -1)
+ self.assertEqual(_opcode.stack_effect(dis.opmap['DUP_TOP_TWO']), 2)
+ self.assertEqual(_opcode.stack_effect(dis.opmap['BUILD_SLICE'], 0), -1)
+ self.assertEqual(_opcode.stack_effect(dis.opmap['BUILD_SLICE'], 1), -1)
+ self.assertEqual(_opcode.stack_effect(dis.opmap['BUILD_SLICE'], 3), -2)
+ self.assertRaises(ValueError, _opcode.stack_effect, 30000)
+ self.assertRaises(ValueError, _opcode.stack_effect, dis.opmap['BUILD_SLICE'])
+ self.assertRaises(ValueError, _opcode.stack_effect, dis.opmap['POP_TOP'], 0)
+
+def test_main():
+ run_unittest(OpcodeTests)
+
+if __name__ == "__main__":
+ test_main()