'Compile a node or template source code.  The `name` parameter is
the load name of the template after it was joined using
:meth:`join_path` if necessary, not the filename on the file system.
the `filename` parameter is the estimated filename of the template on
the file system.  If the template came from a database or memory this
can be omitted.
The return value of this method is a python code object.  If the `raw`
parameter is `True` the return value will be a string with python
code equivalent to the bytecode returned otherwise.  This method is
mainly used internally.'

@internalcode
def compile(self, source, name=None, filename=None, raw=False):

    source_hint = None
    try:
        if isinstance(source, basestring):
            source_hint = source
            source = self._parse(source, name, filename)
        if self.optimized:
            source = optimize(source, self)
        source = generate(source, self, name, filename)
        if raw:
            return source
        if (filename is None):
            filename = '<template>'
        elif isinstance(filename, unicode):
            filename = filename.encode('utf-8')
        return compile(source, filename, 'exec')
    except TemplateSyntaxError:
        exc_info = sys.exc_info()
    self.handle_exception(exc_info, source_hint=source)
