Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c59e220

Browse files
committed
Handle private names
(Hard to believe these were never handled before) Add misc.mangle() that mangles based on the rules in compile.c. XXX Need to test the corner cases Update CodeGenerator with a class_name attribute bound to None. If a particular instance is created within a class scope, the instance's class_name is bound to that class's name. Add mangle() method to CodeGenerator that mangles if the class_name has a class_name in it. Modify the FunctionCodeGenerator family to handle an extra argument-- the class_name. Wrap all name ops and attrnames in calls to self.mangle()
1 parent e7d8322 commit c59e220

6 files changed

Lines changed: 100 additions & 40 deletions

File tree

Lib/compiler/misc.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,26 @@ def push(self, elt):
3939
self.stack.append(elt)
4040
def top(self):
4141
return self.stack[-1]
42+
43+
MANGLE_LEN = 256 # magic constant from compile.c
44+
45+
def mangle(name, klass):
46+
if not name.startswith('__'):
47+
return name
48+
if len(name) + 2 >= MANGLE_LEN:
49+
return name
50+
if name.endswith('__'):
51+
return name
52+
try:
53+
i = 0
54+
while klass[i] == '_':
55+
i = i + 1
56+
except IndexError:
57+
return name
58+
klass = klass[i:]
59+
60+
tlen = len(klass) + len(name)
61+
if tlen > MANGLE_LEN:
62+
klass = klass[:MANGLE_LEN-tlen]
63+
64+
return "_%s%s" % (klass, name)

Lib/compiler/pycodegen.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,6 @@ def is_constant_false(node):
117117
return 1
118118
return 0
119119

120-
def mangle(name):
121-
return name
122-
123120
class CodeGenerator:
124121
"""Defines basic code generator for Python bytecode
125122
@@ -136,6 +133,7 @@ class CodeGenerator:
136133

137134
optimized = 0 # is namespace access optimized?
138135
__initialized = None
136+
class_name = None # provide default for instance variable
139137

140138
def __init__(self, filename):
141139
if self.__initialized is None:
@@ -175,6 +173,12 @@ def getCode(self):
175173
"""Return a code object"""
176174
return self.graph.getCode()
177175

176+
def mangle(self, name):
177+
if self.class_name is not None:
178+
return misc.mangle(name, self.class_name)
179+
else:
180+
return name
181+
178182
# Next five methods handle name access
179183

180184
def isLocalName(self, name):
@@ -190,6 +194,7 @@ def delName(self, name):
190194
self._nameOp('DELETE', name)
191195

192196
def _nameOp(self, prefix, name):
197+
name = self.mangle(name)
193198
if not self.optimized:
194199
self.emit(prefix + '_NAME', name)
195200
return
@@ -258,7 +263,8 @@ def visitLambda(self, node):
258263
self._visitFuncOrLambda(node, isLambda=1)
259264

260265
def _visitFuncOrLambda(self, node, isLambda=0):
261-
gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
266+
gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
267+
self.class_name)
262268
walk(node.code, gen)
263269
gen.finish()
264270
self.set_lineno(node)
@@ -645,7 +651,7 @@ def _resolveDots(self, name):
645651

646652
def visitGetattr(self, node):
647653
self.visit(node.expr)
648-
self.emit('LOAD_ATTR', node.attrname)
654+
self.emit('LOAD_ATTR', self.mangle(node.attrname))
649655

650656
# next five implement assignments
651657

@@ -671,9 +677,9 @@ def visitAssName(self, node):
671677
def visitAssAttr(self, node):
672678
self.visit(node.expr)
673679
if node.flags == 'OP_ASSIGN':
674-
self.emit('STORE_ATTR', node.attrname)
680+
self.emit('STORE_ATTR', self.mangle(node.attrname))
675681
elif node.flags == 'OP_DELETE':
676-
self.emit('DELETE_ATTR', node.attrname)
682+
self.emit('DELETE_ATTR', self.mangle(node.attrname))
677683
else:
678684
print "warning: unexpected flags:", node.flags
679685
print node
@@ -728,10 +734,10 @@ def visitAugGetattr(self, node, mode):
728734
if mode == "load":
729735
self.visit(node.expr)
730736
self.emit('DUP_TOP')
731-
self.emit('LOAD_ATTR', node.attrname)
737+
self.emit('LOAD_ATTR', self.mangle(node.attrname))
732738
elif mode == "store":
733739
self.emit('ROT_TWO')
734-
self.emit('STORE_ATTR', node.attrname)
740+
self.emit('STORE_ATTR', self.mangle(node.attrname))
735741

736742
def visitAugSlice(self, node, mode):
737743
if mode == "load":
@@ -987,6 +993,7 @@ def visitModule(self, node):
987993
self.__super_visitModule(node)
988994

989995
def _nameOp(self, prefix, name):
996+
name = self.mangle(name)
990997
scope = self.scope.check_name(name)
991998
if scope == SC_LOCAL:
992999
if not self.optimized:
@@ -1002,7 +1009,8 @@ def _nameOp(self, prefix, name):
10021009
(name, scope)
10031010

10041011
def _visitFuncOrLambda(self, node, isLambda=0):
1005-
gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
1012+
gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
1013+
self.class_name)
10061014
walk(node.code, gen)
10071015
gen.finish()
10081016
self.set_lineno(node)
@@ -1079,7 +1087,8 @@ class AbstractFunctionCode:
10791087
optimized = 1
10801088
lambdaCount = 0
10811089

1082-
def __init__(self, func, filename, scopes, isLambda):
1090+
def __init__(self, func, filename, scopes, isLambda, class_name):
1091+
self.class_name = class_name
10831092
if isLambda:
10841093
klass = FunctionCodeGenerator
10851094
name = "<lambda.%d>" % klass.lambdaCount
@@ -1142,17 +1151,18 @@ class NestedFunctionCodeGenerator(AbstractFunctionCode,
11421151
super_init = NestedScopeCodeGenerator.__init__ # call be other init
11431152
__super_init = AbstractFunctionCode.__init__
11441153

1145-
def __init__(self, func, filename, scopes, isLambda):
1154+
def __init__(self, func, filename, scopes, isLambda, class_name):
11461155
self.scopes = scopes
11471156
self.scope = scopes[func]
1148-
self.__super_init(func, filename, scopes, isLambda)
1157+
self.__super_init(func, filename, scopes, isLambda, class_name)
11491158
self.graph.setFreeVars(self.scope.get_free_vars())
11501159
self.graph.setCellVars(self.scope.get_cell_vars())
11511160
## self.graph.setFlag(CO_NESTED)
11521161

11531162
class AbstractClassCode:
11541163

11551164
def __init__(self, klass, filename, scopes):
1165+
self.class_name = klass.name
11561166
self.graph = pyassem.PyFlowGraph(klass.name, filename,
11571167
optimized=0)
11581168
self.super_init(filename)
@@ -1163,6 +1173,7 @@ def __init__(self, klass, filename, scopes):
11631173
self.setDocstring(klass.doc)
11641174

11651175
def _nameOp(self, prefix, name):
1176+
name = self.mangle(name)
11661177
# Class namespaces are always unoptimized
11671178
self.emit(prefix + '_NAME', name)
11681179

Lib/compiler/symbols.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
from compiler import ast
44
from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN
5+
from compiler.misc import mangle
56
import types
67

8+
79
import sys
810

911
MANGLE_LEN = 256
@@ -36,13 +38,7 @@ def __repr__(self):
3638
def mangle(self, name):
3739
if self.klass is None:
3840
return name
39-
if not name.startswith('__'):
40-
return name
41-
if len(name) + 2 >= MANGLE_LEN:
42-
return name
43-
if name.endswith('__'):
44-
return name
45-
return "_%s%s" % (self.klass, name)
41+
return mangle(name, self.klass)
4642

4743
def add_def(self, name):
4844
self.defs[self.mangle(name)] = 1

Tools/compiler/compiler/misc.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,26 @@ def push(self, elt):
3939
self.stack.append(elt)
4040
def top(self):
4141
return self.stack[-1]
42+
43+
MANGLE_LEN = 256 # magic constant from compile.c
44+
45+
def mangle(name, klass):
46+
if not name.startswith('__'):
47+
return name
48+
if len(name) + 2 >= MANGLE_LEN:
49+
return name
50+
if name.endswith('__'):
51+
return name
52+
try:
53+
i = 0
54+
while klass[i] == '_':
55+
i = i + 1
56+
except IndexError:
57+
return name
58+
klass = klass[i:]
59+
60+
tlen = len(klass) + len(name)
61+
if tlen > MANGLE_LEN:
62+
klass = klass[:MANGLE_LEN-tlen]
63+
64+
return "_%s%s" % (klass, name)

Tools/compiler/compiler/pycodegen.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,6 @@ def is_constant_false(node):
117117
return 1
118118
return 0
119119

120-
def mangle(name):
121-
return name
122-
123120
class CodeGenerator:
124121
"""Defines basic code generator for Python bytecode
125122
@@ -136,6 +133,7 @@ class CodeGenerator:
136133

137134
optimized = 0 # is namespace access optimized?
138135
__initialized = None
136+
class_name = None # provide default for instance variable
139137

140138
def __init__(self, filename):
141139
if self.__initialized is None:
@@ -175,6 +173,12 @@ def getCode(self):
175173
"""Return a code object"""
176174
return self.graph.getCode()
177175

176+
def mangle(self, name):
177+
if self.class_name is not None:
178+
return misc.mangle(name, self.class_name)
179+
else:
180+
return name
181+
178182
# Next five methods handle name access
179183

180184
def isLocalName(self, name):
@@ -190,6 +194,7 @@ def delName(self, name):
190194
self._nameOp('DELETE', name)
191195

192196
def _nameOp(self, prefix, name):
197+
name = self.mangle(name)
193198
if not self.optimized:
194199
self.emit(prefix + '_NAME', name)
195200
return
@@ -258,7 +263,8 @@ def visitLambda(self, node):
258263
self._visitFuncOrLambda(node, isLambda=1)
259264

260265
def _visitFuncOrLambda(self, node, isLambda=0):
261-
gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
266+
gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
267+
self.class_name)
262268
walk(node.code, gen)
263269
gen.finish()
264270
self.set_lineno(node)
@@ -645,7 +651,7 @@ def _resolveDots(self, name):
645651

646652
def visitGetattr(self, node):
647653
self.visit(node.expr)
648-
self.emit('LOAD_ATTR', node.attrname)
654+
self.emit('LOAD_ATTR', self.mangle(node.attrname))
649655

650656
# next five implement assignments
651657

@@ -671,9 +677,9 @@ def visitAssName(self, node):
671677
def visitAssAttr(self, node):
672678
self.visit(node.expr)
673679
if node.flags == 'OP_ASSIGN':
674-
self.emit('STORE_ATTR', node.attrname)
680+
self.emit('STORE_ATTR', self.mangle(node.attrname))
675681
elif node.flags == 'OP_DELETE':
676-
self.emit('DELETE_ATTR', node.attrname)
682+
self.emit('DELETE_ATTR', self.mangle(node.attrname))
677683
else:
678684
print "warning: unexpected flags:", node.flags
679685
print node
@@ -728,10 +734,10 @@ def visitAugGetattr(self, node, mode):
728734
if mode == "load":
729735
self.visit(node.expr)
730736
self.emit('DUP_TOP')
731-
self.emit('LOAD_ATTR', node.attrname)
737+
self.emit('LOAD_ATTR', self.mangle(node.attrname))
732738
elif mode == "store":
733739
self.emit('ROT_TWO')
734-
self.emit('STORE_ATTR', node.attrname)
740+
self.emit('STORE_ATTR', self.mangle(node.attrname))
735741

736742
def visitAugSlice(self, node, mode):
737743
if mode == "load":
@@ -987,6 +993,7 @@ def visitModule(self, node):
987993
self.__super_visitModule(node)
988994

989995
def _nameOp(self, prefix, name):
996+
name = self.mangle(name)
990997
scope = self.scope.check_name(name)
991998
if scope == SC_LOCAL:
992999
if not self.optimized:
@@ -1002,7 +1009,8 @@ def _nameOp(self, prefix, name):
10021009
(name, scope)
10031010

10041011
def _visitFuncOrLambda(self, node, isLambda=0):
1005-
gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
1012+
gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
1013+
self.class_name)
10061014
walk(node.code, gen)
10071015
gen.finish()
10081016
self.set_lineno(node)
@@ -1079,7 +1087,8 @@ class AbstractFunctionCode:
10791087
optimized = 1
10801088
lambdaCount = 0
10811089

1082-
def __init__(self, func, filename, scopes, isLambda):
1090+
def __init__(self, func, filename, scopes, isLambda, class_name):
1091+
self.class_name = class_name
10831092
if isLambda:
10841093
klass = FunctionCodeGenerator
10851094
name = "<lambda.%d>" % klass.lambdaCount
@@ -1142,17 +1151,18 @@ class NestedFunctionCodeGenerator(AbstractFunctionCode,
11421151
super_init = NestedScopeCodeGenerator.__init__ # call be other init
11431152
__super_init = AbstractFunctionCode.__init__
11441153

1145-
def __init__(self, func, filename, scopes, isLambda):
1154+
def __init__(self, func, filename, scopes, isLambda, class_name):
11461155
self.scopes = scopes
11471156
self.scope = scopes[func]
1148-
self.__super_init(func, filename, scopes, isLambda)
1157+
self.__super_init(func, filename, scopes, isLambda, class_name)
11491158
self.graph.setFreeVars(self.scope.get_free_vars())
11501159
self.graph.setCellVars(self.scope.get_cell_vars())
11511160
## self.graph.setFlag(CO_NESTED)
11521161

11531162
class AbstractClassCode:
11541163

11551164
def __init__(self, klass, filename, scopes):
1165+
self.class_name = klass.name
11561166
self.graph = pyassem.PyFlowGraph(klass.name, filename,
11571167
optimized=0)
11581168
self.super_init(filename)
@@ -1163,6 +1173,7 @@ def __init__(self, klass, filename, scopes):
11631173
self.setDocstring(klass.doc)
11641174

11651175
def _nameOp(self, prefix, name):
1176+
name = self.mangle(name)
11661177
# Class namespaces are always unoptimized
11671178
self.emit(prefix + '_NAME', name)
11681179

Tools/compiler/compiler/symbols.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
from compiler import ast
44
from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN
5+
from compiler.misc import mangle
56
import types
67

8+
79
import sys
810

911
MANGLE_LEN = 256
@@ -36,13 +38,7 @@ def __repr__(self):
3638
def mangle(self, name):
3739
if self.klass is None:
3840
return name
39-
if not name.startswith('__'):
40-
return name
41-
if len(name) + 2 >= MANGLE_LEN:
42-
return name
43-
if name.endswith('__'):
44-
return name
45-
return "_%s%s" % (self.klass, name)
41+
return mangle(name, self.klass)
4642

4743
def add_def(self, name):
4844
self.defs[self.mangle(name)] = 1

0 commit comments

Comments
 (0)