2012-01-16 12:09:52 -05:00
|
|
|
import inspect
|
|
|
|
import re
|
|
|
|
from itertools import combinations
|
|
|
|
|
|
|
|
class NoContext:
|
|
|
|
pass
|
|
|
|
|
|
|
|
def trace_back(name=None):
|
|
|
|
l = []
|
|
|
|
frame = inspect.currentframe().f_back.f_back
|
|
|
|
while frame is not None:
|
|
|
|
try:
|
|
|
|
obj = frame.f_locals["self"]
|
|
|
|
except KeyError:
|
|
|
|
obj = None
|
|
|
|
if obj is None or isinstance(obj, NoContext):
|
|
|
|
modules = frame.f_globals["__name__"]
|
|
|
|
modules = modules.split(".")
|
|
|
|
obj = modules[len(modules)-1]
|
|
|
|
|
|
|
|
if name is None:
|
|
|
|
line = inspect.getframeinfo(frame).code_context[0]
|
|
|
|
m = re.match("[\t ]*([0-9A-Za-z_\.]+)[\t ]*=", line)
|
|
|
|
if m is None:
|
|
|
|
name = None
|
|
|
|
else:
|
|
|
|
names = m.group(1).split(".")
|
|
|
|
name = names[len(names)-1]
|
|
|
|
l.insert(0, (obj, name))
|
|
|
|
name = None
|
|
|
|
frame = frame.f_back
|
|
|
|
return l
|
|
|
|
|
|
|
|
def obj_name(obj):
|
|
|
|
if isinstance(obj, str):
|
|
|
|
return obj
|
|
|
|
else:
|
|
|
|
return obj.__class__.__name__.lower()
|
|
|
|
|
|
|
|
class TreeNode:
|
|
|
|
def __init__(self, name):
|
|
|
|
self.name = name
|
|
|
|
self.ids = {}
|
|
|
|
self.children = []
|
|
|
|
self.include_context = False
|
|
|
|
self.include_varname = False
|
|
|
|
|
|
|
|
def add_to_tree(root, backtrace):
|
|
|
|
for step in backtrace:
|
|
|
|
n = obj_name(step[0])
|
|
|
|
found = list(filter(lambda x: x.name == n, root.children))
|
|
|
|
if found:
|
|
|
|
node = found[0]
|
|
|
|
else:
|
|
|
|
node = TreeNode(n)
|
|
|
|
root.children.append(node)
|
|
|
|
if not isinstance(step[0], str) and id(step[0]) not in node.ids:
|
|
|
|
node.ids[id(step[0])] = len(node.ids)
|
|
|
|
root = node
|
|
|
|
|
|
|
|
def build_tree(signals):
|
|
|
|
t = TreeNode("root")
|
|
|
|
for signal in signals:
|
|
|
|
if signal.name_override is None:
|
|
|
|
add_to_tree(t, signal.backtrace)
|
|
|
|
return t
|
|
|
|
|
|
|
|
def name_backtrace(root, backtrace):
|
|
|
|
parts = []
|
2012-01-16 12:42:55 -05:00
|
|
|
for step in backtrace[:-1]:
|
2012-01-16 12:09:52 -05:00
|
|
|
n = obj_name(step[0])
|
|
|
|
found = list(filter(lambda x: x.name == n, root.children))
|
|
|
|
node = found[0]
|
|
|
|
if node.include_context:
|
|
|
|
if len(node.ids) > 1:
|
|
|
|
parts.append(node.name + str(node.ids[id(step[0])]))
|
|
|
|
else:
|
|
|
|
parts.append(node.name)
|
|
|
|
if node.include_varname and step[1] is not None:
|
|
|
|
parts.append(step[1])
|
2012-01-16 12:42:55 -05:00
|
|
|
root = node
|
|
|
|
last = backtrace[-1]
|
|
|
|
if last[1] is not None:
|
|
|
|
parts.append(last[1])
|
|
|
|
else:
|
|
|
|
parts.append(obj_name(last[0]))
|
2012-01-16 12:09:52 -05:00
|
|
|
return "_".join(parts)
|
|
|
|
|
|
|
|
def _include_divergence(root, bt1, bt2):
|
|
|
|
for step1, step2 in zip(bt1, bt2):
|
|
|
|
n1, n2 = obj_name(step1[0]), obj_name(step2[0])
|
2012-01-16 12:42:55 -05:00
|
|
|
node1 = list(filter(lambda x: x.name == n1, root.children))[0]
|
|
|
|
node2 = list(filter(lambda x: x.name == n2, root.children))[0]
|
2012-01-16 12:09:52 -05:00
|
|
|
if node1 != node2:
|
|
|
|
node1.include_context = True
|
|
|
|
node2.include_context = True
|
|
|
|
return
|
|
|
|
if not isinstance(step1[0], str) and not isinstance(step2[0], str) \
|
|
|
|
and id(step1[0]) != id(step2[0]):
|
|
|
|
node1.include_context = True
|
|
|
|
return
|
|
|
|
if step1[1] is not None and step2[1] is not None \
|
|
|
|
and step1[1] != step2[1]:
|
|
|
|
node1.include_varname = True
|
|
|
|
return
|
|
|
|
root = node1
|
|
|
|
|
|
|
|
def resolve_conflicts(root, signals):
|
|
|
|
for s1, s2 in combinations(signals, 2):
|
2012-01-16 12:42:55 -05:00
|
|
|
if name_backtrace(root, s1.backtrace) == name_backtrace(root, s2.backtrace):
|
2012-01-16 12:09:52 -05:00
|
|
|
_include_divergence(root, s1.backtrace, s2.backtrace)
|
|
|
|
|
|
|
|
def build_tree_res(signals):
|
|
|
|
t = build_tree(signals)
|
|
|
|
resolve_conflicts(t, signals)
|
|
|
|
return t
|
|
|
|
|
|
|
|
def signal_name(root, sig):
|
|
|
|
if sig.name_override is not None:
|
|
|
|
return sig.name_override
|
|
|
|
else:
|
|
|
|
return name_backtrace(root, sig.backtrace)
|
|
|
|
|
|
|
|
class Namespace:
|
|
|
|
def __init__(self, tree):
|
|
|
|
self.counts = {}
|
|
|
|
self.sigs = {}
|
|
|
|
self.tree = tree
|
|
|
|
|
|
|
|
def get_name(self, sig):
|
|
|
|
sig_name = signal_name(self.tree, sig)
|
|
|
|
try:
|
|
|
|
n = self.sigs[sig]
|
|
|
|
if n:
|
|
|
|
return sig_name + "_" + str(n)
|
|
|
|
else:
|
|
|
|
return sig_name
|
|
|
|
except KeyError:
|
|
|
|
try:
|
|
|
|
n = self.counts[sig_name]
|
|
|
|
except KeyError:
|
|
|
|
n = 0
|
|
|
|
self.sigs[sig] = n
|
|
|
|
self.counts[sig_name] = n + 1
|
|
|
|
if n:
|
|
|
|
return sig_name + "_" + str(n)
|
|
|
|
else:
|
|
|
|
return sig_name
|