diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index aceb4f1a..a41e3add 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -483,34 +483,15 @@ class Python3Parser(PythonParser): token.kind = self.call_fn_name(token) uniq_param = args_kw + args_pos - if self.version == 3.5 and opname.startswith('CALL_FUNCTION_VAR'): - # Python 3.5 changes the stack position of *args. KW args come - # after *args. - # Python 3.6+ replaces CALL_FUNCTION_VAR_KW with CALL_FUNCTION_EX - if opname.endswith('KW'): - kw = 'expr ' - else: - kw = '' - rule = ('call ::= expr expr ' + - ('pos_arg ' * args_pos) + - ('kwarg ' * args_kw) + kw + token.kind) - self.add_unique_rule(rule, token.kind, uniq_param, customize) - else: - rule = ('call ::= expr ' + + + # Note: 3.5+ have subclassed this method; so we don't handle + # 'CALL_FUNCTION_VAR' or 'CALL_FUNCTION_EX' here. + rule = ('call ::= expr ' + ('pos_arg ' * args_pos) + ('kwarg ' * args_kw) + 'expr ' * nak + token.kind) - self.add_unique_rule(rule, token.kind, uniq_param, customize) - - if self.version >= 3.5 and seen_GET_AWAITABLE_YIELD_FROM: - rule = ('async_call ::= expr ' + - ('pos_arg ' * args_pos) + - ('kwarg ' * args_kw) + - 'expr ' * nak + token.kind + - ' GET_AWAITABLE LOAD_CONST YIELD_FROM') - self.add_unique_rule(rule, token.kind, uniq_param, customize) - self.add_unique_rule('expr ::= async_call', token.kind, uniq_param, customize) + self.add_unique_rule(rule, token.kind, uniq_param, customize) if possible_class_decorator: if next_token == 'CALL_FUNCTION' and next_token.attr == 1: diff --git a/uncompyle6/parsers/parse35.py b/uncompyle6/parsers/parse35.py index 7620f49d..a53e3187 100644 --- a/uncompyle6/parsers/parse35.py +++ b/uncompyle6/parsers/parse35.py @@ -187,6 +187,52 @@ class Python35Parser(Python34Parser): pass return + def custom_classfunc_rule(self, opname, token, customize, + seen_LOAD_BUILD_CLASS, + seen_GET_AWAITABLE_YIELD_FROM, + *args): + args_pos, args_kw = self.get_pos_kw(token) + + # Additional exprs for * and ** args: + # 0 if neither + # 1 for CALL_FUNCTION_VAR or CALL_FUNCTION_KW + # 2 for * and ** args (CALL_FUNCTION_VAR_KW). + # 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 + + if seen_GET_AWAITABLE_YIELD_FROM: + rule = ('async_call ::= expr ' + + ('pos_arg ' * args_pos) + + ('kwarg ' * args_kw) + + 'expr ' * nak + token.kind + + ' GET_AWAITABLE LOAD_CONST YIELD_FROM') + self.add_unique_rule(rule, token.kind, uniq_param, customize) + self.add_unique_rule('expr ::= async_call', token.kind, uniq_param, customize) + + uniq_param = args_kw + args_pos + if opname.startswith('CALL_FUNCTION_VAR'): + # Python 3.5 changes the stack position of *args. KW args come + # after *args. + + # Note: Python 3.6+ replaces CALL_FUNCTION_VAR and + # CALL_FUNCTION_VAR_KW with CALL_FUNCTION_EX + + token.kind = self.call_fn_name(token) + if opname.endswith('KW'): + kw = 'expr ' + else: + kw = '' + rule = ('call ::= expr expr ' + + ('pos_arg ' * args_pos) + + ('kwarg ' * args_kw) + kw + token.kind) + self.add_unique_rule(rule, token.kind, uniq_param, customize) + else: + super(Python35Parser, self).custom_classfunc_rule(opname, token, customize, + seen_LOAD_BUILD_CLASS, + seen_GET_AWAITABLE_YIELD_FROM, + *args) + class Python35ParserSingle(Python35Parser, PythonParserSingle): pass diff --git a/uncompyle6/parsers/parse36.py b/uncompyle6/parsers/parse36.py index c4f0c81f..9e809b4b 100644 --- a/uncompyle6/parsers/parse36.py +++ b/uncompyle6/parsers/parse36.py @@ -132,6 +132,26 @@ class Python36Parser(Python35Parser): def custom_classfunc_rule(self, opname, token, customize, possible_class_decorator, seen_GET_AWAITABLE_YIELD_FROM, next_token): + + args_pos, args_kw = self.get_pos_kw(token) + + # Additional exprs for * and ** args: + # 0 if neither + # 1 for CALL_FUNCTION_VAR or CALL_FUNCTION_KW + # 2 for * and ** args (CALL_FUNCTION_VAR_KW). + # 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 + + if seen_GET_AWAITABLE_YIELD_FROM: + rule = ('async_call ::= expr ' + + ('pos_arg ' * args_pos) + + ('kwarg ' * args_kw) + + 'expr ' * nak + token.kind + + ' GET_AWAITABLE LOAD_CONST YIELD_FROM') + self.add_unique_rule(rule, token.kind, uniq_param, customize) + self.add_unique_rule('expr ::= async_call', token.kind, uniq_param, customize) + if opname.startswith('CALL_FUNCTION_KW'): self.addRule("expr ::= call_kw", nop_func) values = 'expr ' * token.attr