loops and `tests` tests pass now

--HG--
branch : trunk
diff --git a/jinja2/compiler.py b/jinja2/compiler.py
index b7aae46..871728f 100644
--- a/jinja2/compiler.py
+++ b/jinja2/compiler.py
@@ -76,6 +76,9 @@
         # frames or because they are special for the frame)
         self.declared = set()
 
+        # undeclared variables from outer scopes
+        self.outer_undeclared = set()
+
         # names that are accessed without being explicitly declared by
         # this one or any of the outer scopes.  Names can appear both in
         # declared and undeclared.
@@ -106,7 +109,8 @@
 
     def find_shadowed(self):
         """Find all the shadowed names."""
-        return self.declared & (self.declared_locally | self.declared_parameter)
+        return (self.declared | self.outer_undeclared) & \
+               (self.declared_locally | self.declared_parameter)
 
 
 class Frame(object):
@@ -145,6 +149,10 @@
                 parent.identifiers.declared_locally |
                 parent.identifiers.declared_parameter
             )
+            self.identifiers.outer_undeclared.update(
+                parent.identifiers.undeclared -
+                self.identifiers.declared
+            )
             self.buffer = parent.buffer
             self.name_overrides = parent.name_overrides.copy()
 
diff --git a/jinja2/parser.py b/jinja2/parser.py
index 84a317c..8b82a4d 100644
--- a/jinja2/parser.py
+++ b/jinja2/parser.py
@@ -626,6 +626,8 @@
         else:
             negated = False
         name = self.stream.expect('name').value
+        dyn_args = dyn_kwargs = None
+        kwargs = []
         if self.stream.current.type is 'lparen':
             args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
         elif self.stream.current.type in ('name', 'string', 'integer',
@@ -634,8 +636,6 @@
             args = [self.parse_expression()]
         else:
             args = []
-            kwargs = []
-            dyn_args = dyn_kwargs = None
         node = nodes.Test(node, name, args, kwargs, dyn_args,
                           dyn_kwargs, lineno=token.lineno)
         if negated:
diff --git a/jinja2/runtime.py b/jinja2/runtime.py
index 1f1d7bd..e1bf486 100644
--- a/jinja2/runtime.py
+++ b/jinja2/runtime.py
@@ -142,8 +142,8 @@
     first = property(lambda x: x.index0 == 0)
     last = property(lambda x: x.revindex0 == 0)
     index = property(lambda x: x.index0 + 1)
-    revindex = property(lambda x: x.length)
-    revindex0 = property(lambda x: x.length - 1)
+    revindex = property(lambda x: x.length - x.index0)
+    revindex0 = property(lambda x: x.length - x.index)
 
     def __len__(self):
         return self.length
@@ -191,7 +191,8 @@
     """The static loop context is used in the optimizer to "freeze" the
     status of an iteration.  The only reason for this object is if the
     loop object is accessed in a non static way (eg: becomes part of a
-    function call)."""
+    function call).
+    """
 
     def __init__(self, index0, length):
         self.index0 = index0