%PDF- %PDF-
| Direktori : /lib/python3/dist-packages/pythran/transformations/ |
| Current File : //lib/python3/dist-packages/pythran/transformations/false_polymorphism.py |
""" FalsePolymorphism try to rename variable to avoid false polymorphism."""
from pythran.passmanager import Transformation
from pythran.analyses import DefUseChains, UseDefChains, Identifiers
import gast as ast
class FalsePolymorphism(Transformation):
"""
Rename variable when possible to avoid false polymorphism.
>>> import gast as ast
>>> from pythran import passmanager, backend
>>> node = ast.parse("def foo(): a = 12; a = 'babar'")
>>> pm = passmanager.PassManager("test")
>>> _, node = pm.apply(FalsePolymorphism, node)
>>> print(pm.dump(backend.Python, node))
def foo():
a = 12
a_ = 'babar'
"""
def __init__(self):
super(FalsePolymorphism, self).__init__(DefUseChains, UseDefChains)
def visit_FunctionDef(self, node):
# reset available identifier names
# removing local identifiers from the list so that first occurrence can
# actually use the slot
identifiers = self.gather(Identifiers, node)
for def_ in self.def_use_chains.locals[node]:
try:
identifiers.remove(def_.name())
except KeyError:
pass
# compute all reachable nodes from each def. This builds a bag of def
# that should have the same name
visited_defs = set()
for def_ in self.def_use_chains.locals[node]:
if def_ in visited_defs:
continue
associated_defs = set()
# fill the bag of associated defs, going through users and defs
to_process = [def_]
while to_process:
curr = to_process.pop()
if curr in associated_defs:
continue
if curr.name() != def_.name():
continue
associated_defs.add(curr)
for u in curr.users():
to_process.append(u)
curr_udc = (d for d in self.use_def_chains.get(curr.node, [])
if isinstance(d.node, ast.Name))
to_process.extend(curr_udc)
visited_defs.update(associated_defs)
# find a new identifier
local_identifier = def_.name()
name = local_identifier
while name in identifiers:
name += "_"
identifiers.add(name)
# don't rename first candidate
if name == local_identifier:
continue
# actual renaming of each node in the bag
self.update = True
for d in associated_defs:
dn = d.node
if isinstance(dn, ast.Name) and dn.id == local_identifier:
dn.id = name
return node