Compare commits

...

11 Commits

Author SHA1 Message Date
rocky
7c99564640 Reinstate pos_args in CALL_METHOD 2023-01-18 21:01:11 -05:00
rocky
931abc5726 self.opc.version -> self.opc.version_tuple
The next release of xdis will no longer support self.opc.version (a
float value which doesn't work in the presense of 3.10 and above)
2023-01-18 17:08:39 -05:00
rocky
2b3cd696db 3.0 set comprehension bug 2023-01-16 03:50:50 -05:00
rocky
50697bb79e Improve set comprehension for Python 3.0 2023-01-16 03:40:55 -05:00
R. Bernstein
137dd64a46 Merge pull request #427 from rocky/make-fn-or-closure-with-annotatation
try to be more honest about MAKE_{FUNCTION,CLOSURE}
2023-01-16 02:12:13 -05:00
rocky
9a7eb0ad0a try to be more honest about MAKE_{FUNCTION,CLOSURE} 2023-01-16 01:45:37 -05:00
rocky
154dabfcef Handle Python 3.4 MAKE_CLOSURE fns ...
Is done just like Python 3.3
2023-01-14 09:54:48 -05:00
rocky
42d26ccbd7 Bump version 2023-01-14 06:21:12 -05:00
rocky
73a4c0be78 Use 3.7.16 for master version 2023-01-14 02:49:43 -05:00
rocky
92830c2eae Newer setuptools 2023-01-14 02:22:53 -05:00
rocky
090570cd34 3.4-3.5 MAKE_CLOSURE with annotate
Docs lie about annnotation args. Slight adjustment here.
More is probably needed.
2023-01-14 02:20:59 -05:00
16 changed files with 176 additions and 115 deletions

View File

@@ -1,5 +1,5 @@
#!/bin/bash
PYTHON_VERSION=3.7.14
PYTHON_VERSION=3.7.16
function checkout_version {
local repo=$1

View File

@@ -6,4 +6,4 @@ pytest
Click~=7.0
xdis>=6.0.4
configobj~=5.0.6
setuptools~=65.3.0
setuptools~=65.5.1

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,18 @@
# Related to #426
# This file is RUNNABLE!
"""This program is self-checking!"""
a = 5
class MakeClosureTest():
# This function uses MAKE_CLOSURE with annotation args
def __init__(self, dev: str, b: bool):
super().__init__()
self.dev = dev
self.b = b
self.a = a
x = MakeClosureTest("dev", True)
assert x.dev == "dev"
assert x.b == True
assert x.a == 5

View File

@@ -199,7 +199,7 @@ class PythonParser(GenericASTBuilder):
if instructions[finish].linestart:
break
pass
if start > 0:
if start >= 0:
err_token = instructions[index]
print("Instruction context:")
for i in range(start, finish):
@@ -213,10 +213,16 @@ class PythonParser(GenericASTBuilder):
raise ParserError(None, -1, self.debug["reduce"])
def get_pos_kw(self, token):
"""Return then the number of positional parameters and
represented by the attr field of token"""
"""
Return then the number of positional parameters and keyword
parfameters represented by the attr (operand) field of
token.
This appears in CALL_FUNCTION or CALL_METHOD (PyPy) tokens
"""
# Low byte indicates number of positional paramters,
# high byte number of keyword parameters
assert token.kind.startswith("CALL_FUNCTION") or token.kind.startswith("CALL_METHOD")
args_pos = token.attr & 0xFF
args_kw = (token.attr >> 8) & 0xFF
return args_pos, args_kw

View File

@@ -541,9 +541,9 @@ class Python3Parser(PythonParser):
# token found, while this one doesn't.
if self.version < (3, 6):
call_function = self.call_fn_name(call_fn_tok)
args_pos, args_kw = self.get_pos_kw(call_fn_tok)
pos_args_count, kw_args_count = self.get_pos_kw(call_fn_tok)
rule = "build_class ::= LOAD_BUILD_CLASS mkfunc %s" "%s" % (
("expr " * (args_pos - 1) + ("kwarg " * args_kw)),
("expr " * (pos_args_count - 1) + ("kwarg " * kw_args_count)),
call_function,
)
else:
@@ -552,10 +552,10 @@ class Python3Parser(PythonParser):
if call_function.startswith("CALL_FUNCTION_KW"):
self.addRule("classdef ::= build_class_kw store", nop_func)
if is_pypy:
args_pos, args_kw = self.get_pos_kw(call_fn_tok)
pos_args_count, kw_args_count = self.get_pos_kw(call_fn_tok)
rule = "build_class_kw ::= LOAD_BUILD_CLASS mkfunc %s%s%s" % (
"expr " * (args_pos - 1),
"kwarg " * (args_kw),
"expr " * (pos_args_count - 1),
"kwarg " * (kw_args_count),
call_function,
)
else:
@@ -581,7 +581,7 @@ class Python3Parser(PythonParser):
classdefdeco2 ::= LOAD_BUILD_CLASS mkfunc {expr}^n-1 CALL_FUNCTION_n
"""
args_pos, args_kw = self.get_pos_kw(token)
pos_args_count, kw_args_count = self.get_pos_kw(token)
# Additional exprs for * and ** args:
# 0 if neither
@@ -590,7 +590,7 @@ class Python3Parser(PythonParser):
# Yes, this computation based on instruction name is a little bit hoaky.
nak = (len(opname) - len("CALL_FUNCTION")) // 3
uniq_param = args_kw + args_pos
uniq_param = kw_args_count + pos_args_count
# Note: 3.5+ have subclassed this method; so we don't handle
# 'CALL_FUNCTION_VAR' or 'CALL_FUNCTION_EX' here.
@@ -599,16 +599,16 @@ class Python3Parser(PythonParser):
token.kind = self.call_fn_name(token)
rule = (
"call ::= expr "
+ ("pos_arg " * args_pos)
+ ("kwarg " * args_kw)
+ ("pos_arg " * pos_args_count)
+ ("kwarg " * kw_args_count)
+ token.kind
)
else:
token.kind = self.call_fn_name(token)
rule = (
"call ::= expr "
+ ("pos_arg " * args_pos)
+ ("kwarg " * args_kw)
+ ("pos_arg " * pos_args_count)
+ ("kwarg " * kw_args_count)
+ "expr " * nak
+ token.kind
)
@@ -616,11 +616,11 @@ class Python3Parser(PythonParser):
self.add_unique_rule(rule, token.kind, uniq_param, customize)
if "LOAD_BUILD_CLASS" in self.seen_ops:
if next_token == "CALL_FUNCTION" and next_token.attr == 1 and args_pos > 1:
if next_token == "CALL_FUNCTION" and next_token.attr == 1 and pos_args_count > 1:
rule = "classdefdeco2 ::= LOAD_BUILD_CLASS mkfunc %s%s_%d" % (
("expr " * (args_pos - 1)),
("expr " * (pos_args_count - 1)),
opname,
args_pos,
pos_args_count,
)
self.add_unique_rule(rule, token.kind, uniq_param, customize)
@@ -845,18 +845,18 @@ class Python3Parser(PythonParser):
elif opname in ("BUILD_CONST_LIST", "BUILD_CONST_DICT", "BUILD_CONST_SET"):
if opname == "BUILD_CONST_DICT":
rule = f"""
rule = """
add_consts ::= ADD_VALUE*
const_list ::= COLLECTION_START add_consts {opname}
const_list ::= COLLECTION_START add_consts %s
dict ::= const_list
expr ::= dict
"""
""" % opname
else:
rule = f"""
rule = """
add_consts ::= ADD_VALUE*
const_list ::= COLLECTION_START add_consts {opname}
const_list ::= COLLECTION_START add_consts %s
expr ::= const_list
"""
""" % opname
self.addRule(rule, nop_func)
elif opname_base in (
@@ -955,14 +955,14 @@ class Python3Parser(PythonParser):
elif opname_base == "CALL_METHOD":
# PyPy and Python 3.7+ only - DRY with parse2
args_pos, args_kw = self.get_pos_kw(token)
pos_args_count, kw_args_count = self.get_pos_kw(token)
# number of apply equiv arguments:
nak = (len(opname_base) - len("CALL_METHOD")) // 3
rule = (
"call ::= expr "
+ ("pos_arg " * args_pos)
+ ("kwarg " * args_kw)
+ ("pos_arg " * pos_args_count)
+ ("kwarg " * kw_args_count)
+ "expr " * nak
+ opname
)
@@ -1096,7 +1096,7 @@ class Python3Parser(PythonParser):
"""
self.addRule(rule, nop_func)
args_pos, args_kw, annotate_args = token.attr
pos_args_count, kw_args_count, annotate_args = token.attr
# FIXME: Fold test into add_make_function_rule
if self.version < (3, 3):
@@ -1105,7 +1105,7 @@ class Python3Parser(PythonParser):
j = 2
if self.is_pypy or (i >= j and tokens[i - j] == "LOAD_LAMBDA"):
rule_pat = "lambda_body ::= %sload_closure LOAD_LAMBDA %%s%s" % (
"pos_arg " * args_pos,
"pos_arg " * pos_args_count,
opname,
)
self.add_make_function_rule(rule_pat, opname, token.attr, customize)
@@ -1113,7 +1113,7 @@ class Python3Parser(PythonParser):
if has_get_iter_call_function1:
rule_pat = (
"generator_exp ::= %sload_closure load_genexpr %%s%s expr "
"GET_ITER CALL_FUNCTION_1" % ("pos_arg " * args_pos, opname)
"GET_ITER CALL_FUNCTION_1" % ("pos_arg " * pos_args_count, opname)
)
self.add_make_function_rule(rule_pat, opname, token.attr, customize)
@@ -1129,7 +1129,7 @@ class Python3Parser(PythonParser):
rule_pat = (
"listcomp ::= %sload_closure LOAD_LISTCOMP %%s%s expr "
"GET_ITER CALL_FUNCTION_1"
% ("pos_arg " * args_pos, opname)
% ("pos_arg " * pos_args_count, opname)
)
self.add_make_function_rule(
rule_pat, opname, token.attr, customize
@@ -1138,7 +1138,7 @@ class Python3Parser(PythonParser):
rule_pat = (
"set_comp ::= %sload_closure LOAD_SETCOMP %%s%s expr "
"GET_ITER CALL_FUNCTION_1"
% ("pos_arg " * args_pos, opname)
% ("pos_arg " * pos_args_count, opname)
)
self.add_make_function_rule(
rule_pat, opname, token.attr, customize
@@ -1149,13 +1149,13 @@ class Python3Parser(PythonParser):
self.add_unique_rule(
"dict_comp ::= %sload_closure LOAD_DICTCOMP %s "
"expr GET_ITER CALL_FUNCTION_1"
% ("pos_arg " * args_pos, opname),
% ("pos_arg " * pos_args_count, opname),
opname,
token.attr,
customize,
)
if args_kw > 0:
if kw_args_count > 0:
kwargs_str = "kwargs "
else:
kwargs_str = ""
@@ -1167,36 +1167,40 @@ class Python3Parser(PythonParser):
"mkfunc_annotate ::= %s%s%sannotate_tuple load_closure LOAD_CODE %s"
% (
kwargs_str,
"pos_arg " * args_pos,
"annotate_arg " * (annotate_args - 1),
"pos_arg " * pos_args_count,
"annotate_arg " * (annotate_args),
opname,
)
)
else:
rule = "mkfunc ::= %s%sload_closure LOAD_CODE %s" % (
kwargs_str,
"pos_arg " * args_pos,
"pos_arg " * pos_args_count,
opname,
)
elif self.version == (3, 3):
self.add_unique_rule(rule, opname, token.attr, customize)
elif (3, 3) <= self.version < (3, 6):
if annotate_args > 0:
rule = (
"mkfunc_annotate ::= %s%s%sannotate_tuple load_closure LOAD_CODE LOAD_STR %s"
% (
kwargs_str,
"pos_arg " * args_pos,
"annotate_arg " * (annotate_args - 1),
"pos_arg " * pos_args_count,
"annotate_arg " * (annotate_args),
opname,
)
)
else:
rule = "mkfunc ::= %s%sload_closure LOAD_CODE LOAD_STR %s" % (
kwargs_str,
"pos_arg " * args_pos,
"pos_arg " * pos_args_count,
opname,
)
self.add_unique_rule(rule, opname, token.attr, customize)
elif self.version >= (3, 4):
if self.version >= (3, 4):
if not self.is_pypy:
load_op = "LOAD_STR"
else:
@@ -1206,33 +1210,33 @@ class Python3Parser(PythonParser):
rule = (
"mkfunc_annotate ::= %s%s%sannotate_tuple load_closure %s %s"
% (
"pos_arg " * args_pos,
"pos_arg " * pos_args_count,
kwargs_str,
"annotate_arg " * (annotate_args - 1),
"annotate_arg " * (annotate_args),
load_op,
opname,
)
)
else:
rule = "mkfunc ::= %s%s load_closure LOAD_CODE %s %s" % (
"pos_arg " * args_pos,
"pos_arg " * pos_args_count,
kwargs_str,
load_op,
opname,
)
self.add_unique_rule(rule, opname, token.attr, customize)
self.add_unique_rule(rule, opname, token.attr, customize)
if args_kw == 0:
if kw_args_count == 0:
rule = "mkfunc ::= %sload_closure load_genexpr %s" % (
"pos_arg " * args_pos,
"pos_arg " * pos_args_count,
opname,
)
self.add_unique_rule(rule, opname, token.attr, customize)
if self.version < (3, 4):
rule = "mkfunc ::= %sload_closure LOAD_CODE %s" % (
"expr " * args_pos,
"expr " * pos_args_count,
opname,
)
self.add_unique_rule(rule, opname, token.attr, customize)
@@ -1243,10 +1247,10 @@ class Python3Parser(PythonParser):
if self.version >= (3, 6):
# The semantics of MAKE_FUNCTION in 3.6 are totally different from
# before.
args_pos, args_kw, annotate_args, closure = token.attr
stack_count = args_pos + args_kw + annotate_args
pos_args_count, kw_args_count, annotate_args, closure = token.attr
stack_count = pos_args_count + kw_args_count + annotate_args
if closure:
if args_pos:
if pos_args_count:
rule = "lambda_body ::= %s%s%s%s" % (
"expr " * stack_count,
"load_closure " * closure,
@@ -1279,14 +1283,14 @@ class Python3Parser(PythonParser):
if has_get_iter_call_function1:
rule_pat = (
"generator_exp ::= %sload_genexpr %%s%s expr "
"GET_ITER CALL_FUNCTION_1" % ("pos_arg " * args_pos, opname)
"GET_ITER CALL_FUNCTION_1" % ("pos_arg " * pos_args_count, opname)
)
self.add_make_function_rule(
rule_pat, opname, token.attr, customize
)
rule_pat = (
"generator_exp ::= %sload_closure load_genexpr %%s%s expr "
"GET_ITER CALL_FUNCTION_1" % ("pos_arg " * args_pos, opname)
"GET_ITER CALL_FUNCTION_1" % ("pos_arg " * pos_args_count, opname)
)
self.add_make_function_rule(
rule_pat, opname, token.attr, customize
@@ -1308,7 +1312,7 @@ class Python3Parser(PythonParser):
rule_pat = (
"listcomp ::= %sLOAD_LISTCOMP %%s%s expr "
"GET_ITER CALL_FUNCTION_1"
% ("expr " * args_pos, opname)
% ("expr " * pos_args_count, opname)
)
self.add_make_function_rule(
rule_pat, opname, token.attr, customize
@@ -1316,8 +1320,8 @@ class Python3Parser(PythonParser):
if self.is_pypy or (i >= 2 and tokens[i - 2] == "LOAD_LAMBDA"):
rule_pat = "lambda_body ::= %s%sLOAD_LAMBDA %%s%s" % (
("pos_arg " * args_pos),
("kwarg " * args_kw),
("pos_arg " * pos_args_count),
("kwarg " * kw_args_count),
opname,
)
self.add_make_function_rule(
@@ -1326,9 +1330,9 @@ class Python3Parser(PythonParser):
continue
if self.version < (3, 6):
args_pos, args_kw, annotate_args = token.attr
pos_args_count, kw_args_count, annotate_args = token.attr
else:
args_pos, args_kw, annotate_args, closure = token.attr
pos_args_count, kw_args_count, annotate_args, closure = token.attr
if self.version < (3, 3):
j = 1
@@ -1338,7 +1342,7 @@ class Python3Parser(PythonParser):
if has_get_iter_call_function1:
rule_pat = (
"generator_exp ::= %sload_genexpr %%s%s expr "
"GET_ITER CALL_FUNCTION_1" % ("pos_arg " * args_pos, opname)
"GET_ITER CALL_FUNCTION_1" % ("pos_arg " * pos_args_count, opname)
)
self.add_make_function_rule(rule_pat, opname, token.attr, customize)
@@ -1350,7 +1354,7 @@ class Python3Parser(PythonParser):
# Todo: For Pypy we need to modify this slightly
rule_pat = (
"listcomp ::= %sLOAD_LISTCOMP %%s%s expr "
"GET_ITER CALL_FUNCTION_1" % ("expr " * args_pos, opname)
"GET_ITER CALL_FUNCTION_1" % ("expr " * pos_args_count, opname)
)
self.add_make_function_rule(
rule_pat, opname, token.attr, customize
@@ -1359,13 +1363,13 @@ class Python3Parser(PythonParser):
# FIXME: Fold test into add_make_function_rule
if self.is_pypy or (i >= j and tokens[i - j] == "LOAD_LAMBDA"):
rule_pat = "lambda_body ::= %s%sLOAD_LAMBDA %%s%s" % (
("pos_arg " * args_pos),
("kwarg " * args_kw),
("pos_arg " * pos_args_count),
("kwarg " * kw_args_count),
opname,
)
self.add_make_function_rule(rule_pat, opname, token.attr, customize)
if args_kw == 0:
if kw_args_count == 0:
kwargs = "no_kwargs"
self.add_unique_rule("no_kwargs ::=", opname, token.attr, customize)
else:
@@ -1375,13 +1379,13 @@ class Python3Parser(PythonParser):
# positional args after keyword args
rule = "mkfunc ::= %s %s%s%s" % (
kwargs,
"pos_arg " * args_pos,
"pos_arg " * pos_args_count,
"LOAD_CODE ",
opname,
)
self.add_unique_rule(rule, opname, token.attr, customize)
rule = "mkfunc ::= %s%s%s" % (
"pos_arg " * args_pos,
"pos_arg " * pos_args_count,
"LOAD_CODE ",
opname,
)
@@ -1389,14 +1393,14 @@ class Python3Parser(PythonParser):
# positional args after keyword args
rule = "mkfunc ::= %s %s%s%s" % (
kwargs,
"pos_arg " * args_pos,
"pos_arg " * pos_args_count,
"LOAD_CODE LOAD_STR ",
opname,
)
elif self.version >= (3, 6):
# positional args before keyword args
rule = "mkfunc ::= %s%s %s%s" % (
"pos_arg " * args_pos,
"pos_arg " * pos_args_count,
kwargs,
"LOAD_CODE LOAD_STR ",
opname,
@@ -1404,7 +1408,7 @@ class Python3Parser(PythonParser):
elif self.version >= (3, 4):
# positional args before keyword args
rule = "mkfunc ::= %s%s %s%s" % (
"pos_arg " * args_pos,
"pos_arg " * pos_args_count,
kwargs,
"LOAD_CODE LOAD_STR ",
opname,
@@ -1412,7 +1416,7 @@ class Python3Parser(PythonParser):
else:
rule = "mkfunc ::= %s%sexpr %s" % (
kwargs,
"pos_arg " * args_pos,
"pos_arg " * pos_args_count,
opname,
)
self.add_unique_rule(rule, opname, token.attr, customize)
@@ -1422,8 +1426,8 @@ class Python3Parser(PythonParser):
rule = (
"mkfunc_annotate ::= %s%sannotate_tuple LOAD_CODE LOAD_STR %s"
% (
("pos_arg " * (args_pos)),
("call " * (annotate_args - 1)),
("pos_arg " * pos_args_count),
("call " * annotate_args),
opname,
)
)
@@ -1431,8 +1435,8 @@ class Python3Parser(PythonParser):
rule = (
"mkfunc_annotate ::= %s%sannotate_tuple LOAD_CODE LOAD_STR %s"
% (
("pos_arg " * (args_pos)),
("annotate_arg " * (annotate_args - 1)),
("pos_arg " * pos_args_count),
("annotate_arg " * annotate_args),
opname,
)
)
@@ -1443,21 +1447,21 @@ class Python3Parser(PythonParser):
if self.version == (3, 3):
# 3.3 puts kwargs before pos_arg
pos_kw_tuple = (
("kwargs " * args_kw),
("pos_arg " * (args_pos)),
("kwargs " * kw_args_count),
("pos_arg " * pos_args_count),
)
else:
# 3.4 and 3.5puts pos_arg before kwargs
pos_kw_tuple = (
"pos_arg " * (args_pos),
("kwargs " * args_kw),
"pos_arg " * (pos_args_count),
("kwargs " * kw_args_count),
)
rule = (
"mkfunc_annotate ::= %s%s%sannotate_tuple LOAD_CODE LOAD_STR EXTENDED_ARG %s"
% (
pos_kw_tuple[0],
pos_kw_tuple[1],
("call " * (annotate_args - 1)),
("call " * annotate_args),
opname,
)
)
@@ -1467,7 +1471,7 @@ class Python3Parser(PythonParser):
% (
pos_kw_tuple[0],
pos_kw_tuple[1],
("annotate_arg " * (annotate_args - 1)),
("annotate_arg " * annotate_args),
opname,
)
)
@@ -1476,9 +1480,9 @@ class Python3Parser(PythonParser):
rule = (
"mkfunc_annotate ::= %s%s%sannotate_tuple LOAD_CODE EXTENDED_ARG %s"
% (
("kwargs " * args_kw),
("pos_arg " * (args_pos)),
("annotate_arg " * (annotate_args - 1)),
("kwargs " * kw_args_count),
("pos_arg " * (pos_args_count)),
("annotate_arg " * annotate_args),
opname,
)
)
@@ -1486,9 +1490,9 @@ class Python3Parser(PythonParser):
rule = (
"mkfunc_annotate ::= %s%s%sannotate_tuple LOAD_CODE EXTENDED_ARG %s"
% (
("kwargs " * args_kw),
("pos_arg " * (args_pos)),
("call " * (annotate_args - 1)),
("kwargs " * kw_args_count),
("pos_arg " * pos_args_count),
("call " * annotate_args),
opname,
)
)

View File

@@ -74,8 +74,8 @@ class Python30Parser(Python31Parser):
# Need to keep LOAD_FAST as index 1
set_comp_header ::= BUILD_SET_0 DUP_TOP STORE_FAST
set_comp_func ::= set_comp_header
LOAD_FAST FOR_ITER store comp_iter
JUMP_BACK POP_TOP JUMP_BACK RETURN_VALUE RETURN_LAST
LOAD_ARG FOR_ITER store comp_iter
JUMP_BACK COME_FROM POP_TOP JUMP_BACK RETURN_VALUE RETURN_LAST
list_comp_header ::= BUILD_LIST_0 DUP_TOP STORE_FAST
list_comp ::= list_comp_header

View File

@@ -92,7 +92,7 @@ class Python32Parser(Python3Parser):
"LOAD_CONST LOAD_CODE EXTENDED_ARG %s"
) % (
("pos_arg " * args_pos),
("annotate_arg " * (annotate_args - 1)),
("annotate_arg " * (annotate_args)),
opname,
)
self.add_unique_rule(rule, opname, token.attr, customize)

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2016-2017, 2019-2020, 2022 Rocky Bernstein
# Copyright (c) 2016-2017, 2019-2020, 2022-2023 Rocky Bernstein
"""
Python 3.7 base code. We keep non-custom-generated grammar rules out of this file.
"""
@@ -558,7 +558,7 @@ class Python37BaseParser(PythonParser):
nak = (len(opname_base) - len("CALL_METHOD")) // 3
rule = (
"call ::= expr "
+ ("expr " * args_pos)
+ ("pos_arg " * args_pos)
+ ("kwarg " * args_kw)
+ "expr " * nak
+ opname

View File

@@ -21,7 +21,7 @@ scanner/ingestion module. From here we call various version-specific
scanners, e.g. for Python 2.7 or 3.4.
"""
from typing import Optional
from typing import Optional, Tuple
from array import array
from collections import namedtuple
@@ -600,8 +600,25 @@ class Scanner(object):
return self.Token
def parse_fn_counts(argc):
return ((argc & 0xFF), (argc >> 8) & 0xFF, (argc >> 16) & 0x7FFF)
# TODO: after the next xdis release, use from there instead.
def parse_fn_counts_30_35(argc: int) -> Tuple[int, int, int]:
"""
In Python 3.0 to 3.5 MAKE_CLOSURE and MAKE_FUNCTION encode
arguments counts of positional, default + named, and annotation
arguments a particular kind of encoding where each of
the entry a a packe byted value of the lower 24 bits
of ``argc``. The high bits of argc may have come from
an EXTENDED_ARG instruction. Here, we unpack the values
from the ``argc`` int and return a triple of the
positional args, named_args, and annotation args.
"""
annotate_count = (argc >> 16) & 0x7FFF
# For some reason that I don't understand, annotate_args is off by one
# when there is an EXENDED_ARG instruction from what is documented in
# https://docs.python.org/3.4/library/dis.html#opcode-MAKE_CLOSURE
if annotate_count > 1:
annotate_count -= 1
return ((argc & 0xFF), (argc >> 8) & 0xFF, annotate_count)
def get_scanner(version, is_pypy=False, show_asm=None):

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2015-2019, 2021-2022 by Rocky Bernstein
# Copyright (c) 2015-2019, 2021-2023 by Rocky Bernstein
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
#
@@ -41,7 +41,7 @@ from xdis import iscode, instruction_size, Instruction
from xdis.bytecode import _get_const_info
from uncompyle6.scanners.tok import Token
from uncompyle6.scanner import parse_fn_counts
from uncompyle6.scanner import parse_fn_counts_30_35
import xdis
# Get all the opcodes into globals
@@ -363,7 +363,7 @@ class Scanner3(Scanner):
)
new_tokens.append(
Token(
opname=f"BUILD_DICT_OLDER",
opname="BUILD_DICT_OLDER",
attr=t.attr,
pattr=t.pattr,
offset=t.offset,
@@ -623,23 +623,29 @@ class Scanner3(Scanner):
flags >>= 1
attr = attr[:4] # remove last value: attr[5] == False
else:
pos_args, name_pair_args, annotate_args = parse_fn_counts(
pos_args, name_pair_args, annotate_args = parse_fn_counts_30_35(
inst.argval
)
pattr = "%d positional, %d keyword only, %d annotated" % (
pos_args,
name_pair_args,
annotate_args,
)
if name_pair_args > 0:
)
pattr = f"{pos_args} positional, {name_pair_args} keyword only, {annotate_args} annotated"
if name_pair_args > 0 and annotate_args > 0:
# FIXME: this should probably be K_
opname = "%s_N%d" % (opname, name_pair_args)
opname += f"_N{name_pair_args}_A{annotate_args}"
pass
if annotate_args > 0:
opname = "%s_A_%d" % (opname, annotate_args)
elif annotate_args > 0:
opname += f"_A_{annotate_args}"
pass
opname = "%s_%d" % (opname, pos_args)
elif name_pair_args > 0:
opname += f"_N_{name_pair_args}"
pass
else:
# Rule customization mathics, MAKE_FUNCTION_...
# so make sure to add the "_"
opname += "_0"
attr = (pos_args, name_pair_args, annotate_args)
new_tokens.append(
Token(
opname=opname,

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2016-2021 by Rocky Bernstein
# Copyright (c) 2016-2021, 2023 by Rocky Bernstein
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
# Copyright (c) 1999 John Aycock
#
@@ -180,7 +180,7 @@ class Token:
elif name == "LOAD_ASSERT":
return "%s%s %s" % (prefix, offset_opname, pattr)
elif self.op in self.opc.NAME_OPS:
if self.opc.version >= 3.0:
if self.opc.version_tuple >= (3, 0):
return "%s%s%s %s" % (prefix, offset_opname, argstr, self.attr)
elif name == "EXTENDED_ARG":
return "%s%s%s 0x%x << %s = %s" % (

View File

@@ -466,7 +466,12 @@ class ComprehensionMixin:
self.preorder(n[1])
else:
if self.version == (3, 0):
body = n[1]
if isinstance(n, Token):
body = store
elif len(n) > 1:
body = n[1]
else:
body = n[0]
else:
body = n[0]
self.preorder(body)

View File

@@ -1093,7 +1093,12 @@ class NonterminalActions:
self.write("{")
if node[0] in ["LOAD_SETCOMP", "LOAD_DICTCOMP"]:
if self.version == (3, 0):
iter_index = 6
if len(node) >= 6:
iter_index = 6
else:
assert node[1].kind.startswith("MAKE_FUNCTION")
iter_index = 2
pass
else:
iter_index = 1
self.comprehension_walk_newer(node, iter_index=iter_index, code_index=0)

View File

@@ -14,4 +14,4 @@
# This file is suitable for sourcing inside POSIX shell as
# well as importing into Python
# fmt: off
__version__="3.9.0" # noqa
__version__="3.9.1.dev0" # noqa