Handle Python 3 yield from

Start dealing with MAKE_FUNCTION flags - not done yet.
This commit is contained in:
rocky
2016-05-07 11:20:15 -04:00
parent 039c115679
commit 36ffd4c31f
6 changed files with 64 additions and 15 deletions

Binary file not shown.

View 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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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))