Python 3.6 CALL_FUNCTION_EX first attempt

This commit is contained in:
rocky
2017-04-25 07:31:01 -04:00
parent 50687e6317
commit 84fd71b73b
7 changed files with 42 additions and 11 deletions

Binary file not shown.

View File

@@ -0,0 +1,5 @@
# Python 3.6's changes for calling functions.
# See https://github.com/rocky/python-uncompyle6/issues/58
# CALL_FUNCTION_EX takes 2 to 3 arguments on the stack: the function, the tuple of positional arguments,
# and optionally the dict of keyword arguments if bit 0 of oparg is 1.
a(*[])

View File

@@ -26,12 +26,16 @@ class Python36Parser(Python35Parser):
withstmt ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK LOAD_CONST
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
call_function ::= expr expr CALL_FUNCTION_EX
call_function ::= expr expr expr CALL_FUNCTION_EX_KW
"""
def add_custom_rules(self, tokens, customize):
super(Python36Parser, self).add_custom_rules(tokens, customize)
for i, token in enumerate(tokens):
opname = token.type
if opname == 'FORMAT_VALUE':
rules_str = """
expr ::= fstring_single

View File

@@ -1,8 +1,8 @@
# Copyright (c) 2016 by Rocky Bernstein
"""
Python 3.5 bytecode scanner/deparser
Python 3.6 bytecode scanner/deparser
This sets up opcodes Python's 3.5 and calls a generalized
This sets up opcodes Python's 3.6 and calls a generalized
scanner routine for Python 3.
"""
@@ -19,6 +19,18 @@ class Scanner36(Scanner3):
def __init__(self, show_asm=None):
Scanner3.__init__(self, 3.6, show_asm)
return
def ingest(self, co, classname=None, code_objects={}, show_asm=None):
tokens, customize = Scanner3.ingest(self, co, classname, code_objects, show_asm)
for t in tokens:
# The lowest bit of flags indicates whether the
# var-keyword argument is placed at the top of the stack
if t.op == self.opc.CALL_FUNCTION_EX and t.attr & 1:
t.type = 'CALL_FUNCTION_EX_KW'
pass
pass
return tokens, customize
pass
if __name__ == "__main__":

View File

@@ -393,7 +393,11 @@ class SourceWalker(GenericASTTraversal, object):
'fstring_multi': ( "f'%c'", 0),
'func_args36': ( "%c(**", 0),
})
TABLE_R.update({
'CALL_FUNCTION_EX': ('%c(*%P)', 0, (1, 2, ', ', 100)),
# Not quite right
'CALL_FUNCTION_EX_KW': ('%c%c *%c', 0, 1, 2)
})
FSTRING_CONVERSION_MAP = {1: '!s', 2: '!r', 3: '!a'}
def f_conversion(node):
@@ -1698,6 +1702,7 @@ class SourceWalker(GenericASTTraversal, object):
self.prec = p
arg += 1
elif typ == 'C':
try:
low, high, sep = entry[arg]
remaining = len(node[low:high])
for subnode in node[low:high]:
@@ -1705,7 +1710,12 @@ class SourceWalker(GenericASTTraversal, object):
remaining -= 1
if remaining > 0:
self.write(sep)
pass
pass
arg += 1
except:
from trepan.api import debug; debug()
pass
elif typ == 'D':
low, high, sep = entry[arg]
remaining = len(node[low:high])