[Checkins] SVN: z3c.pt/trunk/z3c/pt/ Refactor scoping

Daniel Nouri daniel.nouri at gmail.com
Sat Dec 22 19:06:02 EST 2007


Log message for revision 82404:
  Refactor scoping
  

Changed:
  U   z3c.pt/trunk/z3c/pt/clauses.py
  U   z3c.pt/trunk/z3c/pt/io.py
  U   z3c.pt/trunk/z3c/pt/translation.py

-=-
Modified: z3c.pt/trunk/z3c/pt/clauses.py
===================================================================
--- z3c.pt/trunk/z3c/pt/clauses.py	2007-12-22 21:28:32 UTC (rev 82403)
+++ z3c.pt/trunk/z3c/pt/clauses.py	2007-12-23 00:06:01 UTC (rev 82404)
@@ -1,10 +1,11 @@
 from attributes import expression
+from attributes import definition
+
 import utils
 
 class Assign(object):
     """
       >>> from z3c.pt.io import CodeIO; stream = CodeIO()
-      >>> _scope = []
 
     Simple assignment:
 
@@ -23,7 +24,15 @@
       >>> b == 1
       True
       >>> assign.end(stream)
-      
+
+    Try-except chain part 2: 
+
+      >>> assign = Assign(expression("'abc' | 1"))
+      >>> assign.begin(stream, 'b')
+      >>> exec stream.getvalue()
+      >>> b == 'abc'
+      True
+      >>> assign.end(stream)
      """
     
     def __init__(self, expressions, variable=None):
@@ -54,7 +63,6 @@
 class Define(object):
     """
       >>> from z3c.pt.io import CodeIO; stream = CodeIO()
-      >>> _scope = []
 
     Variable scope:
 
@@ -65,7 +73,6 @@
       >>> a is b
       True
       >>> del a
-      >>> _scope.remove('a')
       >>> define.end(stream)
       >>> exec stream.getvalue()
       >>> a
@@ -89,7 +96,7 @@
       >>> define2.end(stream)
       >>> define1.end(stream)
       >>> del a; del c
-      >>> _scope.remove('a'); _scope.remove('c')
+      >>> stream.scope[-1].remove('a'); stream.scope[-1].remove('c')
       >>> exec stream.getvalue()
       >>> a
       Traceback (most recent call last):
@@ -105,7 +112,7 @@
     Tuple assignments:
 
       >>> stream = CodeIO()
-      >>> define = Define("(e, f)", expression("[1, 2]"))
+      >>> define = Define(['e', 'f'], expression("[1, 2]"))
       >>> define.begin(stream)
       >>> exec stream.getvalue()
       >>> e == 1 and f == 2
@@ -114,8 +121,12 @@
 
     Verify scope is preserved on tuple assignment:
 
+      >>> stream = CodeIO()
       >>> e = None; f = None
-      >>> _scope.append('e'); _scope.append('f')
+      >>> stream.scope[-1].add('e'); stream.scope[-1].add('f')
+      >>> stream.scope.append(set())
+      >>> define.begin(stream)
+      >>> define.end(stream)
       >>> exec stream.getvalue()
       >>> e is None and f is None
       True
@@ -134,7 +145,8 @@
 
       >>> stream = CodeIO()
       >>> a = 1
-      >>> _scope.append('a')
+      >>> stream.scope[-1].add('a')
+      >>> stream.scope.append(set())
       >>> define = Define("a", expression("2"))
       >>> define.begin(stream)
       >>> define.end(stream)
@@ -143,7 +155,7 @@
       1
     
     """
-    def __init__(self, definition, expression, scope=()):
+    def __init__(self, definition, expression):
         if not isinstance(definition, (list, tuple)):
             definition = (definition,)
 
@@ -152,45 +164,48 @@
         else:
             variable = u"(%s,)" % ", ".join(definition)
 
-        self.assign = Assign(expression, variable)
-
-        # only register definitions for variables that have not
-        # been defined in this scope
-        self.definitions = [var for var in definition if var not in scope]
-            
-        if scope:
-            scope.extend(self.definitions)
-        if not scope:
-            scope = utils.scope()
-
-        self.scope = scope
+        self.assign = Assign(expression, variable)        
+        self.definitions = definition
         
     def begin(self, stream):
-        temp = stream.savevariable(self.scope, '{}')
-
         # save local variables already in in scope
         for var in self.definitions:
-            stream.write("if '%s' in _scope: %s['%s'] = %s" % (var, temp, var, var))
-            stream.write("else: _scope.append('%s')" % var)
-            
+            temp = stream.save()
+
+            # If we didn't set the variable in this scope already
+            if var not in stream.scope[-1]:
+
+                # we'll check if it's set in one of the older scopes
+                for scope in stream.scope[:-1]:
+                    if var in scope:
+                        # in which case we back it up
+                        stream.write('%s = %s' % (temp, var))
+
+                stream.scope[-1].add(var)
+                   
         self.assign.begin(stream)
 
     def end(self, stream):
-        temp = stream.restorevariable(self.scope)
+        self.assign.end(stream)
 
-        self.assign.end(stream)
-        
+        # back come the variables that were already in scope in the
+        # first place
         for var in reversed(self.definitions):
-            stream.write("if '%s' in %s:" % (var, temp))
-            stream.indent()
-            stream.write("%s = %s['%s']" % (var, temp, var))
-            stream.outdent()
-            stream.write("else:")
-            stream.indent()
-            stream.write("del %s" % var)
-            stream.write("_scope.remove('%s')" % var)
-            stream.outdent()
-            
+            temp = stream.restore()
+
+            # If we set the variable in this scope already
+            if var in stream.scope[-1]:
+
+                # we'll check if it's set in one of the older scopes
+                for scope in stream.scope[:-1]:
+                    if var in scope:
+                        # in which case we restore it
+                        stream.write('%s = %s' % (var, temp))
+                        stream.scope[-1].remove(var)
+                        break
+                else:
+                    stream.write("del %s" % var)
+
 class Condition(object):
     """
       >>> from z3c.pt.io import CodeIO
@@ -284,7 +299,6 @@
     """
       >>> from z3c.pt.io import CodeIO
       >>> from StringIO import StringIO
-      >>> _scope = []
 
       >>> _out = StringIO(); stream = CodeIO()
       >>> tag = Tag('div', dict(alt=expression(repr('Hello World!'))))
@@ -338,7 +352,6 @@
 class Repeat(object):
     """
       >>> from z3c.pt.io import CodeIO; stream = CodeIO()
-      >>> _scope = []
 
     We need to set up the repeat object.
 
@@ -363,7 +376,7 @@
         
     def __init__(self, v, e, scope=()):
         self.variable = v
-        self.define = Define(v, expression("None"), scope)
+        self.define = Define(v, expression("None"))
         self.assign = Assign(e)
 
     def begin(self, stream):

Modified: z3c.pt/trunk/z3c/pt/io.py
===================================================================
--- z3c.pt/trunk/z3c/pt/io.py	2007-12-22 21:28:32 UTC (rev 82403)
+++ z3c.pt/trunk/z3c/pt/io.py	2007-12-23 00:06:01 UTC (rev 82404)
@@ -22,48 +22,21 @@
         self.indentation = indentation
         self.indentation_string = indentation_string
         self.queue = u''
-        self.scope = {}
+        self.scope = [set()]
+        
+        self._variables = {}
 
         self.t_counter = 0
-        self.v_counter = 0        
 
-    def save(self, variable=None):
+    def save(self):
         self.t_counter += 1
-        if variable:
-            self.write("%s%d = %s" % (self.t_prefix, self.t_counter, variable))
-        else:
-            return "%s%d" % (self.t_prefix, self.t_counter)
+        return "%s%d" % (self.t_prefix, self.t_counter)
         
-    def restore(self, variable=None):
-        if variable:
-            self.write("%s = %s%d" % (variable, self.t_prefix, self.t_counter))
-        else:
-            return "%s%d" % (self.t_prefix, self.t_counter)
-        
+    def restore(self):
+        var = "%s%d" % (self.t_prefix, self.t_counter)
         self.t_counter -= 1
-
-    def savevariable(self, obj, expression="None"):
-        if obj in self.scope:
-            return self.scope[obj]
-
-        self.v_counter += 1
-        variable = "%s%d" % (self.v_prefix, self.v_counter)
-
-        self.write("%s = %s" % (variable, expression))
-
-        self.scope[obj] = variable
-        return variable
-
-    def restorevariable(self, obj, expression="None"):
-        if obj in self.scope:
-            return self.scope[obj]
-
-        variable = "%s%d" % (self.v_prefix, self.v_counter)
-        self.v_counter -= 1
-
-        self.scope[obj] = variable
-        return variable
-
+        return var
+        
     def indent(self, amount=1):
         self.cook()
         self.indentation += amount

Modified: z3c.pt/trunk/z3c/pt/translation.py
===================================================================
--- z3c.pt/trunk/z3c/pt/translation.py	2007-12-22 21:28:32 UTC (rev 82403)
+++ z3c.pt/trunk/z3c/pt/translation.py	2007-12-23 00:06:01 UTC (rev 82404)
@@ -11,7 +11,6 @@
 \tglobal utils
 
 \t_out = utils.initialize_stream()
-\t_scope = locals().keys()
     
 \t(_attributes, repeat) = utils.initialize_tal()
 \t(_domain, _translate) = utils.initialize_i18n()
@@ -32,10 +31,12 @@
 
 class Element(lxml.etree.ElementBase):
     def begin(self, stream):
+        stream.scope.append(set())
         stream.begin(self.clauses())
         
     def end(self, stream):
         stream.end(self.clauses())
+        stream.scope.pop()
 
     def body(self, stream):
         skip = self.replace or self.content or self.i18n_translate is not None
@@ -51,16 +52,14 @@
     def clauses(self):
         _ = []
 
-        scope = utils.scope()
-
         # i18n domain
         if self.i18n_domain is not None:
-            _.append(clauses.Define("_domain", [repr(self.i18n_domain)], scope))
+            _.append(clauses.Define("_domain", [repr(self.i18n_domain)]))
 
         # defines
         if self.define is not None:
             for variables, expression in self.define:
-                _.append(clauses.Define(variables, expression, scope))
+                _.append(clauses.Define(variables, expression))
 
         # condition
         if self.condition is not None:
@@ -71,7 +70,7 @@
             variables, expression = self.repeat
             if len(variables) != 1:
                 raise ValueError, "Cannot unpack more than one variable in a repeat statement."
-            _.append(clauses.Repeat(variables[0], expression, scope))
+            _.append(clauses.Repeat(variables[0], expression))
 
         # tag tail (deferred)
         if self.tail:
@@ -131,7 +130,7 @@
                     name = element.i18n_name
                     
                     subclauses = []
-                    subclauses.append(clauses.Define('_out', ['utils.initialize_stream()'], scope))
+                    subclauses.append(clauses.Define('_out', ['utils.initialize_stream()']))
                     subclauses.append(clauses.Group(element.clauses()))
                     subclauses.append(clauses.Assign(['_out.getvalue()'],
                                                      "%s['%s']" % (mapping, name)))
@@ -275,6 +274,8 @@
         
     stream = io.CodeIO(indentation=1, indentation_string="\t")
 
+    stream.scope.append(set(params + ['_out']))
+
     root.visit(stream)
 
     code = stream.getvalue()



More information about the Checkins mailing list