added first code for parser extensions and moved some code in speedups around

--HG--
branch : trunk
diff --git a/jinja2/nodes.py b/jinja2/nodes.py
index c579395..8c58959 100644
--- a/jinja2/nodes.py
+++ b/jinja2/nodes.py
@@ -63,7 +63,19 @@
             storage.extend(d.get(attr, ()))
             assert len(storage) == len(set(storage))
             d[attr] = tuple(storage)
-        return type.__new__(cls, name, bases, d)
+        rv = type.__new__(cls, name, bases, d)
+
+        # unless the node is a subclass of `CustomNode` it may not
+        # be defined in any other module than the jinja2.nodes module.
+        # the reason for this is that the we don't want users to take
+        # advantage of the fact that the parser is using the node name
+        # only as callback name for non custom nodes.  This could lead
+        # to broken code in the future and is disallowed because of this.
+        if rv.__module__ != 'jinja2.nodes' and not \
+           isinstance(rv, CustomStmt):
+            raise TypeError('non builtin node %r is not a subclass of '
+                            'CustomStmt.' % node.__class__.__name__)
+        return rv
 
 
 class Node(object):
@@ -193,6 +205,15 @@
     """Nodes that exist in a specific context only."""
 
 
+class CustomStmt(Stmt):
+    """Custom statements must extend this node."""
+
+    def compile(self, compiler):
+        """The compiler calls this method to get the python sourcecode
+        for the statement.
+        """
+
+
 class Template(Node):
     """Node that represents a template."""
     fields = ('body',)