[Zope-Checkins] CVS: Zope/lib/python/RestrictedPython/compiler_2_1 - ast.txt:1.1.2.1 ast.py:1.1.2.2 astgen.py:1.1.2.2 consts.py:1.1.2.2 future.py:1.1.2.2 misc.py:1.1.2.2 pyassem.py:1.1.2.2 pycodegen.py:1.1.2.2 symbols.py:1.1.2.2 transformer.py:1.1.2.2

Shane Hathaway shane@digicool.com
Wed, 19 Dec 2001 17:15:19 -0500


Update of /cvs-repository/Zope/lib/python/RestrictedPython/compiler_2_1
In directory cvs.zope.org:/tmp/cvs-serv21423

Modified Files:
      Tag: RestrictedPython-2_2-branch
	ast.py astgen.py consts.py future.py misc.py pyassem.py 
	pycodegen.py symbols.py transformer.py 
Added Files:
      Tag: RestrictedPython-2_2-branch
	ast.txt 
Log Message:
Sync with release21-maint branch of Tools/compiler/compiler from Python CVS.


=== Added File Zope/lib/python/RestrictedPython/compiler_2_1/ast.txt ===
Module: doc, node
Stmt: nodes
Function: name, argnames, defaults, flags, doc, code
Lambda: argnames, defaults, flags, code
Class: name, bases, doc, code
Pass: 
Break: 
Continue: 
For: assign, list, body, else_
While: test, body, else_
If: tests, else_
Exec: expr, locals, globals
From: modname, names
Import: names
Raise: expr1, expr2, expr3
TryFinally: body, final
TryExcept: body, handlers, else_
Return: value
Const: value
Print: nodes, dest
Printnl: nodes, dest
Discard: expr
AugAssign: node, op, expr
Assign: nodes, expr
AssTuple: nodes
AssList: nodes
AssName: name, flags
AssAttr: expr, attrname, flags
ListComp: expr, quals
ListCompFor: assign, list, ifs
ListCompIf: test
List: nodes
Dict: items
Not: expr
Compare: expr, ops
Name: name
Global: names
Backquote: expr
Getattr: expr, attrname
CallFunc: node, args, star_args = None, dstar_args = None
Keyword: name, expr
Subscript: expr, flags, subs
Ellipsis: 
Sliceobj: nodes
Slice: expr, flags, lower, upper
Assert: test, fail
Tuple: nodes
Or: nodes
And: nodes
Bitor: nodes
Bitxor: nodes
Bitand: nodes
LeftShift: (left, right)
RightShift: (left, right)
Add: (left, right)
Sub: (left, right)
Mul: (left, right)
Div: (left, right)
Mod: (left, right)
Power: (left, right)
UnaryAdd: expr
UnarySub: expr
Invert: expr

init(Function):
    self.varargs = self.kwargs = None
    if flags & CO_VARARGS:
        self.varargs = 1
    if flags & CO_VARKEYWORDS:
        self.kwargs = 1

init(Lambda):
    self.varargs = self.kwargs = None
    if flags & CO_VARARGS:
        self.varargs = 1
    if flags & CO_VARKEYWORDS:
        self.kwargs = 1


=== Zope/lib/python/RestrictedPython/compiler_2_1/ast.py 1.1.2.1 => 1.1.2.2 ===
     def asList(self):
         return tuple(asList(self.getChildren()))
-    def getChildNodes(self):
-        return [n for n in self.getChildren() if isinstance(n, Node)]
 
 class EmptyNode(Node):
     def __init__(self):
@@ -190,7 +188,7 @@
     def _getChildren(self):
         return self.left, self.right
     def __repr__(self):
-        return "Sub((%s, %s))" % (repr(self.left), repr(self.right))
+        return "Sub(%s, %s)" % (repr(self.left), repr(self.right))
 
 class ListCompIf(Node):
     nodes["listcompif"] = "ListCompIf"
@@ -209,7 +207,7 @@
     def _getChildren(self):
         return self.left, self.right
     def __repr__(self):
-        return "Div((%s, %s))" % (repr(self.left), repr(self.right))
+        return "Div(%s, %s)" % (repr(self.left), repr(self.right))
 
 class Discard(Node):
     nodes["discard"] = "Discard"
@@ -237,7 +235,7 @@
     def _getChildren(self):
         return self.left, self.right
     def __repr__(self):
-        return "RightShift((%s, %s))" % (repr(self.left), repr(self.right))
+        return "RightShift(%s, %s)" % (repr(self.left), repr(self.right))
 
 class Continue(Node):
     nodes["continue"] = "Continue"
@@ -277,7 +275,7 @@
     def _getChildren(self):
         return self.left, self.right
     def __repr__(self):
-        return "LeftShift((%s, %s))" % (repr(self.left), repr(self.right))
+        return "LeftShift(%s, %s)" % (repr(self.left), repr(self.right))
 
 class Mul(Node):
     nodes["mul"] = "Mul"
@@ -287,16 +285,7 @@
     def _getChildren(self):
         return self.left, self.right
     def __repr__(self):
-        return "Mul((%s, %s))" % (repr(self.left), repr(self.right))
-
-class Yield(Node):
-    nodes["yield"] = "Yield"
-    def __init__(self, value):
-        self.value = value
-    def _getChildren(self):
-        return self.value,
-    def __repr__(self):
-        return "Yield(%s)" % (repr(self.value),)
+        return "Mul(%s, %s)" % (repr(self.left), repr(self.right))
 
 class List(Node):
     nodes["list"] = "List"
@@ -365,7 +354,7 @@
     def _getChildren(self):
         return self.left, self.right
     def __repr__(self):
-        return "Mod((%s, %s))" % (repr(self.left), repr(self.right))
+        return "Mod(%s, %s)" % (repr(self.left), repr(self.right))
 
 class Class(Node):
     nodes["class"] = "Class"
@@ -463,16 +452,16 @@
     def _getChildren(self):
         return self.left, self.right
     def __repr__(self):
-        return "Power((%s, %s))" % (repr(self.left), repr(self.right))
+        return "Power(%s, %s)" % (repr(self.left), repr(self.right))
 
-class Ellipsis(Node):
-    nodes["ellipsis"] = "Ellipsis"
-    def __init__(self, ):
-        pass
+class Import(Node):
+    nodes["import"] = "Import"
+    def __init__(self, names):
+        self.names = names
     def _getChildren(self):
-        return ()
+        return self.names,
     def __repr__(self):
-        return "Ellipsis()"
+        return "Import(%s)" % (repr(self.names),)
 
 class Return(Node):
     nodes["return"] = "Return"
@@ -491,7 +480,7 @@
     def _getChildren(self):
         return self.left, self.right
     def __repr__(self):
-        return "Add((%s, %s))" % (repr(self.left), repr(self.right))
+        return "Add(%s, %s)" % (repr(self.left), repr(self.right))
 
 class Function(Node):
     nodes["function"] = "Function"
@@ -536,14 +525,14 @@
     def __repr__(self):
         return "Subscript(%s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.subs))
 
-class Import(Node):
-    nodes["import"] = "Import"
-    def __init__(self, names):
-        self.names = names
+class Ellipsis(Node):
+    nodes["ellipsis"] = "Ellipsis"
+    def __init__(self, ):
+        pass
     def _getChildren(self):
-        return self.names,
+        return ()
     def __repr__(self):
-        return "Import(%s)" % (repr(self.names),)
+        return "Ellipsis()"
 
 class Print(Node):
     nodes["print"] = "Print"


=== Zope/lib/python/RestrictedPython/compiler_2_1/astgen.py 1.1.2.1 => 1.1.2.2 ===
         if self.argnames:
             fmt = COMMA.join(["%s"] * self.nargs)
-            if '(' in self.args:
-                fmt = '(%s)' % fmt
             vals = ["repr(self.%s)" % name for name in self.argnames]
             vals = COMMA.join(vals)
             if self.nargs == 1:
@@ -173,8 +171,6 @@
         return flatten(self._getChildren())
     def asList(self):
         return tuple(asList(self.getChildren()))
-    def getChildNodes(self):
-        return [n for n in self.getChildren() if isinstance(n, Node)]
 
 class EmptyNode(Node):
     def __init__(self):


=== Zope/lib/python/RestrictedPython/compiler_2_1/consts.py 1.1.2.1 => 1.1.2.2 ===
-CO_VARARGS = 1
-CO_VARKEYWORDS = 2
-
 # operation flags
 OP_ASSIGN = 'OP_ASSIGN'
 OP_DELETE = 'OP_DELETE'
@@ -12,3 +8,9 @@
 SC_FREE = 3
 SC_CELL = 4
 SC_UNKNOWN = 5
+
+CO_OPTIMIZED = 0x0001
+CO_NEWLOCALS = 0x0002
+CO_VARARGS = 0x0004
+CO_VARKEYWORDS = 0x0008
+CO_NESTED = 0x0010


=== Zope/lib/python/RestrictedPython/compiler_2_1/future.py 1.1.2.1 => 1.1.2.2 ===
 class FutureParser:
 
-    features = ("nested_scopes", "generators", "division")
+    features = ("nested_scopes",)
     
     def __init__(self):
         self.found = {} # set
 
     def visitModule(self, node):
+        if node.doc is None:
+            off = 0
+        else:
+            off = 1
+
         stmt = node.node
-        for s in stmt.nodes:
+        for s in stmt.nodes[off:]:
             if not self.check_stmt(s):
                 break
 
@@ -62,7 +67,7 @@
 
 if __name__ == "__main__":
     import sys
-    from compiler import parseFile, walk
+    from transformer import parseFile
 
     for file in sys.argv[1:]:
         print file


=== Zope/lib/python/RestrictedPython/compiler_2_1/misc.py 1.1.2.1 => 1.1.2.2 ===
     def top(self):
         return self.stack[-1]
+    def __getitem__(self, index): # needed by visitContinue()
+        return self.stack[index]
+
+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)
+


=== Zope/lib/python/RestrictedPython/compiler_2_1/pyassem.py 1.1.2.1 => 1.1.2.2 ===
 
 from __future__ import nested_scopes
+
 import dis
 import new
 import string
@@ -8,6 +9,7 @@
 import types
 
 import misc
+from consts import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS
 
 def xxx_sort(l):
     l = l[:]
@@ -54,7 +56,7 @@
         # these edges to get the blocks emitted in the right order,
         # however. :-(  If a client needs to remove these edges, call
         # pruneEdges().
-        
+
         self.current.addNext(block)
         self.startBlock(block)
 
@@ -109,13 +111,13 @@
 
         # XXX This is a total mess.  There must be a better way to get
         # the code blocks in the right order.
-        
+
         self.fixupOrderHonorNext(blocks, default_next)
         self.fixupOrderForward(blocks, default_next)
 
     def fixupOrderHonorNext(self, blocks, default_next):
         """Fix one problem with DFS.
-        
+
         The DFS uses child block, but doesn't know about the special
         "next" block.  As a result, the DFS can order blocks so that a
         block isn't next to the right block for implicit control
@@ -195,19 +197,18 @@
             chains.remove(c)
             chains.insert(goes_before, c)
 
-
         del blocks[:]
         for c in chains:
             for b in c:
                 blocks.append(b)
-            
+
     def getBlocks(self):
         return self.blocks.elements()
 
     def getRoot(self):
         """Return nodes appropriate for use with dominator"""
         return self.entry
-    
+
     def getContainedGraphs(self):
         l = []
         for b in self.getBlocks():
@@ -246,7 +247,7 @@
     def __str__(self):
         insts = map(str, self.insts)
         return "<block %s %d:\n%s>" % (self.label, self.bid,
-                                       string.join(insts, '\n')) 
+                                       string.join(insts, '\n'))
 
     def emit(self, inst):
         op = inst[0]
@@ -268,7 +269,7 @@
         assert len(self.next) == 1, map(str, self.next)
 
     _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS',
-                        'JUMP_ABSOLUTE', 'JUMP_FORWARD')
+                        'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP')
 
     def pruneNext(self):
         """Remove bogus edge for unconditional transfers
@@ -312,11 +313,6 @@
         return contained
 
 # flags for code objects
-CO_OPTIMIZED = 0x0001
-CO_NEWLOCALS = 0x0002
-CO_VARARGS = 0x0004
-CO_VARKEYWORDS = 0x0008
-CO_NESTED = 0x0010
 
 # the FlowGraph is transformed in place; it exists in one of these states
 RAW = "RAW"
@@ -327,15 +323,17 @@
 class PyFlowGraph(FlowGraph):
     super_init = FlowGraph.__init__
 
-    def __init__(self, name, filename, args=(), optimized=0):
+    def __init__(self, name, filename, args=(), optimized=0, klass=None):
         self.super_init()
         self.name = name
+        assert isinstance(filename, types.StringType)
         self.filename = filename
         self.docstring = None
         self.args = args # XXX
         self.argcount = getArgCount(args)
+        self.klass = klass
         if optimized:
-            self.flags = CO_OPTIMIZED | CO_NEWLOCALS 
+            self.flags = CO_OPTIMIZED | CO_NEWLOCALS
         else:
             self.flags = 0
         self.consts = []
@@ -364,6 +362,10 @@
         if flag == CO_VARARGS:
             self.argcount = self.argcount - 1
 
+    def checkFlag(self, flag):
+        if self.flags & flag:
+            return 1
+
     def setFreeVars(self, names):
         self.freevars = list(names)
 
@@ -462,7 +464,6 @@
                 insts[i] = opname, offset
             elif self.hasjabs.has_elt(opname):
                 insts[i] = opname, begin[inst[1]]
-        self.stacksize = findDepth(self.insts)
         self.stage = FLAT
 
     hasjrel = misc.Set()
@@ -480,8 +481,7 @@
         for i in range(len(self.insts)):
             t = self.insts[i]
             if len(t) == 2:
-                opname = t[0]
-                oparg = t[1]
+                opname, oparg = t
                 conv = self._converters.get(opname, None)
                 if conv:
                     self.insts[i] = opname, conv(self, oparg)
@@ -501,10 +501,16 @@
         self.closure = self.cellvars + self.freevars
 
     def _lookupName(self, name, list):
-        """Return index of name in list, appending if necessary"""
+        """Return index of name in list, appending if necessary
+
+        This routine uses a list instead of a dictionary, because a
+        dictionary can't store two different keys if the keys have the
+        same value but different types, e.g. 2 and 2L.  The compiler
+        must treat these two separately, so it does an explicit type
+        comparison before comparing the values.
+        """
         t = type(name)
         for i in range(len(list)):
-            # must do a comparison on type first to prevent UnicodeErrors 
             if t == type(list[i]) and list[i] == name:
                 return i
         end = len(list)
@@ -523,9 +529,15 @@
     _convert_STORE_FAST = _convert_LOAD_FAST
     _convert_DELETE_FAST = _convert_LOAD_FAST
 
+    def _convert_LOAD_NAME(self, arg):
+        if self.klass is None:
+            self._lookupName(arg, self.varnames)
+        return self._lookupName(arg, self.names)
+
     def _convert_NAME(self, arg):
+        if self.klass is None:
+            self._lookupName(arg, self.varnames)
         return self._lookupName(arg, self.names)
-    _convert_LOAD_NAME = _convert_NAME
     _convert_STORE_NAME = _convert_NAME
     _convert_DELETE_NAME = _convert_NAME
     _convert_IMPORT_NAME = _convert_NAME
@@ -557,7 +569,7 @@
     for name, obj in locals().items():
         if name[:9] == "_convert_":
             opname = name[9:]
-            _converters[opname] = obj            
+            _converters[opname] = obj
     del name, obj, opname
 
     def makeByteCode(self):
@@ -587,13 +599,14 @@
 
     def newCodeObject(self):
         assert self.stage == DONE
-        if self.flags == 0:
+        if (self.flags & CO_NEWLOCALS) == 0:
             nlocals = 0
         else:
             nlocals = len(self.varnames)
         argcount = self.argcount
         if self.flags & CO_VARKEYWORDS:
             argcount = argcount - 1
+
         return new.code(argcount, nlocals, self.stacksize, self.flags,
                         self.lnotab.getCode(), self.getConsts(),
                         tuple(self.names), tuple(self.varnames),
@@ -613,7 +626,7 @@
                 elt = elt.getCode()
             l.append(elt)
         return tuple(l)
-            
+
 def isJump(opname):
     if opname[:4] == 'JUMP':
         return 1
@@ -707,17 +720,19 @@
 
     def getTable(self):
         return string.join(map(chr, self.lnotab), '')
-    
+
 class StackDepthTracker:
     # XXX 1. need to keep track of stack depth on jumps
     # XXX 2. at least partly as a result, this code is broken
 
-    def findDepth(self, insts):
+    def findDepth(self, insts, debug=0):
         depth = 0
         maxDepth = 0
         for i in insts:
             opname = i[0]
-            delta = self.effect.get(opname)
+            if debug:
+                print i,
+            delta = self.effect.get(opname, None)
             if delta is not None:
                 depth = depth + delta
             else:
@@ -732,10 +747,10 @@
                     meth = getattr(self, opname, None)
                     if meth is not None:
                         depth = depth + meth(i[1])
-            if depth < 0:
-                depth = 0
             if depth > maxDepth:
                 maxDepth = depth
+            if debug:
+                print depth, maxDepth
         return maxDepth
 
     effect = {
@@ -756,9 +771,8 @@
         'DELETE_SUBSCR': -2,
         # PRINT_EXPR?
         'PRINT_ITEM': -1,
-        'LOAD_LOCALS': 1,
         'RETURN_VALUE': -1,
-        'EXEC_STMT': -2,
+        'EXEC_STMT': -3,
         'BUILD_CLASS': -2,
         'STORE_NAME': -1,
         'STORE_ATTR': -2,
@@ -781,16 +795,13 @@
         ('BINARY_', -1),
         ('LOAD_', 1),
         ]
-    
-    # special cases:
-    # UNPACK_SEQUENCE, BUILD_TUPLE,
-    # BUILD_LIST, CALL_FUNCTION, MAKE_FUNCTION, BUILD_SLICE
+
     def UNPACK_SEQUENCE(self, count):
         return count-1
     def BUILD_TUPLE(self, count):
-        return 1-count
+        return -count+1
     def BUILD_LIST(self, count):
-        return 1-count
+        return -count+1
     def CALL_FUNCTION(self, argc):
         hi, lo = divmod(argc, 256)
         return -(lo + hi * 2)
@@ -802,6 +813,9 @@
         return self.CALL_FUNCTION(argc)-2
     def MAKE_FUNCTION(self, argc):
         return -argc
+    def MAKE_CLOSURE(self, argc):
+        # XXX need to account for free variables too!
+        return -argc
     def BUILD_SLICE(self, argc):
         if argc == 2:
             return -1
@@ -809,5 +823,5 @@
             return -2
     def DUP_TOPX(self, argc):
         return argc
-    
+
 findDepth = StackDepthTracker().findDepth


=== Zope/lib/python/RestrictedPython/compiler_2_1/pycodegen.py 1.1.2.1 => 1.1.2.2 === (426/526 lines abridged)
 import pyassem, misc, future, symbols
 from consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
-from pyassem import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
-     CO_NESTED, TupleArg
+from consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS, CO_NESTED
+from pyassem import TupleArg
 
 # Do we have Python 1.x or Python 2.x?
 try:
@@ -30,15 +30,24 @@
     (1,1) : "CALL_FUNCTION_VAR_KW",
 }
 
+LOOP = 1
+EXCEPT = 2
+TRY_FINALLY = 3
+END_FINALLY = 4
+
 def compile(filename, display=0):
     f = open(filename)
     buf = f.read()
     f.close()
     mod = Module(buf, filename)
-    mod.compile(display)
-    f = open(filename + "c", "wb")
-    mod.dump(f)
-    f.close()
+    try:
+        mod.compile(display)
+    except SyntaxError:
+        raise
+    else:
+        f = open(filename + "c", "wb")
+        mod.dump(f)
+        f.close()
 
 class Module:
     def __init__(self, source, filename):
@@ -117,6 +126,12 @@
     def visitAssName(self, node):
         self.names.add(node.name)
 
+def is_constant_false(node):
+    if isinstance(node, ast.Const):
+        if not node.value:
+            return 1
+    return 0
+
 class CodeGenerator:
     """Defines basic code generator for Python bytecode

[-=- -=- -=- 426 lines omitted -=- -=- -=-]

+    __super_init = AbstractClassCode.__init__
+
+    def __init__(self, klass, scopes, filename):
+        self.scopes = scopes
+        self.scope = scopes[klass]
+        self.__super_init(klass, scopes, filename)
+        self.graph.setFreeVars(self.scope.get_free_vars())
+        self.graph.setCellVars(self.scope.get_cell_vars())
+
 class NestedClassCodeGenerator(AbstractClassCode,
                                NestedScopeMixin,
                                NestedScopeCodeGenerator):
     super_init = NestedScopeCodeGenerator.__init__ # call be other init
     __super_init = AbstractClassCode.__init__
 
-    def __init__(self, klass, filename, scopes):
+    def __init__(self, klass, scopes, filename):
+        assert isinstance(filename, types.StringType)
         self.scopes = scopes
         self.scope = scopes[klass]
-        self.__super_init(klass, filename, scopes)
+        self.__super_init(klass, scopes, filename)
         self.graph.setFreeVars(self.scope.get_free_vars())
         self.graph.setCellVars(self.scope.get_cell_vars())
         self.graph.setFlag(CO_NESTED)
@@ -1212,7 +1287,7 @@
 def findOp(node):
     """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
     v = OpFinder()
-    walk(node, v, 0)
+    walk(node, v, verbose=0)
     return v.op
 
 class OpFinder:
@@ -1224,6 +1299,7 @@
         elif self.op != node.flags:
             raise ValueError, "mixed ops in stmt"
     visitAssAttr = visitAssName
+    visitSubscript = visitAssName
 
 class Delegator:
     """Base class to support delegation for augmented assignment nodes
@@ -1253,6 +1329,7 @@
 
 class AugSubscript(Delegator):
     pass
+
 
 wrapper = {
     ast.Getattr: AugGetattr,


=== Zope/lib/python/RestrictedPython/compiler_2_1/symbols.py 1.1.2.1 => 1.1.2.2 ===
 import ast
 from consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN
+from misc import mangle
 import types
 
 import sys
@@ -36,13 +37,7 @@
     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
@@ -295,6 +290,27 @@
                 name = name[:i]
             scope.add_def(asname or name)
 
+    def visitGlobal(self, node, scope):
+        for name in node.names:
+            scope.add_global(name)
+
+    def visitAssign(self, node, scope):
+        """Propagate assignment flag down to child nodes.
+
+        The Assign node doesn't itself contains the variables being
+        assigned to.  Instead, the children in node.nodes are visited
+        with the assign flag set to true.  When the names occur in
+        those nodes, they are marked as defs.
+
+        Some names that occur in an assignment target are not bound by
+        the assignment, e.g. a name occurring inside a slice.  The
+        visitor handles these nodes specially; they do not propagate
+        the assign flag to their children.
+        """
+        for n in node.nodes:
+            self.visit(n, scope, 1)
+        self.visit(node.expr, scope)
+
     def visitAssName(self, node, scope, assign=1):
         scope.add_def(node.name)
 
@@ -306,6 +322,13 @@
         for n in node.subs:
             self.visit(n, scope, 0)
 
+    def visitSlice(self, node, scope, assign=0):
+        self.visit(node.expr, scope, 0)
+        if node.lower:
+            self.visit(node.lower, scope, 0)
+        if node.upper:
+            self.visit(node.upper, scope, 0)
+
     def visitAugAssign(self, node, scope):
         # If the LHS is a name, then this counts as assignment.
         # Otherwise, it's just use.
@@ -314,15 +337,6 @@
             self.visit(node.node, scope, 1) # XXX worry about this
         self.visit(node.expr, scope)
 
-    def visitAssign(self, node, scope):
-        for n in node.nodes:
-            self.visit(n, scope, 1)
-        self.visit(node.expr, scope)
-
-    def visitGlobal(self, node, scope):
-        for name in node.names:
-            scope.add_global(name)
-
     # prune if statements if tests are false
 
     _const_types = types.StringType, types.IntType, types.FloatType
@@ -348,7 +362,8 @@
 
 if __name__ == "__main__":
     import sys
-    from compiler import parseFile, walk
+    from transformer import parseFile
+    from visitor import walk
     import symtable
 
     def get_names(syms):


=== Zope/lib/python/RestrictedPython/compiler_2_1/transformer.py 1.1.2.1 => 1.1.2.2 ===
     def file_input(self, nodelist):
         doc = self.get_docstring(nodelist, symbol.file_input)
-        if doc is not None:
-            i = 1
-        else:
-            i = 0
         stmts = []
-        for node in nodelist[i:]:
+        for node in nodelist:
             if node[0] != token.ENDMARKER and node[0] != token.NEWLINE:
                 self.com_append_stmt(stmts, node)
         return Module(doc, Stmt(stmts))
@@ -344,11 +340,6 @@
         n.lineno = nodelist[0][2]
         return n
 
-    def yield_stmt(self, nodelist):
-        n = Yield(self.com_node(nodelist[1]))
-        n.lineno = nodelist[0][2]
-        return n
-
     def raise_stmt(self, nodelist):
         # raise: [test [',' test [',' test]]]
         if len(nodelist) > 5:
@@ -1254,7 +1245,6 @@
     symbol.continue_stmt,
     symbol.return_stmt,
     symbol.raise_stmt,
-    #symbol.yield_stmt,
     symbol.import_stmt,
     symbol.global_stmt,
     symbol.exec_stmt,
@@ -1280,9 +1270,6 @@
     symbol.power,
     symbol.atom,
     ]
-
-if hasattr(symbol, 'yield_stmt'):
-    _legal_node_types.append(symbol.yield_stmt)
 
 _assign_types = [
     symbol.test,