forked from ethanchewy/PythonBuddy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgensupp.py
More file actions
118 lines (106 loc) · 4.32 KB
/
gensupp.py
File metadata and controls
118 lines (106 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""
Some support for genxxx implementations of source generators.
Another name could be genEric, but well...
"""
def uniquemodulename(name, SEEN=set()):
# never reuse the same module name within a Python session!
i = 0
while True:
i += 1
result = '%s_%d' % (name, i)
if result not in SEEN:
SEEN.add(result)
return result
# a translation table suitable for str.translate() to remove
# non-C characters from an identifier
C_IDENTIFIER = ''.join([(('0' <= chr(i) <= '9' or
'a' <= chr(i) <= 'z' or
'A' <= chr(i) <= 'Z') and chr(i) or '_')
for i in range(256)])
# a name manager knows about all global and local names in the
# program and keeps them disjoint. It provides ways to generate
# shorter local names with and without wrapping prefixes,
# while always keeping all globals visible.
class NameManager(object):
def __init__(self, global_prefix='', number_sep='_'):
self.seennames = {}
self.scope = 0
self.scopelist = []
self.global_prefix = global_prefix
self.number_sep = number_sep
def make_reserved_names(self, txt):
"""add names to list of known names. If one exists already,
then we raise an exception. This function should be called
before generating any new names."""
for name in txt.split():
if name in self.seennames:
raise NameError("%s has already been seen!")
self.seennames[name] = 1
def _ensure_unique(self, basename):
n = self.seennames.get(basename, 0)
self.seennames[basename] = n+1
if n:
return self._ensure_unique('%s_%d' % (basename, n))
return basename
def uniquename(self, basename, with_number=None, bare=False, lenmax=50):
basename = basename[:lenmax].translate(C_IDENTIFIER)
n = self.seennames.get(basename, 0)
self.seennames[basename] = n+1
if with_number is None:
with_number = basename in ('v', 'w_')
fmt = '%%s%s%%d' % self.number_sep
if with_number and not basename[-1].isdigit():
fmt = '%s%d'
if n != 0 or with_number:
basename = self._ensure_unique(fmt % (basename, n))
if bare:
return basename, self.global_prefix + basename
else:
return self.global_prefix + basename
def localScope(self, parent=None):
ret = _LocalScope(self, parent)
while ret.scope >= len(self.scopelist):
self.scopelist.append({})
return ret
class _LocalScope(object):
"""track local names without hiding globals or nested locals"""
def __init__(self, glob, parent):
self.glob = glob
if not parent:
parent = glob
self.parent = parent
self.mapping = {}
self.usednames = {}
self.scope = parent.scope + 1
def uniquename(self, basename):
basename = basename.translate(C_IDENTIFIER)
glob = self.glob
p = self.usednames.get(basename, 0)
self.usednames[basename] = p+1
namesbyscope = glob.scopelist[self.scope]
namelist = namesbyscope.setdefault(basename, [])
if p == len(namelist):
namelist.append(glob.uniquename(basename))
return namelist[p]
def localname(self, name, wrapped=False):
"""modify and mangle local names"""
if name in self.mapping:
return self.mapping[name]
scorepos = name.rfind("_")
if name.startswith("v") and name[1:].isdigit():
basename = ('v', 'w_') [wrapped]
elif scorepos >= 0 and name[scorepos+1:].isdigit():
basename = name[:scorepos]
# for wrapped named things, prepend a w_
# for other named things, prepend a l_.
# XXX The latter is needed because tcc has a nasty parser bug that
# produces errors if names co-incide with global typedefs,
# if the type prefix is itself a typedef reference!
# XXX report this bug to the tcc maintainer(s)
# YYY drop this comment afterwards, but keep the code, it's better.
basename = ("l_", "w_")[wrapped] + basename
else:
basename = name
ret = self.uniquename(basename)
self.mapping[name] = ret
return ret