3.4 dictionary comprehension bug

Sync up fragment code with recent changesa
This commit is contained in:
rocky
2016-06-19 00:49:22 -04:00
parent 73df5f3737
commit d7b79c2b59
7 changed files with 36 additions and 13 deletions

Binary file not shown.

View File

@@ -1,2 +1,5 @@
# Bug in python 3.x handling set comprehensions # Bug in python 3.x handling set comprehensions
{y for y in range(3)} {y for y in range(3)}
# Bug in python 3.4 (base64.py) in handling dict comprehension
b = {v: k for k, v in enumerate(b3)}

View File

@@ -121,12 +121,9 @@ class PythonParser(GenericASTBuilder):
def p_dictcomp(self, args): def p_dictcomp(self, args):
''' '''
expr ::= dictcomp expr ::= dictcomp
dictcomp ::= LOAD_DICTCOMP MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
stmt ::= dictcomp_func stmt ::= dictcomp_func
dictcomp_func ::= BUILD_MAP_0 LOAD_FAST FOR_ITER designator
dictcomp_func ::= BUILD_MAP LOAD_FAST FOR_ITER designator
comp_iter JUMP_BACK RETURN_VALUE RETURN_LAST comp_iter JUMP_BACK RETURN_VALUE RETURN_LAST
''' '''
def p_augmented_assign(self, args): def p_augmented_assign(self, args):

View File

@@ -287,6 +287,11 @@ class Python2Parser(PythonParser):
''' '''
def p_dictcomp2(self, args):
""""
dictcomp ::= LOAD_DICTCOMP MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
"""
def p_genexpr2(self, args): def p_genexpr2(self, args):
''' '''
genexpr ::= LOAD_GENEXPR MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1 genexpr ::= LOAD_GENEXPR MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1

View File

@@ -56,6 +56,11 @@ class Python3Parser(PythonParser):
# See also common Python p_list_comprehension # See also common Python p_list_comprehension
""" """
def p_dictcomp3(self, args):
""""
dictcomp ::= LOAD_DICTCOMP LOAD_CONST MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
"""
def p_grammar(self, args): def p_grammar(self, args):
''' '''
sstmt ::= stmt sstmt ::= stmt
@@ -428,6 +433,10 @@ class Python3Parser(PythonParser):
GET_ITER CALL_FUNCTION_1 GET_ITER CALL_FUNCTION_1
listcomp ::= {expr}^n LOAD_LISTCOMP MAKE_CLOSURE listcomp ::= {expr}^n LOAD_LISTCOMP MAKE_CLOSURE
GET_ITER CALL_FUNCTION_1 GET_ITER CALL_FUNCTION_1
dictcomp ::= LOAD_DICTCOMP LOAD_CONST MAKE_FUNCTION_0 expr
GET_ITER CALL_FUNCTION_1
Python < 3.4 Python < 3.4
listcomp ::= LOAD_LISTCOMP MAKE_FUNCTION_0 expr listcomp ::= LOAD_LISTCOMP MAKE_FUNCTION_0 expr
GET_ITER CALL_FUNCTION_1 GET_ITER CALL_FUNCTION_1
@@ -439,6 +448,7 @@ class Python3Parser(PythonParser):
dictcomp ::= LOAD_DICTCOMP MAKE_FUNCTION_0 expr dictcomp ::= LOAD_DICTCOMP MAKE_FUNCTION_0 expr
GET_ITER CALL_FUNCTION_1 GET_ITER CALL_FUNCTION_1
# build_class (see load_build_class) # build_class (see load_build_class)
build_list ::= {expr}^n BUILD_LIST_n build_list ::= {expr}^n BUILD_LIST_n
@@ -476,6 +486,14 @@ class Python3Parser(PythonParser):
rule = ("listcomp ::= LOAD_LISTCOMP MAKE_FUNCTION_0 expr " rule = ("listcomp ::= LOAD_LISTCOMP MAKE_FUNCTION_0 expr "
"GET_ITER CALL_FUNCTION_1") "GET_ITER CALL_FUNCTION_1")
self.add_unique_rule(rule, opname, token.attr, customize) self.add_unique_rule(rule, opname, token.attr, customize)
elif opname == 'LOAD_DICTCOMP':
if self.version >= 3.4:
rule = ("dictcomp ::= LOAD_DICTCOMP LOAD_CONST MAKE_FUNCTION_0 expr "
"GET_ITER CALL_FUNCTION_1")
else:
rule = ("dictcomp ::= LOAD_DICTCOMP MAKE_FUNCTION_0 expr "
"GET_ITER CALL_FUNCTION_1")
self.add_unique_rule(rule, opname, token.attr, customize)
elif opname == 'LOAD_SETCOMP': elif opname == 'LOAD_SETCOMP':
if self.version >= 3.4: if self.version >= 3.4:
rule = ("setcomp ::= LOAD_SETCOMP LOAD_CONST MAKE_FUNCTION_0 expr " rule = ("setcomp ::= LOAD_SETCOMP LOAD_CONST MAKE_FUNCTION_0 expr "

View File

@@ -588,7 +588,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
# skip over stmts sstmt smt # skip over stmts sstmt smt
ast = ast[0][0][0] ast = ast[0][0][0]
if ast == 'setcomp_func': if ast in ['setcomp_func', 'dictcomp_func']:
for k in ast: for k in ast:
if k == 'comp_iter': if k == 'comp_iter':
n = k n = k
@@ -605,15 +605,15 @@ class FragmentsWalker(pysource.SourceWalker, object):
## FIXME: I'm not totally sure this is right. ## FIXME: I'm not totally sure this is right.
# find innermost node # find innermost node
list_if_node = None if_node = None
while n in ('list_iter', 'comp_iter'): while n in ('list_iter', 'comp_iter'):
n = n[0] # recurse one step n = n[0] # recurse one step
if n == 'list_for': if n == 'list_for':
if n[2] == 'designator': if n[2] == 'designator':
designator = n[2] designator = n[2]
n = n[3] n = n[3]
elif n in ['list_if', 'list_if_not']: elif n in ['list_if', 'list_if_not', 'comp_if']:
list_if_node = n[0] if_node = n[0]
if n[1] == 'designator': if n[1] == 'designator':
designator = n[1] designator = n[1]
n = n[2] n = n[2]
@@ -633,9 +633,9 @@ class FragmentsWalker(pysource.SourceWalker, object):
node[-3].parent = node node[-3].parent = node
self.preorder(node[-3]) self.preorder(node[-3])
self.set_pos_info(node[-3], start, len(self.f.getvalue())) self.set_pos_info(node[-3], start, len(self.f.getvalue()))
if list_if_node: if if_node:
self.write(' if ') self.write(' if ')
self.preorder(list_if_node) self.preorder(if_node)
self.prec = p self.prec = p
def listcomprehension_walk2(self, node): def listcomprehension_walk2(self, node):
@@ -703,7 +703,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
def n_setcomp(self, node): def n_setcomp(self, node):
start = len(self.f.getvalue()) start = len(self.f.getvalue())
self.write('{') self.write('{')
if node[0] == 'LOAD_SETCOMP': if node[0] in ['LOAD_SETCOMP', 'LOAD_DICTCOMP']:
start = len(self.f.getvalue()) start = len(self.f.getvalue())
self.set_pos_info(node[0], start-1, start) self.set_pos_info(node[0], start-1, start)
self.listcomprehension_walk3(node, 1, 0) self.listcomprehension_walk3(node, 1, 0)

View File

@@ -1053,7 +1053,7 @@ class SourceWalker(GenericASTTraversal, object):
def n_setcomp(self, node): def n_setcomp(self, node):
self.write('{') self.write('{')
if node[0] == 'LOAD_SETCOMP': if node[0] in ['LOAD_SETCOMP', 'LOAD_DICTCOMP']:
self.listcomprehension_walk3(node, 1, 0) self.listcomprehension_walk3(node, 1, 0)
else: else:
self.comprehension_walk(node, iter_index=4) self.comprehension_walk(node, iter_index=4)
@@ -1078,7 +1078,7 @@ class SourceWalker(GenericASTTraversal, object):
# skip over stmts sstmt smt # skip over stmts sstmt smt
ast = ast[0][0][0] ast = ast[0][0][0]
designator = None designator = None
if ast == 'setcomp_func': if ast in ['setcomp_func', 'dictcomp_func']:
for k in ast: for k in ast:
if k == 'comp_iter': if k == 'comp_iter':
n = k n = k