]> granicus.if.org Git - python/commitdiff
Handle private names
authorJeremy Hylton <jeremy@alum.mit.edu>
Mon, 27 Aug 2001 22:56:16 +0000 (22:56 +0000)
committerJeremy Hylton <jeremy@alum.mit.edu>
Mon, 27 Aug 2001 22:56:16 +0000 (22:56 +0000)
(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()

Lib/compiler/misc.py
Lib/compiler/pycodegen.py
Lib/compiler/symbols.py
Tools/compiler/compiler/misc.py
Tools/compiler/compiler/pycodegen.py
Tools/compiler/compiler/symbols.py

index 29ff86678025f1bcb5c52e54816792e5e525f59c..b834a2e677cc8f2e1c681a9477113cb5b4d18955 100644 (file)
@@ -39,3 +39,26 @@ class Stack:
         self.stack.append(elt)
     def top(self):
         return self.stack[-1]
+
+MANGLE_LEN = 256 # magic constant from compile.c
+
+def mangle(name, klass):
+    if not name.startswith('__'):
+        return name
+    if len(name) + 2 >= MANGLE_LEN:
+        return name
+    if name.endswith('__'):
+        return name
+    try:
+        i = 0
+        while klass[i] == '_':
+            i = i + 1
+    except IndexError:
+        return name
+    klass = klass[i:]
+
+    tlen = len(klass) + len(name)
+    if tlen > MANGLE_LEN:
+        klass = klass[:MANGLE_LEN-tlen]
+
+    return "_%s%s" % (klass, name)
index 37b51bf44d4c8b97795ac691bf6f258a3532ff78..ced0f07d425c16caede10f764e9ce17f3fdf8e46 100644 (file)
@@ -117,9 +117,6 @@ def is_constant_false(node):
             return 1
     return 0
 
-def mangle(name):
-    return name
-
 class CodeGenerator:
     """Defines basic code generator for Python bytecode
 
@@ -136,6 +133,7 @@ class CodeGenerator:
 
     optimized = 0 # is namespace access optimized?
     __initialized = None
+    class_name = None # provide default for instance variable
 
     def __init__(self, filename):
         if self.__initialized is None:
@@ -175,6 +173,12 @@ class CodeGenerator:
         """Return a code object"""
         return self.graph.getCode()
 
+    def mangle(self, name):
+        if self.class_name is not None:
+            return misc.mangle(name, self.class_name)
+        else:
+            return name
+
     # Next five methods handle name access
 
     def isLocalName(self, name):
@@ -190,6 +194,7 @@ class CodeGenerator:
         self._nameOp('DELETE', name)
 
     def _nameOp(self, prefix, name):
+        name = self.mangle(name)
         if not self.optimized:
             self.emit(prefix + '_NAME', name)
             return
@@ -258,7 +263,8 @@ class CodeGenerator:
         self._visitFuncOrLambda(node, isLambda=1)
 
     def _visitFuncOrLambda(self, node, isLambda=0):
-        gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
+        gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
+                               self.class_name)
         walk(node.code, gen)
         gen.finish()
         self.set_lineno(node)
@@ -645,7 +651,7 @@ class CodeGenerator:
 
     def visitGetattr(self, node):
         self.visit(node.expr)
-        self.emit('LOAD_ATTR', node.attrname)
+        self.emit('LOAD_ATTR', self.mangle(node.attrname))
 
     # next five implement assignments
 
@@ -671,9 +677,9 @@ class CodeGenerator:
     def visitAssAttr(self, node):
         self.visit(node.expr)
         if node.flags == 'OP_ASSIGN':
-            self.emit('STORE_ATTR', node.attrname)
+            self.emit('STORE_ATTR', self.mangle(node.attrname))
         elif node.flags == 'OP_DELETE':
-            self.emit('DELETE_ATTR', node.attrname)
+            self.emit('DELETE_ATTR', self.mangle(node.attrname))
         else:
             print "warning: unexpected flags:", node.flags
             print node
@@ -728,10 +734,10 @@ class CodeGenerator:
         if mode == "load":
             self.visit(node.expr)
             self.emit('DUP_TOP')
-            self.emit('LOAD_ATTR', node.attrname)
+            self.emit('LOAD_ATTR', self.mangle(node.attrname))
         elif mode == "store":
             self.emit('ROT_TWO')
-            self.emit('STORE_ATTR', node.attrname)
+            self.emit('STORE_ATTR', self.mangle(node.attrname))
 
     def visitAugSlice(self, node, mode):
         if mode == "load":
@@ -987,6 +993,7 @@ class NestedScopeCodeGenerator(CodeGenerator):
         self.__super_visitModule(node)
 
     def _nameOp(self, prefix, name):
+        name = self.mangle(name)
         scope = self.scope.check_name(name)
         if scope == SC_LOCAL:
             if not self.optimized:
@@ -1002,7 +1009,8 @@ class NestedScopeCodeGenerator(CodeGenerator):
                   (name, scope)
 
     def _visitFuncOrLambda(self, node, isLambda=0):
-        gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
+        gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
+                               self.class_name)
         walk(node.code, gen)
         gen.finish()
         self.set_lineno(node)
@@ -1079,7 +1087,8 @@ class AbstractFunctionCode:
     optimized = 1
     lambdaCount = 0
 
-    def __init__(self, func, filename, scopes, isLambda):
+    def __init__(self, func, filename, scopes, isLambda, class_name):
+        self.class_name = class_name
         if isLambda:
             klass = FunctionCodeGenerator
             name = "<lambda.%d>" % klass.lambdaCount
@@ -1142,10 +1151,10 @@ class NestedFunctionCodeGenerator(AbstractFunctionCode,
     super_init = NestedScopeCodeGenerator.__init__ # call be other init
     __super_init = AbstractFunctionCode.__init__
 
-    def __init__(self, func, filename, scopes, isLambda):
+    def __init__(self, func, filename, scopes, isLambda, class_name):
         self.scopes = scopes
         self.scope = scopes[func]
-        self.__super_init(func, filename, scopes, isLambda)
+        self.__super_init(func, filename, scopes, isLambda, class_name)
         self.graph.setFreeVars(self.scope.get_free_vars())
         self.graph.setCellVars(self.scope.get_cell_vars())
 ##        self.graph.setFlag(CO_NESTED)
@@ -1153,6 +1162,7 @@ class NestedFunctionCodeGenerator(AbstractFunctionCode,
 class AbstractClassCode:
 
     def __init__(self, klass, filename, scopes):
+        self.class_name = klass.name
         self.graph = pyassem.PyFlowGraph(klass.name, filename,
                                            optimized=0)
         self.super_init(filename)
@@ -1163,6 +1173,7 @@ class AbstractClassCode:
             self.setDocstring(klass.doc)
 
     def _nameOp(self, prefix, name):
+        name = self.mangle(name)
         # Class namespaces are always unoptimized
         self.emit(prefix + '_NAME', name)
 
index 0ef0d12f03bc635005970a619cc58ae178e432e5..40fd127bfd19705b765d1e26268454323a20204b 100644 (file)
@@ -2,8 +2,10 @@
 
 from compiler import ast
 from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN
+from compiler.misc import mangle
 import types
 
+
 import sys
 
 MANGLE_LEN = 256
@@ -36,13 +38,7 @@ class Scope:
     def mangle(self, name):
         if self.klass is None:
             return name
-        if not name.startswith('__'):
-            return name
-        if len(name) + 2 >= MANGLE_LEN:
-            return name
-        if name.endswith('__'):
-            return name
-        return "_%s%s" % (self.klass, name)
+        return mangle(name, self.klass)
 
     def add_def(self, name):
         self.defs[self.mangle(name)] = 1
index 29ff86678025f1bcb5c52e54816792e5e525f59c..b834a2e677cc8f2e1c681a9477113cb5b4d18955 100644 (file)
@@ -39,3 +39,26 @@ class Stack:
         self.stack.append(elt)
     def top(self):
         return self.stack[-1]
+
+MANGLE_LEN = 256 # magic constant from compile.c
+
+def mangle(name, klass):
+    if not name.startswith('__'):
+        return name
+    if len(name) + 2 >= MANGLE_LEN:
+        return name
+    if name.endswith('__'):
+        return name
+    try:
+        i = 0
+        while klass[i] == '_':
+            i = i + 1
+    except IndexError:
+        return name
+    klass = klass[i:]
+
+    tlen = len(klass) + len(name)
+    if tlen > MANGLE_LEN:
+        klass = klass[:MANGLE_LEN-tlen]
+
+    return "_%s%s" % (klass, name)
index 37b51bf44d4c8b97795ac691bf6f258a3532ff78..ced0f07d425c16caede10f764e9ce17f3fdf8e46 100644 (file)
@@ -117,9 +117,6 @@ def is_constant_false(node):
             return 1
     return 0
 
-def mangle(name):
-    return name
-
 class CodeGenerator:
     """Defines basic code generator for Python bytecode
 
@@ -136,6 +133,7 @@ class CodeGenerator:
 
     optimized = 0 # is namespace access optimized?
     __initialized = None
+    class_name = None # provide default for instance variable
 
     def __init__(self, filename):
         if self.__initialized is None:
@@ -175,6 +173,12 @@ class CodeGenerator:
         """Return a code object"""
         return self.graph.getCode()
 
+    def mangle(self, name):
+        if self.class_name is not None:
+            return misc.mangle(name, self.class_name)
+        else:
+            return name
+
     # Next five methods handle name access
 
     def isLocalName(self, name):
@@ -190,6 +194,7 @@ class CodeGenerator:
         self._nameOp('DELETE', name)
 
     def _nameOp(self, prefix, name):
+        name = self.mangle(name)
         if not self.optimized:
             self.emit(prefix + '_NAME', name)
             return
@@ -258,7 +263,8 @@ class CodeGenerator:
         self._visitFuncOrLambda(node, isLambda=1)
 
     def _visitFuncOrLambda(self, node, isLambda=0):
-        gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
+        gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
+                               self.class_name)
         walk(node.code, gen)
         gen.finish()
         self.set_lineno(node)
@@ -645,7 +651,7 @@ class CodeGenerator:
 
     def visitGetattr(self, node):
         self.visit(node.expr)
-        self.emit('LOAD_ATTR', node.attrname)
+        self.emit('LOAD_ATTR', self.mangle(node.attrname))
 
     # next five implement assignments
 
@@ -671,9 +677,9 @@ class CodeGenerator:
     def visitAssAttr(self, node):
         self.visit(node.expr)
         if node.flags == 'OP_ASSIGN':
-            self.emit('STORE_ATTR', node.attrname)
+            self.emit('STORE_ATTR', self.mangle(node.attrname))
         elif node.flags == 'OP_DELETE':
-            self.emit('DELETE_ATTR', node.attrname)
+            self.emit('DELETE_ATTR', self.mangle(node.attrname))
         else:
             print "warning: unexpected flags:", node.flags
             print node
@@ -728,10 +734,10 @@ class CodeGenerator:
         if mode == "load":
             self.visit(node.expr)
             self.emit('DUP_TOP')
-            self.emit('LOAD_ATTR', node.attrname)
+            self.emit('LOAD_ATTR', self.mangle(node.attrname))
         elif mode == "store":
             self.emit('ROT_TWO')
-            self.emit('STORE_ATTR', node.attrname)
+            self.emit('STORE_ATTR', self.mangle(node.attrname))
 
     def visitAugSlice(self, node, mode):
         if mode == "load":
@@ -987,6 +993,7 @@ class NestedScopeCodeGenerator(CodeGenerator):
         self.__super_visitModule(node)
 
     def _nameOp(self, prefix, name):
+        name = self.mangle(name)
         scope = self.scope.check_name(name)
         if scope == SC_LOCAL:
             if not self.optimized:
@@ -1002,7 +1009,8 @@ class NestedScopeCodeGenerator(CodeGenerator):
                   (name, scope)
 
     def _visitFuncOrLambda(self, node, isLambda=0):
-        gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
+        gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
+                               self.class_name)
         walk(node.code, gen)
         gen.finish()
         self.set_lineno(node)
@@ -1079,7 +1087,8 @@ class AbstractFunctionCode:
     optimized = 1
     lambdaCount = 0
 
-    def __init__(self, func, filename, scopes, isLambda):
+    def __init__(self, func, filename, scopes, isLambda, class_name):
+        self.class_name = class_name
         if isLambda:
             klass = FunctionCodeGenerator
             name = "<lambda.%d>" % klass.lambdaCount
@@ -1142,10 +1151,10 @@ class NestedFunctionCodeGenerator(AbstractFunctionCode,
     super_init = NestedScopeCodeGenerator.__init__ # call be other init
     __super_init = AbstractFunctionCode.__init__
 
-    def __init__(self, func, filename, scopes, isLambda):
+    def __init__(self, func, filename, scopes, isLambda, class_name):
         self.scopes = scopes
         self.scope = scopes[func]
-        self.__super_init(func, filename, scopes, isLambda)
+        self.__super_init(func, filename, scopes, isLambda, class_name)
         self.graph.setFreeVars(self.scope.get_free_vars())
         self.graph.setCellVars(self.scope.get_cell_vars())
 ##        self.graph.setFlag(CO_NESTED)
@@ -1153,6 +1162,7 @@ class NestedFunctionCodeGenerator(AbstractFunctionCode,
 class AbstractClassCode:
 
     def __init__(self, klass, filename, scopes):
+        self.class_name = klass.name
         self.graph = pyassem.PyFlowGraph(klass.name, filename,
                                            optimized=0)
         self.super_init(filename)
@@ -1163,6 +1173,7 @@ class AbstractClassCode:
             self.setDocstring(klass.doc)
 
     def _nameOp(self, prefix, name):
+        name = self.mangle(name)
         # Class namespaces are always unoptimized
         self.emit(prefix + '_NAME', name)
 
index 0ef0d12f03bc635005970a619cc58ae178e432e5..40fd127bfd19705b765d1e26268454323a20204b 100644 (file)
@@ -2,8 +2,10 @@
 
 from compiler import ast
 from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN
+from compiler.misc import mangle
 import types
 
+
 import sys
 
 MANGLE_LEN = 256
@@ -36,13 +38,7 @@ class Scope:
     def mangle(self, name):
         if self.klass is None:
             return name
-        if not name.startswith('__'):
-            return name
-        if len(name) + 2 >= MANGLE_LEN:
-            return name
-        if name.endswith('__'):
-            return name
-        return "_%s%s" % (self.klass, name)
+        return mangle(name, self.klass)
 
     def add_def(self, name):
         self.defs[self.mangle(name)] = 1