Python 3.0 doesn't have POP_JUMP ops...

In some ways Python 3.0 code generation is more like Python 2.6 (and
before) than it is Python 2.7 or 3.0.
This commit is contained in:
rocky
2016-11-06 08:55:03 -05:00
parent 2a5eda631a
commit 5d10f7a0b0
3 changed files with 37 additions and 22 deletions

View File

@@ -5,19 +5,24 @@ spark grammar differences over Python 3.1 for Python 3.0.
from __future__ import print_function from __future__ import print_function
from uncompyle6.parser import PythonParserSingle from uncompyle6.parser import PythonParserSingle
from uncompyle6.parsers.parse31 import Python31Parser from uncompyle6.parsers.parse3 import Python3Parser
class Python30Parser(Python31Parser): class Python30Parser(Python3Parser):
def p_30(self, args): def p_30(self, args):
""" """
# Store locals is only in Python 3.0 to 3.3 # Store locals is only in Python 3.0 to 3.3
stmt ::= store_locals stmt ::= store_locals
store_locals ::= LOAD_FAST STORE_LOCALS store_locals ::= LOAD_FAST STORE_LOCALS
jmp_true ::= JUMP_IF_TRUE_OR_POP POP_TOP
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD POP_TOP COME_FROM # In many ways Python 3.0 code generation is more like Python 2.6 than
# it is 2.7 or 3.1. So we have a number of 2.6ish (and before) rules below
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD come_froms POP_TOP COME_FROM
jmp_true ::= JUMP_IF_TRUE POP_TOP
""" """
class Python31ParserSingle(Python31Parser, PythonParserSingle): class Python30ParserSingle(Python30Parser, PythonParserSingle):
pass pass

View File

@@ -91,18 +91,35 @@ class Scanner3(Scanner):
self.opc.JUMP_ABSOLUTE, self.opc.UNPACK_EX self.opc.JUMP_ABSOLUTE, self.opc.UNPACK_EX
]) ])
self.jump_if_pop = frozenset([self.opc.JUMP_IF_FALSE_OR_POP, if self.version > 3.0:
self.opc.JUMP_IF_TRUE_OR_POP]) self.jump_if_pop = frozenset([self.opc.JUMP_IF_FALSE_OR_POP,
self.opc.JUMP_IF_TRUE_OR_POP])
self.pop_jump_if_pop = frozenset([self.opc.JUMP_IF_FALSE_OR_POP, self.pop_jump_if_pop = frozenset([self.opc.JUMP_IF_FALSE_OR_POP,
self.opc.JUMP_IF_TRUE_OR_POP, self.opc.JUMP_IF_TRUE_OR_POP,
self.opc.POP_JUMP_IF_TRUE, self.opc.POP_JUMP_IF_TRUE,
self.opc.POP_JUMP_IF_FALSE]) self.opc.POP_JUMP_IF_FALSE])
# Not really a set, but still clasification-like
self.statement_opcode_sequences = [
(self.opc.POP_JUMP_IF_FALSE, self.opc.JUMP_FORWARD),
(self.opc.POP_JUMP_IF_FALSE, self.opc.JUMP_ABSOLUTE),
(self.opc.POP_JUMP_IF_TRUE, self.opc.JUMP_FORWARD),
(self.opc.POP_JUMP_IF_TRUE, self.opc.JUMP_ABSOLUTE)]
else:
self.jump_if_pop = frozenset([])
self.pop_jump_if_pop = frozenset([])
# Not really a set, but still clasification-like
self.statement_opcode_sequences = [
(self.opc.JUMP_FORWARD,),
(self.opc.JUMP_ABSOLUTE,),
(self.opc.JUMP_FORWARD,),
(self.opc.JUMP_ABSOLUTE,)]
# Opcodes that take a variable number of arguments # Opcodes that take a variable number of arguments
# (expr's) # (expr's)
varargs_ops = set([ varargs_ops = set([
self.opc.BUILD_LIST, self.opc.BUILD_TUPLE, self.opc.BUILD_LIST, self.opc.BUILD_TUPLE,
self.opc.BUILD_SET, self.opc.BUILD_SLICE, self.opc.BUILD_SET, self.opc.BUILD_SLICE,
self.opc.BUILD_MAP, self.opc.UNPACK_SEQUENCE, self.opc.BUILD_MAP, self.opc.UNPACK_SEQUENCE,
self.opc.RAISE_VARARGS]) self.opc.RAISE_VARARGS])
@@ -111,13 +128,6 @@ class Scanner3(Scanner):
varargs_ops.add(self.opc.CALL_METHOD) varargs_ops.add(self.opc.CALL_METHOD)
self.varargs_ops = frozenset(varargs_ops) self.varargs_ops = frozenset(varargs_ops)
# Not really a set, but still clasification-like
self.statement_opcode_sequences = [
(self.opc.POP_JUMP_IF_FALSE, self.opc.JUMP_FORWARD),
(self.opc.POP_JUMP_IF_FALSE, self.opc.JUMP_ABSOLUTE),
(self.opc.POP_JUMP_IF_TRUE, self.opc.JUMP_FORWARD),
(self.opc.POP_JUMP_IF_TRUE, self.opc.JUMP_ABSOLUTE)]
def opName(self, offset): def opName(self, offset):
return self.opc.opname[self.code[offset]] return self.opc.opname[self.code[offset]]
@@ -139,7 +149,7 @@ class Scanner3(Scanner):
""" """
show_asm = self.show_asm if not show_asm else show_asm show_asm = self.show_asm if not show_asm else show_asm
# show_asm = 'after' # show_asm = 'before'
if show_asm in ('both', 'before'): if show_asm in ('both', 'before'):
bytecode = Bytecode(co, self.opc) bytecode = Bytecode(co, self.opc)
for instr in bytecode.get_instructions(co): for instr in bytecode.get_instructions(co):

View File

@@ -16,7 +16,7 @@ from uncompyle6.scanners.scanner3 import Scanner3
class Scanner30(Scanner3): class Scanner30(Scanner3):
def __init__(self, show_asm=None, is_pypy=False): def __init__(self, show_asm=None, is_pypy=False):
Scanner3.__init__(self, 3.1, show_asm, is_pypy) Scanner3.__init__(self, 3.0, show_asm, is_pypy)
return return
pass pass