You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
Correct generator function parsing for 3.3..3.5
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
PYTHON_VERSION=3.7.16
|
PYTHON_VERSION=3.8.17
|
||||||
|
|
||||||
function checkout_version {
|
function checkout_version {
|
||||||
local repo=$1
|
local repo=$1
|
||||||
|
@@ -80,7 +80,6 @@ def usage():
|
|||||||
|
|
||||||
|
|
||||||
def main_bin():
|
def main_bin():
|
||||||
current_bytecode_supported = True
|
|
||||||
recurse_dirs = False
|
recurse_dirs = False
|
||||||
numproc = 0
|
numproc = 0
|
||||||
outfile = "-"
|
outfile = "-"
|
||||||
|
@@ -15,12 +15,12 @@ class Python33Parser(Python32Parser):
|
|||||||
# Python 3.3+ adds yield from.
|
# Python 3.3+ adds yield from.
|
||||||
expr ::= yield_from
|
expr ::= yield_from
|
||||||
yield_from ::= expr expr YIELD_FROM
|
yield_from ::= expr expr YIELD_FROM
|
||||||
|
stmt ::= genexpr_func
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def customize_grammar_rules(self, tokens, customize):
|
def customize_grammar_rules(self, tokens, customize):
|
||||||
self.remove_rules("""
|
self.remove_rules("""
|
||||||
# 3.3+ adds POP_BLOCKS
|
# 3.3+ adds POP_BLOCKS
|
||||||
genexpr_func ::= LOAD_ARG FOR_ITER store comp_iter JUMP_BACK
|
|
||||||
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK NOP COME_FROM_LOOP
|
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK NOP COME_FROM_LOOP
|
||||||
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK NOP COME_FROM_LOOP
|
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK NOP COME_FROM_LOOP
|
||||||
""")
|
""")
|
||||||
|
@@ -52,6 +52,8 @@ class Python34Parser(Python33Parser):
|
|||||||
yield_from ::= expr GET_ITER LOAD_CONST YIELD_FROM
|
yield_from ::= expr GET_ITER LOAD_CONST YIELD_FROM
|
||||||
|
|
||||||
_ifstmts_jump ::= c_stmts_opt JUMP_ABSOLUTE JUMP_FORWARD COME_FROM
|
_ifstmts_jump ::= c_stmts_opt JUMP_ABSOLUTE JUMP_FORWARD COME_FROM
|
||||||
|
|
||||||
|
genexpr_func ::= LOAD_ARG _come_froms FOR_ITER store comp_iter JUMP_BACK
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def customize_grammar_rules(self, tokens, customize):
|
def customize_grammar_rules(self, tokens, customize):
|
||||||
|
@@ -191,9 +191,6 @@ class Python36Parser(Python35Parser):
|
|||||||
COME_FROM_FINALLY
|
COME_FROM_FINALLY
|
||||||
|
|
||||||
compare_chained2 ::= expr COMPARE_OP come_froms JUMP_FORWARD
|
compare_chained2 ::= expr COMPARE_OP come_froms JUMP_FORWARD
|
||||||
|
|
||||||
stmt ::= genexpr_func
|
|
||||||
genexpr_func ::= LOAD_ARG _come_froms FOR_ITER store comp_iter JUMP_BACK
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Some of this is duplicated from parse37. Eventually we'll probably rebase from
|
# Some of this is duplicated from parse37. Eventually we'll probably rebase from
|
||||||
|
@@ -39,6 +39,7 @@ from typing import Optional, Tuple
|
|||||||
|
|
||||||
from xdis import iscode, instruction_size, Instruction
|
from xdis import iscode, instruction_size, Instruction
|
||||||
from xdis.bytecode import _get_const_info
|
from xdis.bytecode import _get_const_info
|
||||||
|
from xdis.codetype import UnicodeForPython3
|
||||||
|
|
||||||
from uncompyle6.scanners.tok import Token
|
from uncompyle6.scanners.tok import Token
|
||||||
from uncompyle6.scanner import parse_fn_counts_30_35
|
from uncompyle6.scanner import parse_fn_counts_30_35
|
||||||
@@ -572,16 +573,19 @@ class Scanner3(Scanner):
|
|||||||
if op in self.opc.CONST_OPS:
|
if op in self.opc.CONST_OPS:
|
||||||
const = argval
|
const = argval
|
||||||
if iscode(const):
|
if iscode(const):
|
||||||
if const.co_name == "<lambda>":
|
co_name = const.co_name
|
||||||
|
if isinstance(const.co_name, UnicodeForPython3):
|
||||||
|
co_name = const.co_name.value.decode("utf-8")
|
||||||
|
if co_name == "<lambda>":
|
||||||
assert opname == "LOAD_CONST"
|
assert opname == "LOAD_CONST"
|
||||||
opname = "LOAD_LAMBDA"
|
opname = "LOAD_LAMBDA"
|
||||||
elif const.co_name == "<genexpr>":
|
elif co_name == "<genexpr>":
|
||||||
opname = "LOAD_GENEXPR"
|
opname = "LOAD_GENEXPR"
|
||||||
elif const.co_name == "<dictcomp>":
|
elif co_name == "<dictcomp>":
|
||||||
opname = "LOAD_DICTCOMP"
|
opname = "LOAD_DICTCOMP"
|
||||||
elif const.co_name == "<setcomp>":
|
elif co_name == "<setcomp>":
|
||||||
opname = "LOAD_SETCOMP"
|
opname = "LOAD_SETCOMP"
|
||||||
elif const.co_name == "<listcomp>":
|
elif co_name == "<listcomp>":
|
||||||
opname = "LOAD_LISTCOMP"
|
opname = "LOAD_LISTCOMP"
|
||||||
else:
|
else:
|
||||||
opname = "LOAD_CODE"
|
opname = "LOAD_CODE"
|
||||||
@@ -589,8 +593,8 @@ class Scanner3(Scanner):
|
|||||||
# now holds Code(const) and thus can not be used
|
# now holds Code(const) and thus can not be used
|
||||||
# for comparison (todo: think about changing this)
|
# for comparison (todo: think about changing this)
|
||||||
# pattr = 'code_object @ 0x%x %s->%s' %\
|
# pattr = 'code_object @ 0x%x %s->%s' %\
|
||||||
# (id(const), const.co_filename, const.co_name)
|
# (id(const), const.co_filename, co_name)
|
||||||
pattr = "<code_object " + const.co_name + ">"
|
pattr = "<code_object " + co_name + ">"
|
||||||
elif isinstance(const, str):
|
elif isinstance(const, str):
|
||||||
opname = "LOAD_STR"
|
opname = "LOAD_STR"
|
||||||
else:
|
else:
|
||||||
|
@@ -174,9 +174,11 @@ class ComprehensionMixin:
|
|||||||
tree = tree[1]
|
tree = tree[1]
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if tree in ("genexpr_func_async",):
|
if tree in ("genexpr_func", "genexpr_func_async",):
|
||||||
if tree[3] == "comp_iter":
|
for i in range(3, 5):
|
||||||
iter_index = 3
|
if tree[i] == "comp_iter":
|
||||||
|
iter_index = i
|
||||||
|
break
|
||||||
|
|
||||||
n = tree[iter_index]
|
n = tree[iter_index]
|
||||||
|
|
||||||
|
@@ -146,7 +146,6 @@ class NonterminalActions:
|
|||||||
self.prune() # stop recursing
|
self.prune() # stop recursing
|
||||||
|
|
||||||
def n_classdef(self, node):
|
def n_classdef(self, node):
|
||||||
|
|
||||||
if self.version >= (3, 6):
|
if self.version >= (3, 6):
|
||||||
self.n_classdef36(node)
|
self.n_classdef36(node)
|
||||||
elif self.version >= (3, 0):
|
elif self.version >= (3, 0):
|
||||||
@@ -228,8 +227,10 @@ class NonterminalActions:
|
|||||||
else:
|
else:
|
||||||
# from trepan.api import debug; debug()
|
# from trepan.api import debug; debug()
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
("Internal Error: n_const_list expects dict, list set, or set; got "
|
(
|
||||||
f"{lastnodetype}")
|
"Internal Error: n_const_list expects dict, list set, or set; got "
|
||||||
|
f"{lastnodetype}"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.indent_more(INDENT_PER_LEVEL)
|
self.indent_more(INDENT_PER_LEVEL)
|
||||||
@@ -521,7 +522,6 @@ class NonterminalActions:
|
|||||||
self.prune()
|
self.prune()
|
||||||
|
|
||||||
def n_docstring(self, node):
|
def n_docstring(self, node):
|
||||||
|
|
||||||
indent = self.indent
|
indent = self.indent
|
||||||
doc_node = node[0]
|
doc_node = node[0]
|
||||||
if doc_node.attr:
|
if doc_node.attr:
|
||||||
@@ -543,7 +543,7 @@ class NonterminalActions:
|
|||||||
self.write(indent)
|
self.write(indent)
|
||||||
docstring = repr(docstring.expandtabs())[1:-1]
|
docstring = repr(docstring.expandtabs())[1:-1]
|
||||||
|
|
||||||
for (orig, replace) in (
|
for orig, replace in (
|
||||||
("\\\\", "\t"),
|
("\\\\", "\t"),
|
||||||
("\\r\\n", "\n"),
|
("\\r\\n", "\n"),
|
||||||
("\\n", "\n"),
|
("\\n", "\n"),
|
||||||
@@ -701,8 +701,11 @@ class NonterminalActions:
|
|||||||
self.write("(")
|
self.write("(")
|
||||||
iter_index = 3
|
iter_index = 3
|
||||||
if self.version > (3, 2):
|
if self.version > (3, 2):
|
||||||
if self.version >= (3, 6):
|
if self.version >= (3, 4):
|
||||||
if node[0].kind in ("load_closure", "load_genexpr") and self.version >= (3, 8):
|
if node[0].kind in (
|
||||||
|
"load_closure",
|
||||||
|
"load_genexpr",
|
||||||
|
) and self.version >= (3, 8):
|
||||||
code_index = -6
|
code_index = -6
|
||||||
is_lambda = self.is_lambda
|
is_lambda = self.is_lambda
|
||||||
if node[0].kind == "load_genexpr":
|
if node[0].kind == "load_genexpr":
|
||||||
@@ -710,13 +713,20 @@ class NonterminalActions:
|
|||||||
self.closure_walk(node, collection_index=4)
|
self.closure_walk(node, collection_index=4)
|
||||||
self.is_lambda = is_lambda
|
self.is_lambda = is_lambda
|
||||||
else:
|
else:
|
||||||
# Python 3.7+ adds optional "come_froms" at node[0] so count from the end
|
# Python 3.7+ adds optional "come_froms" at node[0] so count from
|
||||||
|
# the end.
|
||||||
if node == "generator_exp_async" and self.version[:2] == (3, 6):
|
if node == "generator_exp_async" and self.version[:2] == (3, 6):
|
||||||
code_index = 0
|
code_index = 0
|
||||||
else:
|
else:
|
||||||
code_index = -6
|
code_index = -6
|
||||||
iter_index = 4 if self.version < (3, 8) else 3
|
iter_index = (
|
||||||
self.comprehension_walk(node, iter_index=iter_index, code_index=code_index)
|
4
|
||||||
|
if self.version < (3, 8) and not isinstance(node[4], Token)
|
||||||
|
else 3
|
||||||
|
)
|
||||||
|
self.comprehension_walk(
|
||||||
|
node, iter_index=iter_index, code_index=code_index
|
||||||
|
)
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
@@ -1028,7 +1038,6 @@ class NonterminalActions:
|
|||||||
self.prune()
|
self.prune()
|
||||||
|
|
||||||
def n_mkfunc(self, node):
|
def n_mkfunc(self, node):
|
||||||
|
|
||||||
code_node = find_code_node(node, -2)
|
code_node = find_code_node(node, -2)
|
||||||
code = code_node.attr
|
code = code_node.attr
|
||||||
self.write(code.co_name)
|
self.write(code.co_name)
|
||||||
@@ -1076,7 +1085,10 @@ class NonterminalActions:
|
|||||||
else:
|
else:
|
||||||
# We can't comment out like above because there may be a trailing ')'
|
# We can't comment out like above because there may be a trailing ')'
|
||||||
# that needs to be written
|
# that needs to be written
|
||||||
assert len(node) == 3 and node[2] in ("RETURN_VALUE_LAMBDA", "LAMBDA_MARKER")
|
assert len(node) == 3 and node[2] in (
|
||||||
|
"RETURN_VALUE_LAMBDA",
|
||||||
|
"LAMBDA_MARKER",
|
||||||
|
)
|
||||||
self.preorder(node[0])
|
self.preorder(node[0])
|
||||||
self.prune()
|
self.prune()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user