# [Zope-Checkins] CVS: Releases/Zope/lib/python/RestrictedPython/compiler - pyassem.py:1.3.42.1

Evan Simpson evan@zope.com
Fri, 14 Dec 2001 13:27:09 -0500

```Update of /cvs-repository/Releases/Zope/lib/python/RestrictedPython/compiler
In directory cvs.zope.org:/tmp/cvs-serv32010/RestrictedPython/compiler

Modified Files:
Tag: Zope-2_5-branch
pyassem.py
Log Message:
Merge compiler fixes from trunk

=== Releases/Zope/lib/python/RestrictedPython/compiler/pyassem.py 1.3 => 1.3.42.1 ===

+from __future__ import nested_scopes
import dis
import new
import string
@@ -372,6 +373,7 @@
def getCode(self):
"""Get a Python code object"""
if self.stage == RAW:
+            self.computeStackDepth()
self.flattenGraph()
if self.stage == FLAT:
self.convertArgs()
@@ -399,6 +401,36 @@
if io:
sys.stdout = save

+    def computeStackDepth(self):
+        """Compute the max stack depth.
+
+        Approach is to compute the stack effect of each basic block.
+        Then find the path through the code with the largest total
+        effect.
+        """
+        depth = {}
+        exit = None
+        for b in self.getBlocks():
+            depth[b] = findDepth(b.getInstructions())
+
+        seen = {}
+
+        def max_depth(b, d):
+            if seen.has_key(b):
+                return d
+            seen[b] = 1
+            d = d + depth[b]
+            children = b.get_children()
+            if children:
+                return max([max_depth(c, d) for c in children])
+            else:
+                if not b.label == "exit":
+                    return max_depth(self.exit, d)
+                else:
+                    return d
+
+        self.stacksize = max_depth(self.entry, 0)
+
def flattenGraph(self):
"""Arrange the blocks in order and resolve jumps"""
assert self.stage == RAW
@@ -685,16 +717,10 @@
maxDepth = 0
for i in insts:
opname = i[0]
-            delta = self.effect.get(opname, 0)
-            if delta > 1:
-                depth = depth + delta
-            elif delta < 0:
-                if depth > maxDepth:
-                    maxDepth = depth
+            delta = self.effect.get(opname)
+            if delta is not None:
depth = depth + delta
else:
-                if depth > maxDepth:
-                    maxDepth = depth
# now check patterns
for pat, pat_delta in self.patterns:
if opname[:len(pat)] == pat:
@@ -702,12 +728,14 @@
depth = depth + delta
break
# if we still haven't found a match
-                if delta == 0:
+                if delta is None:
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
return maxDepth

effect = {
@@ -742,6 +770,11 @@
'IMPORT_STAR': -1,
'IMPORT_NAME': 0,
'IMPORT_FROM': 1,
+        # close enough...
+        'SETUP_EXCEPT': 3,
+        'SETUP_FINALLY': 3,
+        'FOR_ITER': 1,
}
# use pattern match
patterns = [
@@ -753,20 +786,20 @@
# UNPACK_SEQUENCE, BUILD_TUPLE,
# BUILD_LIST, CALL_FUNCTION, MAKE_FUNCTION, BUILD_SLICE
def UNPACK_SEQUENCE(self, count):
-        return count
+        return count-1
def BUILD_TUPLE(self, count):
-        return -count
+        return 1-count
def BUILD_LIST(self, count):
-        return -count
+        return 1-count
def CALL_FUNCTION(self, argc):
hi, lo = divmod(argc, 256)
-        return lo + hi * 2
+        return -(lo + hi * 2)
def CALL_FUNCTION_VAR(self, argc):
-        return self.CALL_FUNCTION(argc)+1
+        return self.CALL_FUNCTION(argc)-1
def CALL_FUNCTION_KW(self, argc):
-        return self.CALL_FUNCTION(argc)+1
+        return self.CALL_FUNCTION(argc)-1
def CALL_FUNCTION_VAR_KW(self, argc):
-        return self.CALL_FUNCTION(argc)+2
+        return self.CALL_FUNCTION(argc)-2
def MAKE_FUNCTION(self, argc):
return -argc
def BUILD_SLICE(self, argc):
@@ -774,5 +807,7 @@
return -1
elif argc == 3:
return -2
+    def DUP_TOPX(self, argc):
+        return argc

findDepth = StackDepthTracker().findDepth

```