all calls are proxied by context.call now so that we can inject environment and context as first arguments.  This slows calls down a bit but is a lot more user friendly.  Added first draft of FAQ

--HG--
branch : trunk
diff --git a/jinja2/compiler.py b/jinja2/compiler.py
index e43c362..83afc34 100644
--- a/jinja2/compiler.py
+++ b/jinja2/compiler.py
@@ -438,21 +438,13 @@
             self._write_debug_info = node.lineno
             self._last_line = node.lineno
 
-    def signature(self, node, frame, have_comma=True, extra_kwargs=None):
+    def signature(self, node, frame, extra_kwargs=None):
         """Writes a function call to the stream for the current node.
-        Per default it will write a leading comma but this can be
-        disabled by setting have_comma to False.  The extra keyword
+        A leading comma is added automatically.  The extra keyword
         arguments may not include python keywords otherwise a syntax
         error could occour.  The extra keyword arguments should be given
         as python dict.
         """
-        have_comma = have_comma and [True] or []
-        def touch_comma():
-            if have_comma:
-                self.write(', ')
-            else:
-                have_comma.append(True)
-
         # if any of the given keyword arguments is a python keyword
         # we have to make sure that no invalid call is created.
         kwarg_workaround = False
@@ -462,28 +454,25 @@
                 break
 
         for arg in node.args:
-            touch_comma()
+            self.write(', ')
             self.visit(arg, frame)
 
         if not kwarg_workaround:
             for kwarg in node.kwargs:
-                touch_comma()
+                self.write(', ')
                 self.visit(kwarg, frame)
             if extra_kwargs is not None:
                 for key, value in extra_kwargs.iteritems():
-                    touch_comma()
-                    self.write('%s=%s' % (key, value))
+                    self.write(', %s=%s' % (key, value))
         if node.dyn_args:
-            touch_comma()
-            self.write('*')
+            self.write(', *')
             self.visit(node.dyn_args, frame)
 
         if kwarg_workaround:
-            touch_comma()
             if node.dyn_kwargs is not None:
-                self.write('**dict({')
+                self.write(', **dict({')
             else:
-                self.write('**{')
+                self.write(', **{')
             for kwarg in node.kwargs:
                 self.write('%r: ' % kwarg.key)
                 self.visit(kwarg.value, frame)
@@ -499,8 +488,7 @@
                 self.write('}')
 
         elif node.dyn_kwargs is not None:
-            touch_comma()
-            self.write('**')
+            self.write(', **')
             self.visit(node.dyn_kwargs, frame)
 
     def pull_locals(self, frame):
@@ -1353,11 +1341,12 @@
 
     def visit_Call(self, node, frame, forward_caller=False):
         if self.environment.sandboxed:
-            self.write('environment.call(')
+            self.write('environment.call(context, ')
+        else:
+            self.write('context.call(')
         self.visit(node.node, frame)
-        self.write(self.environment.sandboxed and ', ' or '(')
         extra_kwargs = forward_caller and {'caller': 'caller'} or None
-        self.signature(node, frame, False, extra_kwargs)
+        self.signature(node, frame, extra_kwargs)
         self.write(')')
 
     def visit_Keyword(self, node, frame):
diff --git a/jinja2/nodes.py b/jinja2/nodes.py
index 568220f..9eb5460 100644
--- a/jinja2/nodes.py
+++ b/jinja2/nodes.py
@@ -14,7 +14,6 @@
 """
 import operator
 from copy import copy
-from types import FunctionType
 from itertools import chain, izip
 from collections import deque
 from jinja2.utils import Markup
@@ -550,11 +549,10 @@
 
         # don't evaluate context functions
         args = [x.as_const() for x in self.args]
-        if type(obj) is FunctionType:
-            if getattr(obj, 'contextfunction', False):
-                raise Impossible()
-            elif obj.environmentfunction:
-                args.insert(0, self.environment)
+        if getattr(obj, 'contextfunction', False):
+            raise Impossible()
+        elif getattr(obj, 'environmentfunction', False):
+            args.insert(0, self.environment)
 
         kwargs = dict(x.as_const() for x in self.kwargs)
         if self.dyn_args is not None:
diff --git a/jinja2/parser.py b/jinja2/parser.py
index 86ee570..8ca1bd2 100644
--- a/jinja2/parser.py
+++ b/jinja2/parser.py
@@ -150,6 +150,7 @@
         node = nodes.Block(lineno=self.stream.next().lineno)
         node.name = self.stream.expect('name').value
         node.body = self.parse_statements(('name:endblock',), drop_needle=True)
+        self.stream.skip_if('name:' + node.name)
         return node
 
     def parse_extends(self):
diff --git a/jinja2/runtime.py b/jinja2/runtime.py
index fb72ed4..1325b17 100644
--- a/jinja2/runtime.py
+++ b/jinja2/runtime.py
@@ -66,14 +66,6 @@
         self.exported_vars = set()
         self.name = name
 
-        # bind functions to the context of environment if required
-        for name, obj in parent.iteritems():
-            if type(obj) is FunctionType:
-                if getattr(obj, 'contextfunction', 0):
-                    vars[name] = partial(obj, self)
-                elif getattr(obj, 'environmentfunction', 0):
-                    vars[name] = partial(obj, environment)
-
         # create the initial mapping of blocks.  Whenever template inheritance
         # takes place the runtime will update this mapping with the new blocks
         # from the template.
@@ -122,6 +114,17 @@
         """
         return dict(self.parent, **self.vars)
 
+    def call(__self, __obj, *args, **kwargs):
+        """Called by the template code to inject the current context
+        or environment as first arguments.  Then forwards the call to
+        the object with the arguments and keyword arguments.
+        """
+        if getattr(__obj, 'contextfunction', 0):
+            args = (__self,) + args
+        elif getattr(__obj, 'environmentfunction', 0):
+            args = (__self.environment,) + args
+        return __obj(*args, **kwargs)
+
     def _all(meth):
         proxy = lambda self: getattr(self.get_all(), meth)()
         proxy.__doc__ = getattr(dict, meth).__doc__
diff --git a/jinja2/sandbox.py b/jinja2/sandbox.py
index c558c73..b0de8e7 100644
--- a/jinja2/sandbox.py
+++ b/jinja2/sandbox.py
@@ -190,13 +190,13 @@
                 ), name=argument, exc=SecurityError)
         return self.undefined(obj=obj, name=argument)
 
-    def call(__self, __obj, *args, **kwargs):
+    def call(__self, __context, __obj, *args, **kwargs):
         """Call an object from sandboxed code."""
         # the double prefixes are to avoid double keyword argument
         # errors when proxying the call.
         if not __self.is_safe_callable(__obj):
             raise SecurityError('%r is not safely callable' % (__obj,))
-        return __obj(*args, **kwargs)
+        return __context.call(__obj, *args, **kwargs)
 
 
 class ImmutableSandboxedEnvironment(SandboxedEnvironment):
diff --git a/jinja2/utils.py b/jinja2/utils.py
index 2a671d0..258961f 100644
--- a/jinja2/utils.py
+++ b/jinja2/utils.py
@@ -64,8 +64,8 @@
 
 def contextfunction(f):
     """This decorator can be used to mark a callable as context callable.  A
-    context callable is passed the active context as first argument if it
-    was directly stored in the context.
+    context callable is passed the active context as first argument when
+    called from the template.
     """
     f.contextfunction = True
     return f
@@ -74,7 +74,7 @@
 def environmentfunction(f):
     """This decorator can be used to mark a callable as environment callable.
     A environment callable is passed the current environment as first argument
-    if it was directly stored in the context.
+    when called from the template.
     """
     f.environmentfunction = True
     return f