You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
Handle Python 3 yield from
Start dealing with MAKE_FUNCTION flags - not done yet.
This commit is contained in:
BIN
test/bytecode_3.4/05_yield_from.pyc
Normal file
BIN
test/bytecode_3.4/05_yield_from.pyc
Normal file
Binary file not shown.
8
test/simple_source/expression/05_yield_from.py
Normal file
8
test/simple_source/expression/05_yield_from.py
Normal file
@@ -0,0 +1,8 @@
|
||||
# Python 3.3 and above only
|
||||
# Tests
|
||||
|
||||
# yield_from ::= expr expr YIELD_FROM
|
||||
# expr ::= yield_from
|
||||
|
||||
def _walk_dir(dir, ddir=None):
|
||||
yield from _walk_dir(dir, ddir=dfile)
|
@@ -375,10 +375,15 @@ class Python3Parser(PythonParser):
|
||||
load_genexpr ::= LOAD_GENEXPR
|
||||
load_genexpr ::= BUILD_TUPLE_1 LOAD_GENEXPR LOAD_CONST
|
||||
'''
|
||||
|
||||
def p_expr3(self, args):
|
||||
'''
|
||||
expr ::= LOAD_CLASSNAME
|
||||
# Python3 drops slice0..slice3
|
||||
|
||||
# Python 3.3+ adds yield from
|
||||
expr ::= yield_from
|
||||
yield_from ::= expr expr YIELD_FROM
|
||||
'''
|
||||
|
||||
@staticmethod
|
||||
@@ -497,11 +502,21 @@ class Python3Parser(PythonParser):
|
||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||
elif opname_base == 'UNPACK_LIST':
|
||||
rule = 'unpack_list ::= ' + opname + ' designator' * token.attr
|
||||
elif opname_base == ('MAKE_FUNCTION'):
|
||||
elif opname_base.startswith('MAKE_FUNCTION'):
|
||||
self.addRule('mklambda ::= %s LOAD_LAMBDA %s' %
|
||||
('expr ' * token.attr, opname), nop_func)
|
||||
if self.version >= 3.3:
|
||||
rule = 'mkfunc ::= %s LOAD_CONST LOAD_CONST %s' % ('expr ' * token.attr, opname)
|
||||
if opname.startswith('MAKE_FUNCTION_N'):
|
||||
args_pos = token.attr & 0xff
|
||||
args_kw = (token.attr >> 8) & 0xff
|
||||
rule = ('mkfunc ::= %s %s %s %s' %
|
||||
('expr ' * args_pos,
|
||||
'expr ' * args_kw,
|
||||
'LOAD_CONST ' * 3,
|
||||
opname))
|
||||
print(rule)
|
||||
else:
|
||||
rule = 'mkfunc ::= %s LOAD_CONST LOAD_CONST %s' % ('expr ' * token.attr, opname)
|
||||
else:
|
||||
rule = 'mkfunc ::= %s LOAD_CONST %s' % ('expr ' * token.attr, opname)
|
||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||
|
@@ -115,9 +115,21 @@ class Scanner35(scan3.Scanner3):
|
||||
'MAKE_FUNCTION', 'MAKE_CLOSURE',
|
||||
'DUP_TOPX', 'RAISE_VARARGS'
|
||||
):
|
||||
opname = '%s_%d' % (opname, inst.argval)
|
||||
if inst.opname != 'BUILD_SLICE':
|
||||
customize[opname] = inst.argval
|
||||
pos_args = inst.argval
|
||||
if inst.opname == 'MAKE_FUNCTION':
|
||||
argc = inst.argval
|
||||
pos_args = (argc & 0xFF)
|
||||
name_pair_args = (argc >> 8) & 0xFF
|
||||
if name_pair_args > 0:
|
||||
opname = 'MAKE_FUNCTION_N%d' % name_pair_args
|
||||
pass
|
||||
annotate_args = (argc >> 16) & 0x7FFF
|
||||
if annotate_args > 0:
|
||||
opname = '%s_A_%d' % [op_name, annotate_args]
|
||||
pass
|
||||
elif inst.opname != 'BUILD_SLICE':
|
||||
customize[opname] = pos_args
|
||||
opname = '%s_%d' % (opname, pos_args)
|
||||
|
||||
elif opname == 'JUMP_ABSOLUTE':
|
||||
pattr = inst.argval
|
||||
|
@@ -222,6 +222,16 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
||||
self.set_pos_info(node, start, len(self.f.getvalue()))
|
||||
self.prune() # stop recursing
|
||||
|
||||
# In Python 3.3+ only
|
||||
def n_yield_from(self, node):
|
||||
start = len(self.f.getvalue())
|
||||
self.write('yield from')
|
||||
self.write(' ')
|
||||
node[0].parent = node
|
||||
self.preorder(node[0][0][0][0])
|
||||
self.set_pos_info(node, start, len(self.f.getvalue()))
|
||||
self.prune() # stop recursing
|
||||
|
||||
def n_buildslice3(self, node):
|
||||
start = len(self.f.getvalue())
|
||||
p = self.prec
|
||||
@@ -490,7 +500,6 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
||||
|
||||
assert iscode(code)
|
||||
code = Code(code, self.scanner, self.currentclass)
|
||||
# assert isinstance(code, Code)
|
||||
|
||||
ast = self.build_ast(code._tokens, code._customize)
|
||||
self.customize(code._customize)
|
||||
@@ -534,7 +543,6 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
||||
assert iscode(code)
|
||||
# Or Code3
|
||||
code = Code(code, self.scanner, self.currentclass)
|
||||
# assert isinstance(code, Code)
|
||||
|
||||
ast = self.build_ast(code._tokens, code._customize)
|
||||
self.customize(code._customize)
|
||||
|
@@ -693,6 +693,13 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
self.preorder(node[0])
|
||||
self.prune() # stop recursing
|
||||
|
||||
# In Python 3.3+ only
|
||||
def n_yield_from(self, node):
|
||||
self.write('yield from')
|
||||
self.write(' ')
|
||||
self.preorder(node[0][0][0][0])
|
||||
self.prune() # stop recursing
|
||||
|
||||
def n_buildslice3(self, node):
|
||||
p = self.prec
|
||||
self.prec = 100
|
||||
@@ -1033,7 +1040,6 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
|
||||
assert iscode(code)
|
||||
code = Code(code, self.scanner, self.currentclass)
|
||||
# assert isinstance(code, Code)
|
||||
|
||||
ast = self.build_ast(code._tokens, code._customize)
|
||||
self.customize(code._customize)
|
||||
@@ -1476,11 +1482,13 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
- handle defaults
|
||||
- handle format tuple parameters
|
||||
"""
|
||||
# if formal parameter is a tuple, the paramater name
|
||||
# starts with a dot (eg. '.1', '.2')
|
||||
if name.startswith('.'):
|
||||
# replace the name with the tuple-string
|
||||
name = self.get_tuple_parameter(ast, name)
|
||||
if self.version < 3.0:
|
||||
# rocky: is this still even relevant?
|
||||
# if formal parameter is a tuple, the paramater name
|
||||
# starts with a dot (eg. '.1', '.2')
|
||||
if name.startswith('.'):
|
||||
# replace the name with the tuple-string
|
||||
name = self.get_tuple_parameter(ast, name)
|
||||
|
||||
if default:
|
||||
if self.showast:
|
||||
@@ -1500,7 +1508,6 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
|
||||
assert iscode(code)
|
||||
code = Code(code, self.scanner, self.currentclass)
|
||||
# assert isinstance(code, Code)
|
||||
|
||||
# add defaults values to parameter names
|
||||
argc = code.co_argcount
|
||||
@@ -1568,7 +1575,6 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
assert iscode(code)
|
||||
self.classes.append(self.currentclass)
|
||||
code = Code(code, self.scanner, self.currentclass)
|
||||
# assert isinstance(code, Code)
|
||||
|
||||
indent = self.indent
|
||||
# self.print_(indent, '#flags:\t', int(code.co_flags))
|
||||
|
Reference in New Issue
Block a user