diff --git a/core/includes/common.inc b/core/includes/common.inc
index 0f252ca..613b180 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -5774,6 +5774,9 @@ function drupal_render_children(&$element, $children_keys = NULL) {
  * @see hide()
  */
 function render(&$element) {
+  if (!$element && $element !== 0) {
+    return null;
+  }
   if (is_array($element)) {
     show($element);
     return drupal_render($element);
diff --git a/core/includes/file.inc b/core/includes/file.inc
index 977d186..8112d7b 100644
--- a/core/includes/file.inc
+++ b/core/includes/file.inc
@@ -1441,7 +1441,7 @@ function file_scan_directory($dir, $mask, $options = array(), $depth = 0) {
 
   $options['key'] = in_array($options['key'], array('uri', 'filename', 'name')) ? $options['key'] : 'uri';
   $files = array();
-  if (is_dir($dir) && $handle = opendir($dir)) {
+  if (is_dir($dir) && $handle = @opendir($dir)) {
     while (FALSE !== ($filename = readdir($handle))) {
       if (!preg_match($options['nomask'], $filename) && $filename[0] != '.') {
         $uri = "$dir/$filename";
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 3c4576a..64022b3 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -229,6 +229,12 @@ function _drupal_theme_initialize($theme, $base_theme = array(), $registry_callb
       include_once DRUPAL_ROOT . '/' . $theme->owner;
     }
   }
+  // Load twig as secondary always available engine.
+  // @todo Make twig the default engine and remove this. This is required
+  // because (by design) the theme system doesn't allow modules to register more
+  // than one type of extension. We need a temporary backwards compatibility
+  // layer to allow us to perform core-wide .tpl.php to .twig conversion.
+  include_once DRUPAL_ROOT . '/core/themes/engines/twig/twig.engine';
 
   if (isset($registry_callback)) {
     _theme_registry_callback($registry_callback, array($theme, $base_theme, $theme_engine));
@@ -468,6 +474,28 @@ function _theme_process_registry(&$cache, $name, $type, $theme, $path) {
         if (!isset($info['path'])) {
           $result[$hook]['template'] = $path . '/templates/' . $info['template'];
         }
+        if ($type == 'module') {
+          // Add two render engines for modules.
+          // @todo Remove and make twig the default engine.
+          $render_engines = array(
+            '.twig' => 'twig',
+            '.tpl.php' => 'phptemplate'
+          );
+
+          // Find the best engine for this template.
+          foreach ($render_engines as $extension => $engine) {
+            // Render the output using the template file.
+            $template_file = $result[$hook]['template'] . $extension;
+            if (isset($info['path'])) {
+              $template_file = $info['path'] . '/' . $template_file;
+            }
+            if (file_exists($template_file)) {
+              $result[$hook]['template_file'] = $template_file;
+              $result[$hook]['engine'] = $engine;
+              break;
+            }
+          }
+        }
       }
 
       // Allow variable processors for all theming hooks, whether the hook is
@@ -1054,6 +1082,11 @@ function theme($hook, $variables = array()) {
           $extension = $extension_function();
         }
       }
+      elseif (isset($info['engine'])) {
+        if (function_exists($info['engine'] . '_render_template')) {
+          $render_function = $info['engine'] . '_render_template';
+        }
+      }
     }
 
     // In some cases, a template implementation may not have had
@@ -1077,6 +1110,12 @@ function theme($hook, $variables = array()) {
     if (isset($info['path'])) {
       $template_file = $info['path'] . '/' . $template_file;
     }
+
+    // Modules can override this.
+    if (isset($info['template_file'])) {
+      $template_file = $info['template_file'];
+    }
+
     $output = $render_function($template_file, $variables);
   }
 
@@ -1252,7 +1291,14 @@ function drupal_find_theme_templates($cache, $extension, $path) {
       $matches = preg_grep('/^' . $pattern . '/', $patterns);
       if ($matches) {
         foreach ($matches as $match) {
-          $file = substr($match, 0, strpos($match, '.'));
+          $file = $match;
+          // Chop off the remaining extensions if there are any. $template
+          // already has the rightmost extension removed, but there might still
+          // be more, such as with .tpl.php, which still has .tpl in $template
+          // at this point.
+          if (($pos = strpos($match, '.')) !== FALSE) {
+            $file = substr($match, 0, $pos);
+          }
           // Put the underscores back in for the hook name and register this pattern.
           $arg_name = isset($info['variables']) ? 'variables' : 'render element';
           $implementations[strtr($file, '-', '_')] = array(
@@ -2912,6 +2958,7 @@ function drupal_common_theme() {
     ),
     'datetime' => array(
       'variables' => array('timestamp' => NULL, 'text' => NULL, 'attributes' => array(), 'html' => FALSE),
+      'template' => 'datetime',
     ),
     'status_messages' => array(
       'variables' => array('display' => NULL),
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index f1e43d6..19a49f5 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -60,6 +60,9 @@ public function build(ContainerBuilder $container) {
     $container->register('user.tempstore', 'Drupal\user\TempStoreFactory')
       ->addArgument(new Reference('database'))
       ->addArgument(new Reference('lock'));
+    $container->register('twig', 'Drupal\Core\Template\TwigEnvironment')
+      ->setFactoryClass('Drupal\Core\Template\TwigFactory')
+      ->setFactoryMethod('get');
 
     $container->register('router.dumper', '\Drupal\Core\Routing\MatcherDumper')
       ->addArgument(new Reference('database'));
diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php
new file mode 100644
index 0000000..4851919
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\TwigEnvironment.
+ */
+
+namespace Drupal\Core\Template;
+
+/**
+ * @todo Document me! Pleeeeease :)
+ */
+class TwigEnvironment extends \Twig_Environment {
+  protected $cacheO = NULL;
+  protected $storage = NULL;
+
+  public function __construct(\Twig_LoaderInterface $loader = null, $options = array()) {
+    // @todo Pass as arguments from the DIC?
+    $this->cacheO = cache();
+    $this->storage = drupal_php_storage('twig');
+
+    parent::__construct($loader, $options);
+  }
+
+
+  /**
+   * Implements Twig_Environment::loadTemplate().
+   *
+   * We need to overwrite this function to integrate with drupal_php_storage().
+   *
+   * This is a straight copy from loadTemplate() changed to use
+   * drupal_php_storage().
+   */
+  public function loadTemplate($name, $index = null) {
+    $cls = $this->getTemplateClass($name, $index);
+
+    if (isset($this->loadedTemplates[$cls])) {
+      return $this->loadedTemplates[$cls];
+    }
+
+    if (!class_exists($cls, false)) {
+      if (false === $cache = $this->getCacheFilename($name)) {
+        eval('?' . '>' . $this->compileSource($this->loader->getSource($name), $name));
+      } else {
+        $cid = 'twig:' . $cache;
+        $obj = $this->cacheO->get($cid);
+        $mtime = isset($obj->data) ? $obj->data : FALSE;
+
+        if (!$mtime || !$this->storage->exists($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, $mtime))) {
+          $this->storage->save($cache, $this->compileSource($this->loader->getSource($name), $name));
+          // Save the last modification time
+          $this->cacheO->set($cid, REQUEST_TIME);
+        }
+
+        $this->storage->load($cache);
+      }
+    }
+
+    if (!$this->runtimeInitialized) {
+        $this->initRuntime();
+    }
+
+    return $this->loadedTemplates[$cls] = new $cls($this);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Template/TwigFactory.php b/core/lib/Drupal/Core/Template/TwigFactory.php
new file mode 100644
index 0000000..727e4b2
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/TwigFactory.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\TwigFactory.
+ *
+ * This provides a factory class to construct Twig_Environment objects and use
+ * them in combination with the Drupal Injection Container.
+ *
+ * @see \Drupal\Core\CoreBundle
+ */
+
+namespace Drupal\Core\Template;
+
+/**
+ * A class for constructing Twig_Environment objects.
+ *
+ * This is used for constructing and configuring a system wide Twig_Environment
+ * object that is integrated with the Drupal Injection Container.
+ *
+ * @see \Drupal\Core\CoreBundle
+ */
+class TwigFactory {
+  /**
+  * Returns a fully initialized Twig_Environment object.
+  *
+  * This constructs and configures a Twig_Environment. It also adds Drupal
+  * specific Twig_NodeVisitors, filters and functions.
+  *
+  * To retrieve the system wide Twig_Environment object you should use:
+  * @code
+  *   $twig = drupal_container()->get('twig');
+  * @endcode
+  * This will retrieve the Twig_Environment object from the DIC.
+  *
+  * @return Twig_Environment
+  *   The fully initialized Twig_Environment object.
+  *
+  * @see twig_render
+  * @see TwigNodeVisitor
+  * @see TwigReference
+  * @see TwigReferenceFunction
+  */
+  public static function get() {
+    // @todo Maybe we will have our own loader later.
+    $loader = new \Twig_Loader_Filesystem(DRUPAL_ROOT);
+    $twig = new TwigEnvironment($loader, array(
+        // This is saved / loaded via drupal_php_storage().
+        // All files can be refreshed via drush cc all.
+        // @todo ensure garbage collection of expired files
+        'cache' => TRUE,
+        'base_template_class' => 'Drupal\Core\Template\TwigTemplate',
+        // @todo Remove in followup issue.
+        'autoescape' => FALSE,
+        // @todo Remove in followup issue to handle exceptions gracefully.
+        'strict_variables' => FALSE,
+        // @todo Maybe make debug mode dependent on "production mode" setting
+        'debug' => TRUE,
+    ));
+
+    // The node visitor is needed to wrap all variables with
+    // render -> twig_render() function.
+    $twig->addNodeVisitor(new TwigNodeVisitor());
+    $twig->addTokenParser(new TwigFunctionTokenParser('hide'));
+    $twig->addTokenParser(new TwigFunctionTokenParser('show'));
+
+    // @todo Figure out what to do about debugging functions.
+    // @see http://drupal.org/node/1804998
+    $twig->addExtension(new \Twig_Extension_Debug());
+
+    $reference_functions = array(
+      'hide' => 'twig_hide',
+      'render' => 'twig_render',
+      'show' => 'twig_show',
+      // @todo re-add unset => twig_unset if this is really needed
+    );
+    $filters = array(
+      't' => 't'
+    );
+
+    // These functions will receive a TwigReference object, if a render array is detected
+    foreach ($reference_functions as $function => $php_function) {
+      $twig->addFunction($function, new TwigReferenceFunction($php_function));
+    }
+
+    foreach ($filters as $filter => $php_function) {
+      $twig->addFilter($filter, new \Twig_Filter_Function($php_function));
+    }
+
+    // @todo Remove URL function once http://drupal.org/node/1778610 is resolved.
+    $twig->addFunction('url', new \Twig_Function_Function('url'));
+    return $twig;
+  }
+}
diff --git a/core/lib/Drupal/Core/Template/TwigFunctionTokenParser.php b/core/lib/Drupal/Core/Template/TwigFunctionTokenParser.php
new file mode 100644
index 0000000..5291d95
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/TwigFunctionTokenParser.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\TwigFunctionTokenParser.
+ */
+
+namespace Drupal\Core\Template;
+
+/**
+ * @todo Document me!
+ */
+class TwigFunctionTokenParser extends \Twig_TokenParser {
+
+  /**
+   * @todo Document me!
+   */
+  protected $tag;
+
+  /**
+   * @todo Document me!
+   */
+  public function __construct($tag = 'hide') {
+    $this->tag = $tag;
+  }
+
+  /**
+   * @todo Document me!
+   */
+  public function parse(\Twig_Token $token) {
+    $lineno = $token->getLine();
+
+    $expr = $this->parser->getExpressionParser()->parseExpression();
+    $this->parser->getStream()->expect(\Twig_Token::BLOCK_END_TYPE);
+    return new \Twig_Node_Print(new \Twig_Node_Expression_Function($this->tag, new \Twig_Node(array($expr)), $lineno), $lineno);
+  }
+
+  /**
+   * @todo Document me!
+   */
+  public function getTag() {
+    return $this->tag;
+  }
+}
diff --git a/core/lib/Drupal/Core/Template/TwigNodeExpressionNameReference.php b/core/lib/Drupal/Core/Template/TwigNodeExpressionNameReference.php
new file mode 100644
index 0000000..a841df2
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/TwigNodeExpressionNameReference.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\TwigNodeExpressionNameReference
+ */
+
+namespace Drupal\Core\Template;
+
+/**
+ * @todo Document me!
+ */
+class TwigNodeExpressionNameReference extends \Twig_Node_Expression_Name {
+  /**
+   * @todo document me
+   */
+  public function compile(\Twig_Compiler $compiler) {
+    $name = $this->getAttribute('name');
+    $compiler
+    ->raw('$this->getContextReference($context, ')
+    ->string($name)
+    ->raw(')');
+  }
+}
diff --git a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
new file mode 100644
index 0000000..f08f071
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
@@ -0,0 +1,93 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\TwigNodeVisitor.
+ */
+
+namespace Drupal\Core\Template;
+
+/**
+ * Provides a Twig_NodeVisitor to change the generated parse-tree.
+ *
+ * This is used to ensure that everything that is printed is wrapped via
+ * twig_render() function so that we can write for example just {{ content }}
+ * in templates instead of having to write {{ render(content) }}.
+ *
+ * @see twig_render
+ */
+class TwigNodeVisitor implements \Twig_NodeVisitorInterface {
+
+  /**
+   * @todo document me
+   */
+  protected $isReference = FALSE;
+
+  /**
+   * Implements Twig_NodeVisitorInterface::enterNode().
+   */
+  function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) {
+
+   // @todo Document this
+   if ($node instanceof \Twig_Node_Expression_Function) {
+      $name = $node->getAttribute('name');
+      $func = $env->getFunction($name);
+
+      // Optimization: Do not support nested functions.
+      if ($this->isReference && $func instanceof \Twig_Function_Function) {
+        $this->isReference = FALSE;
+      }
+      if ($func instanceof TwigReferenceFunction) {
+        // We need to create a TwigReference
+        $this->isReference = TRUE;
+      }
+    }
+    if ($node instanceof \Twig_Node_Print) {
+       // Our injected render needs arguments passed by reference -- in case of render array
+      $this->isReference = TRUE;
+    }
+
+    return $node;
+  }
+
+  /**
+   * Implements Twig_NodeVisitorInterface::leaveNode().
+   *
+   * We use this to inject a call to render -> twig_render()
+   * before anything is printed.
+   *
+   * @see twig_render
+   */
+  function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) {
+    if ($node instanceof \Twig_Node_Print) {
+      $this->isReference = FALSE;
+
+      $class = get_class($node);
+      return new $class(
+        new \Twig_Node_Expression_Function('render', new \Twig_Node(array($node->getNode('expr'))), $node->getLine()),
+        $node->getLine()
+      );
+    }
+
+    if ($this->isReference) {
+      if ( $node instanceof \Twig_Node_Expression_Name) {
+        $name = $node->getAttribute('name');
+        return new TwigNodeExpressionNameReference($name, $node->getLine());
+      }
+      elseif ($node instanceof \Twig_Function_Function) {
+        // Do something!
+        $this->isReference = FALSE;
+      }
+    }
+
+    return $node;
+  }
+
+  /**
+   * Implements Twig_NodeVisitorInterface::getPriority().
+   */
+  function getPriority() {
+    // We want to run before other NodeVisitors like Escape or Optimizer
+    return -1;
+  }
+}
diff --git a/core/lib/Drupal/Core/Template/TwigReference.php b/core/lib/Drupal/Core/Template/TwigReference.php
new file mode 100644
index 0000000..0b8b506
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/TwigReference.php
@@ -0,0 +1,131 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\TwigReference.
+ */
+
+namespace Drupal\Core\Template;
+
+/**
+ * A class used to pass variables by reference while they are used in twig.
+ *
+ * This is done by saving a reference to the original render array within a
+ * TwigReference via the setReference() method like this:
+ * @code
+ * $obj = new TwigReference();
+ * $obj->setReference($variable);
+ * @endcode
+ *
+ * When a TwigReference is accessed via the offsetGet method the resulting
+ * reference is again wrapped within a TwigReference. Therefore references to
+ * render arrays within render arrays are also retained.
+ *
+ * To unwrap TwigReference objects the reference can be retrieved out of the
+ * object by calling the getReference() method like this:
+ * @code
+ * $variable = &$obj->getReference();
+ * @endcode
+ * This allows render(), hide() and show() to access the original variable and
+ * change it. The process of unwrapping and passing by reference to this
+ * functions is done transparently by the TwigReferenceFunctions helper class.
+ *
+ * @see TwigReferenceFunction
+ * @see TwigReferenceFunctions
+ */
+class TwigReference extends \ArrayObject {
+
+  /**
+   * Holds an internal reference to the original array.
+   *
+   * @var array
+   */
+  protected $writableRef = array();
+
+  /**
+   * Constructs a \Drupal\Core\Template\TwigReference object.
+   *
+   * The argument to the constructor is ignored as it is not safe that this will
+   * always be a reference.
+   *
+   * To set a reference use:
+   * @code
+   * $obj = new TwigReference();
+   * $obj->setReference($variable);
+   * @endcode
+   *
+   * @param $array
+   *   The array parameter is ignored and not passed to the parent
+   */
+  public function __construct($array = NULL) {
+    parent::__construct();
+  }
+
+  /**
+   * Sets a reference in the internal storage.
+   *
+   * @param $array
+   *   The array to set as internal reference.
+   */
+  public function setReference(&$array) {
+    $this->exchangeArray($array);
+    $this->writableRef = &$array;
+  }
+
+  /**
+   * Gets a reference to the internal storage.
+   *
+   * Should be called like:
+   * @code
+   * $reference = &$obj->getReference();
+   * @endcode
+   *
+   * @return
+   *   Returns the stored internal reference.
+   */
+  public function &getReference() {
+    return $this->writableRef;
+  }
+
+  /**
+   * Sets offset in internal reference and internal storage to value.
+   *
+   * This is just for completeness, but should never be used, because
+   * twig cannot set properties and should not.
+   *
+   * @link http://php.net/manual/en/arrayaccess.offsetset.php
+   * @param mixed $offset
+   *   The offset to assign the value to.
+   * @param mixed $value
+   *   The value to set.
+   */
+  public function offsetSet($offset, $value) {
+    $this->writableRef[$offset] = $value;
+    parent::offsetSet($offset, $value);
+  }
+
+  /**
+   * Retrieves offset from internal reference.
+   *
+   * In case of a render array, it is wrapped again within a TwigReference
+   * object.
+   *
+   * @param mixed $offset
+   *   The offset to retrieve.
+   *
+   * @return mixed
+   *   Returns a TwigReference object wrapping the array if the retrieved offset
+   *   is a complex array (i.e. not an attribute). Else it returns the retrived
+   *   offset directly.
+   */
+  public function offsetGet($offset) {
+    if (!is_array($this->writableRef[$offset]) || $offset[0] == '#') {
+      return $this->writableRef[$offset];
+    }
+
+    // Wrap the returned array in a new TwigReference.
+    $x = clone $this; // clone is faster than new
+    $x->setReference($this->writableRef[$offset]);
+    return $x;
+  }
+}
diff --git a/core/lib/Drupal/Core/Template/TwigReferenceFunction.php b/core/lib/Drupal/Core/Template/TwigReferenceFunction.php
new file mode 100644
index 0000000..5fed071
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/TwigReferenceFunction.php
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\TwigReferenceFunction.
+ */
+
+namespace Drupal\Core\Template;
+
+/**
+ * @todo Document me!
+ */
+class TwigReferenceFunction extends \Twig_Function_Function {
+}
diff --git a/core/lib/Drupal/Core/Template/TwigReferenceFunctions.php b/core/lib/Drupal/Core/Template/TwigReferenceFunctions.php
new file mode 100644
index 0000000..bb7ea1d
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/TwigReferenceFunctions.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\TwigReferenceFunctions.
+ */
+
+namespace Drupal\Core\Template;
+
+/**
+ * A class used as a helper to unwrap TwigReference objects and pass a
+ * reference of the original variable to the called function.
+ *
+ * This is providing a static magic function that makes it easier to unwrap
+ * TwigReference objects and pass variables by reference to show(), hide() and
+ * render().
+ *
+ * The problem is that twig passes variables only by value. The following is a
+ * simplified version of the generated code by twig when the property "links" of
+ * a render array stored in $content should be hidden:
+ * @code
+ * $_content_ = $content;
+ * hide(getAttribute($_content_, 'links'));
+ * @endcode
+ * As hide() is operating on a copy of the original array the hidden property
+ * is not set on the original $content variable.
+ *
+ * TwigReferenceFunctions can be used in combination with TwigReference to solve
+ * this problem:
+ * @code
+ * // Internally getContextReference returns the array wrapped in a
+ * // TwigReference if certain criteria are met
+ * function getContextReference(&$content) {
+ *   $obj = new Drupal\Core\Template\TwigReference();
+ *   $obj->setReference($content);
+ *   return $obj;
+ * }
+ *
+ * // [...]
+ * // Simplified, generated twig code
+ * $_content_ = getContextReference($content);
+ *
+ * Drupal\Core\Template\TwigReferenceFunctions::hide(
+ *   getAttribute($_content_, 'links')
+ * );
+ * @endcode
+ * A TwigReference object is passed to the __callStatic function of
+ * TwigReferenceFunctions. The method unwraps the TwigReference and calls the
+ * hide() method essentially with a reference to $content['links'].
+ *
+ * Therefore the hidden property is correctly set and a successive call to
+ * render() will not render the content twice.
+ *
+ * @see TwigReference
+ * @see TwigReferenceFunction
+ * @see TwigFactory
+ *
+ */
+class TwigReferenceFunctions {
+
+  /**
+   * Magic function to call functions called from twig templates with a
+   * reference to the original variable.
+   *
+   * This checks if the array provided by value is containing a reference to
+   * the original version. If yes it replaces the argument with its reference.
+   *
+   * @param $name
+   *   The name of the function to call.
+   * @param $arguments
+   *   The arguments to process and pass to the called function.
+   *
+   * @return mixed
+   *   Returns the output of the called function.
+   *
+   * @see TwigReference
+  */
+  public static function __callStatic($name, $arguments) {
+    foreach ($arguments as $key => $val) {
+      if (is_object($val) && $val instanceof TwigReference) {
+        $arguments[$key] = &$val->getReference();
+      }
+    }
+
+    // Needed to pass by reference -- could also restrict to maximum one
+    // argument instead
+    $args = array();
+    foreach ($arguments as $key => &$arg) {
+      $args[$key] = &$arg;
+    }
+
+    return call_user_func_array($name, $args);
+  }
+}
diff --git a/core/lib/Drupal/Core/Template/TwigTemplate.php b/core/lib/Drupal/Core/Template/TwigTemplate.php
new file mode 100644
index 0000000..b23892c
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/TwigTemplate.php
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\TwigTemplate.
+ */
+
+namespace Drupal\Core\Template;
+
+/**
+ * @todo Document me!
+ */
+abstract class TwigTemplate extends \Twig_Template {
+
+  // @todo: Document me
+  private $twig_reference = NULL;
+
+  // This assumes that no template uses a top level var once as render array, once as normal var
+  protected $is_reference = array();
+  protected $is_no_reference = array();
+
+  /**
+   * @todo Document me!
+   */ 
+  final protected function getContextReference(&$context, $item, $ignoreStrictCheck = TRUE)
+  {
+    // Optimized version
+    if (!isset($context[$item])) {
+      // We don't want to throw an exception, but issue a warning instead.
+      // This is the easiest way to do so.
+      // @todo Decide based on prod vs. dev setting
+      $msg = new \Twig_Error(t('@item could not be found in _context.', array('@item' => $item)));
+      drupal_set_message($msg->getMessage(), 'warning');
+      return null;
+    }
+
+    // The first test also finds empty / null render arrays
+    if (!$context[$item] || isset($this->is_no_reference[$item])) {
+      return $context[$item];
+    }
+
+    if (isset($context['_references'][$item])) {
+      return $context['_references'][$item];
+    }
+
+    // @todo Check if this is a render array (existence of #theme?)
+    if ((!isset($this->is_reference[$item])) && ($context[$item] instanceof \TwigMarkup || !is_array($context[$item]))) {
+      $this->is_no_reference[$item] = TRUE;
+      return $context[$item];
+    }
+
+    if ($this->twig_reference == NULL) {
+      $this->twig_reference = new TwigReference();
+    }
+    $ref = clone $this->twig_reference; // clone is _much_ faster than new
+    $ref->setReference($context[$item]);
+
+    // Save that this is a reference
+    $context['_references'][$item] = $ref;
+    $this->is_reference[$item] = TRUE;
+
+    return $ref;
+  }
+}
diff --git a/core/modules/node/templates/node.twig b/core/modules/node/templates/node.twig
new file mode 100644
index 0000000..60e9cdb
--- /dev/null
+++ b/core/modules/node/templates/node.twig
@@ -0,0 +1,109 @@
+{#
+/**
+ * @file
+ * Default theme implementation to display a node.
+ *
+ * Available variables:
+ * - label: the (sanitized) title of the node.
+ * - content: An array of node items. Use {{ content }} to print them all,
+ *   or print a subset such as {{ content.field_example }}. Use
+ *   {% hide(content.field_example) %} to temporarily suppress the printing
+ *   of a given element.
+ * - user_picture: The node author's picture from user-picture.twig.
+ * - date: Formatted creation date. Preprocess functions can reformat it by
+ *   calling format_date() with the desired parameters on the $created variable.
+ * - name: Themed username of node author output from theme_username().
+ * - node_url: Direct URL of the current node.
+ * - display_submitted: Whether submission information should be displayed.
+ * - submitted: Submission information created from $name and $date during
+ *   template_preprocess_node().
+ * - attributes: An instance of Attributes class that can be manipulated as an
+ *    array and printed as a string.
+ *    It includes the 'class' information, which includes:
+ *   - node: The current template type; for example, "theming hook".
+ *   - node-[type]: The current node type. For example, if the node is a
+ *     "Article" it would result in "node-article". Note that the machine
+ *     name will often be in a short form of the human readable label.
+ *   - view-mode-[view_mode]: The View Mode of the node; for example, "teaser"
+ *     or "full".
+ *   - preview: Nodes in preview mode.
+ *   The following are controlled through the node publishing options.
+ *   - promoted: Nodes promoted to the front page.
+ *   - sticky: Nodes ordered above other non-sticky nodes in teaser
+ *     listings.
+ *   - unpublished: Unpublished nodes visible only to administrators.
+ * - title_prefix: Additional output populated by modules, intended to be
+ *   displayed in front of the main title tag that appears in the template.
+ * - title_suffix: Additional output populated by modules, intended to be
+ *   displayed after the main title tag that appears in the template.
+ *
+ * Other variables:
+ * - node: Full node entity. Contains data that may not be safe.
+ * - type: Node type; for example, page, article, etc.
+ * - comment_count: Number of comments attached to the node.
+ * - uid: User ID of the node author.
+ * - created: Time the node was published formatted in Unix timestamp.
+ * - zebra: Outputs either "even" or "odd". Useful for zebra striping in
+ *   teaser listings.
+ * - id: Position of the node. Increments each time it's output.
+ *
+ * Node status variables:
+ * - view_mode: View mode; for example, "teaser" or "full".
+ * - teaser: Flag for the teaser state (shortcut for $view_mode == 'teaser').
+ * - page: Flag for the full page state.
+ * - promote: Flag for front page promotion state.
+ * - sticky: Flags for sticky post setting.
+ * - status: Flag for published status.
+ * - comment: State of comment settings for the node.
+ * - readmore: Flags true if the teaser content of the node cannot hold the
+ *   main body content.
+ * - is_front: Flags true when presented in the front page.
+ * - logged_in: Flags true when the current user is a logged-in member.
+ * - is_admin: Flags true when the current user is an administrator.
+ *
+ * Field variables: for each field instance attached to the node a corresponding
+ * variable is defined; for example, $node->body becomes body. When needing to
+ * access a field's raw values, developers/themers are strongly encouraged to
+ * use these variables. Otherwise they will have to explicitly specify the
+ * desired field language; for example, $node->body['en'], thus overriding any
+ * language negotiation rule that was previously applied.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_node()
+ *
+ * @ingroup themeable
+ */
+#}
+{#
+  @todo: might be a good idea to remove the id attribute, because if that gets
+  rendered twice on a page this is invalid CSS
+  for example: two lists in different view modes.
+#}
+<article id="node-{{ node.nid }}" class="{{ attributes.class }} clearfix" {{- attributes }}>
+
+  {{ title_prefix }}
+  {% if page != true %}
+    <h2 {{- title_attributes }}>
+      <a href="{{ node_url }}" rel="bookmark">{{ label }}</a>
+    </h2>
+  {% endif %}
+  {{ title_suffix }}
+
+  {% if display_submitted %}
+    <footer>
+      {{ user_picture }}
+      <p class="submitted">{{ submitted }}</p>
+    </footer>
+  {% endif %}
+
+  <div class="content" {{- content_attributes }}>
+    {# We hide the comments and links now so that we can render them later. #}
+    {% hide(content.comments) %}
+    {% hide(content.links) %}
+    {{ content }}
+  </div>
+
+  {{ content.links }}
+  {{ content.comments }}
+
+</article>
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
index 484d00b..ce74a93 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
@@ -187,4 +187,19 @@ function testRegistryRebuild() {
   function testClassLoading() {
     new ThemeClass();
   }
+
+  /**
+   * Tests drupal_find_theme_templates().
+   */
+  public function testFindThemeTemplates() {
+    $cache = array();
+
+    // Prime the theme cache.
+    foreach (module_implements('theme') as $module) {
+      _theme_process_registry($cache, $module, 'module', $module, drupal_get_path('module', $module));
+    }
+
+    $templates = drupal_find_theme_templates($cache, '.tpl.php', drupal_get_path('theme', 'test_theme'));
+    $this->assertEqual($templates['node__1']['template'], 'node--1', 'Template node--1.tpl.php was found in test_theme.');
+  }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTestTwig.php b/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTestTwig.php
new file mode 100644
index 0000000..6a9d988
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTestTwig.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Theme\ThemeTest.
+ */
+
+namespace Drupal\system\Tests\Theme;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests low-level theme functions.
+ */
+class ThemeTestTwig extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('theme_test');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Twig Engine',
+      'description' => 'Test theme functions with twig.',
+      'group' => 'Theme',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    theme_enable(array('test_theme_twig'));
+  }
+
+  /**
+   * Ensures a themes template is overrideable based on the 'template' filename.
+   */
+  function testTemplateOverride() {
+    variable_set('theme_default', 'test_theme_twig');
+    $this->drupalGet('theme-test/template-test');
+    $this->assertText('Success: Template overridden.', t('Template overridden by defined \'template\' filename.'));
+  }
+
+  /**
+   * Tests drupal_find_theme_templates
+   */
+  function testFindThemeTemplates() {
+
+    $cache = array();
+
+    // Prime the theme cache
+    foreach (module_implements('theme') as $module) {
+      _theme_process_registry($cache, $module, 'module', $module, drupal_get_path('module', $module));
+    }
+
+    // Check for correct content
+    // @todo Remove this tests once double engine code is removed
+
+    $this->assertEqual($cache['node']['template_file'], 'core/modules/node/templates/node.twig', 'Node is using node.twig as template file');
+    $this->assertEqual($cache['node']['engine'], 'twig', 'Node is using twig engine');
+
+    $this->assertEqual($cache['theme_test_template_test']['template_file'], 'core/modules/system/tests/modules/theme_test/templates/theme_test.template_test.tpl.php', 'theme_test is using theme_test.template_test.tpl.php as template file');
+    $this->assertEqual($cache['theme_test_template_test']['engine'], 'phptemplate', 'theme_test is using phptemplate as engine.');
+
+    $templates = drupal_find_theme_templates($cache, '.twig', drupal_get_path('theme', 'test_theme_twig'));
+    $this->assertEqual($templates['node__1']['template'], 'node--1', 'Template node--1.twig was found in test_theme_twig.');
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/TwigReferenceObjectTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigReferenceObjectTest.php
new file mode 100644
index 0000000..88a4d22
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigReferenceObjectTest.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Theme\TwigReferenceObjectTest.
+ */
+
+namespace Drupal\system\Tests\Theme;
+
+/**
+ * TwigReferenceObjectTest class.
+ */
+class TwigReferenceObjectTest {
+  public function __construct($nid, $title) {
+    $this->nid = $nid;
+    $this->title = $title;
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/TwigReferenceUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigReferenceUnitTest.php
new file mode 100644
index 0000000..0f9534e
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigReferenceUnitTest.php
@@ -0,0 +1,147 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Theme\TwigReferenceUnitTest.
+ */
+
+namespace Drupal\system\Tests\Theme;
+
+use Drupal\simpletest\UnitTestBase;
+use Drupal\Core\Template\TwigReference;
+use Drupal\Core\Template\TwigReferenceFunctions;
+
+/**
+ * Unit tests for TwigReference class.
+ */
+class TwigReferenceUnitTest extends UnitTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Theme Twig References',
+      'description' => 'Tests TwigReference functions',
+      'group' => 'Theme',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    $this->variables = array(
+      'foo' => 'bar',
+      'baz' => array(
+        'foo' => '42',
+        'bar' => '23',
+      ),
+      'node' => new TwigReferenceObjectTest(
+        42,
+        'test node'
+      )
+    );
+  }
+
+  /**
+   * Test function for TwigReference class
+   */
+  function testTwigReference() {
+    // Create a new TwigReference wrapper
+    $wrapper = new TwigReference();
+    $wrapper->setReference($this->variables);
+
+    // Check that strings are returned as strings
+    $foo = $wrapper['foo'];
+    $this->assertEqual($foo, $this->variables['foo'], 'String returned from TwigReference is the same');
+    $this->assertTrue(is_string($foo), 'String returned from TwigReference is of type string');
+
+    // Check that arrays are wrapped again as TwigReference objects
+    $baz = $wrapper['baz'];
+    $this->assertTrue(is_object($baz), 'Array returned from TwigReference is of type object');
+    $this->assertTrue($baz instanceof TwigReference, 'Array returned from TwigReference is instance of TwigReference');
+
+    // Check that getReference is giving back a reference to the original array
+
+    $ref = &$baz->getReference();
+    $this->assertTrue(is_array($ref), 'getReference returns an array');
+
+    // Now modify $ref
+    $ref['#hidden'] = TRUE;
+    $this->assertEqual($ref['#hidden'], $this->variables['baz']['#hidden'], 'Property set on reference is passed to original array.');
+    $this->assertEqual($ref['#hidden'], $baz['#hidden'], 'Property set on reference is passed to wrapper.');
+
+    // Now modify $baz
+    $baz['hi'] = 'hello';
+
+    $this->assertEqual($baz['hi'], $this->variables['baz']['hi'], 'Property set on TwigReference object is passed to original array.');
+    $this->assertEqual($baz['hi'], $ref['hi'], 'Property set on TwigReference object is passed to reference.');
+
+    // Check that an object is passed through directly
+    $node = $wrapper['node'];
+    $this->assertTrue(is_object($node), 'Object returned from TwigReference is of type object');
+    $this->assertTrue($node instanceof TwigReferenceObjectTest, 'Object returned from TwigReference is instance of TwigReferenceObjectTest');
+  }
+
+  /**
+   * Test function for TwigReferenceFunctions class
+   */
+  function testTwigReferenceFunctions() {
+
+    // Create wrapper
+    $content = &$this->variables;
+
+    // Use twig nomenclature
+    $context['content'] = $content;
+
+    // Twig converts {{ hide(content.baz) }} to the following code
+
+    // This will have failed, because getAttribute returns a value and not a reference
+
+    try {
+      if (isset($context["content"])) {
+        $_content_ = $context["content"];
+      }
+      else {
+        $_content_ = NULL;
+      }
+      TwigReferenceFunctions::hide($this->getAttribute($_content_, "baz"));
+    }
+    catch (Exception $e) {
+      // Catch the critical warning that a value was passed by reference
+    }
+    $this->assertFalse(isset($content['baz']['#printed']), 'baz is not hidden in content after hide() via value');
+
+    // Now lets do the same with some TwigReference magic!
+
+    $content_wrapper = new TwigReference();
+    $content_wrapper->setReference($content);
+    $context['content'] = $content_wrapper;
+
+    // Twig converts {{ hide(content.baz) }} to the following code
+
+    // This will succeed, because getAttribute returns a value, but it is an object
+
+    if (isset($context["content"])) {
+      $_content_ = $context["content"];
+    }
+    else {
+      $_content_ = NULL;
+    }
+    TwigReferenceFunctions::hide($this->getAttribute($_content_, "baz"));
+
+    $this->assertTrue(isset($content['baz']['#printed']), 'baz is hidden in content after hide() via TwigReference object');
+
+    $type = TwigReferenceFunctions::gettype($this->getAttribute($_content_, "baz"));
+    $this->assertEqual($type, 'array', 'Type returned via TwigReferenceFunctions:: is an array.');
+
+    $type = gettype($this->getAttribute($_content_, "baz"));
+    $this->assertEqual($type, 'object', 'Type returned without TwigReferenceFunctions:: is an object.');
+  }
+
+  /**
+   *  Helper function to somehow simulate Twigs getAttribute function
+   */
+  public function getAttribute($array, $offset) {
+    if (isset($array[$offset])) {
+      return $array[$offset];
+    }
+
+    return NULL;
+  }
+}
diff --git a/core/modules/system/templates/datetime.twig b/core/modules/system/templates/datetime.twig
new file mode 100644
index 0000000..b6c6f21
--- /dev/null
+++ b/core/modules/system/templates/datetime.twig
@@ -0,0 +1,32 @@
+{#
+/**
+ * Returns HTML for a date / time.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - timestamp: (optional) A UNIX timestamp for the datetime attribute. If the
+ *     datetime cannot be represented as a UNIX timestamp, use a valid datetime
+ *     attribute value in $variables['attributes']['datetime'].
+ *   - text: (optional) The content to display within the <time> element. Set
+ *     'html' to TRUE if this value is already sanitized for output in HTML.
+ *     Defaults to a human-readable representation of the timestamp value or the
+ *     datetime attribute value using format_date().
+ *     When invoked as #theme or #theme_wrappers of a render element, the
+ *     rendered #children are autoamtically taken over as 'text', unless #text
+ *     is explicitly set.
+ *   - attributes: (optional) An associative array of HTML attributes to apply
+ *     to the <time> element. A datetime attribute in 'attributes' overrides the
+ *     'timestamp'. To create a valid datetime attribute value from a UNIX
+ *     timestamp, use format_date() with one of the predefined 'html_*' formats.
+ *   - html: (optional) Whether 'text' is HTML markup (TRUE) or plain-text
+ *     (FALSE). Defaults to FALSE. For example, to use a SPAN tag within the
+ *     TIME element, this must be set to TRUE, or the SPAN tag will be escaped.
+ *     It is the responsibility of the caller to properly sanitize the value
+ *     contained in 'text' (or within the SPAN tag in aforementioned example).
+ *
+ * @see template_preprocess_datetime()
+ * @see http://www.w3.org/TR/html5-author/the-time-element.html#attr-time-datetime
+ */
+#}
+{# @todo Revisit this once autoescape is enabled #}
+<time class="{{ attributes.class }}" {{ attributes }}>{{ html ? text : (text|escape) }}</time>
diff --git a/core/modules/system/tests/modules/theme_test/theme_test.template_test.tpl.php b/core/modules/system/tests/modules/theme_test/templates/theme_test.template_test.tpl.php
similarity index 100%
rename from core/modules/system/tests/modules/theme_test/theme_test.template_test.tpl.php
rename to core/modules/system/tests/modules/theme_test/templates/theme_test.template_test.tpl.php
diff --git a/core/modules/system/tests/modules/theme_test/theme_test.module b/core/modules/system/tests/modules/theme_test/theme_test.module
index a05bc46..f231b49 100644
--- a/core/modules/system/tests/modules/theme_test/theme_test.module
+++ b/core/modules/system/tests/modules/theme_test/theme_test.module
@@ -27,6 +27,7 @@ function theme_test_system_theme_info() {
   $themes['test_theme'] = drupal_get_path('module', 'system') . '/tests/themes/test_theme/test_theme.info';
   $themes['test_basetheme'] = drupal_get_path('module', 'system') . '/tests/themes/test_basetheme/test_basetheme.info';
   $themes['test_subtheme'] = drupal_get_path('module', 'system') . '/tests/themes/test_subtheme/test_subtheme.info';
+  $themes['test_theme_twig'] = drupal_get_path('module', 'system') . '/tests/themes/test_theme_twig/test_theme_twig.info';
   return $themes;
 }
 
diff --git a/core/modules/system/tests/themes/test_theme/node--1.tpl.php b/core/modules/system/tests/themes/test_theme/node--1.tpl.php
new file mode 100644
index 0000000..81974ce
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme/node--1.tpl.php
@@ -0,0 +1,4 @@
+<?php
+  // node--1.tpl.php - Dummy file for finding the template
+?>
+Node Content Dummy
diff --git a/core/modules/system/tests/themes/test_theme_twig/node--1.twig b/core/modules/system/tests/themes/test_theme_twig/node--1.twig
new file mode 100644
index 0000000..79148f1
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_twig/node--1.twig
@@ -0,0 +1,4 @@
+{#
+  // node--1.twig - Dummy file for finding the template
+#}
+Node Content Dummy
diff --git a/core/modules/system/tests/themes/test_theme_twig/template.php b/core/modules/system/tests/themes/test_theme_twig/template.php
new file mode 100644
index 0000000..a4abe2d
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_twig/template.php
@@ -0,0 +1,2 @@
+<?php
+
diff --git a/core/modules/system/tests/themes/test_theme_twig/test_theme_twig.info b/core/modules/system/tests/themes/test_theme_twig/test_theme_twig.info
new file mode 100644
index 0000000..5097adb
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_twig/test_theme_twig.info
@@ -0,0 +1,5 @@
+name = Test theme for Twig
+description = Theme for testing the theme system with twig engine
+engine = twig
+core = 8.x
+hidden = TRUE
diff --git a/core/modules/system/tests/themes/test_theme_twig/theme_test.template_test.twig b/core/modules/system/tests/themes/test_theme_twig/theme_test.template_test.twig
new file mode 100644
index 0000000..6cda319
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_twig/theme_test.template_test.twig
@@ -0,0 +1,2 @@
+{# Output for Theme API test #}
+Success: Template overridden.
diff --git a/core/themes/engines/twig/twig.engine b/core/themes/engines/twig/twig.engine
new file mode 100644
index 0000000..abc4407
--- /dev/null
+++ b/core/themes/engines/twig/twig.engine
@@ -0,0 +1,126 @@
+<?php
+
+/**
+ * @file
+ * Handles integration of Twig templates with the Drupal theme system.
+ */
+use Drupal\Core\Template\TwigReference;
+
+/**
+ * Implements hook_theme().
+ */
+function twig_theme($existing, $type, $theme, $path) {
+  return drupal_find_theme_templates($existing, '.twig', $path);
+}
+
+/**
+ * Implements hook_extension().
+ */
+function twig_extension() {
+  return '.twig';
+}
+
+/**
+ * Implements hook_init().
+ */
+function twig_init($template) {
+  $file = dirname($template->filename) . '/template.php';
+  if (file_exists($file)) {
+    include_once DRUPAL_ROOT . '/' . $file;
+  }
+}
+
+/**
+ * Render twig templates.
+ *
+ * This retrieves the Twig_Environment from the Drupal Injection container and
+ * renders the template.
+ *
+ * @param $template_file
+ *   The filename of the template to render.
+ * @param $variables
+ *   A keyed array of variables that will appear in the output.
+ *
+ * @return
+ *   The output generated by the template.
+ */
+function twig_render_template($template_file, $variables) {
+  $variables['_references']=array();
+  return drupal_container()->get('twig')->loadTemplate($template_file)->render($variables);
+}
+
+/**
+ * Wrapper around render() for twig printed output.
+ *
+ * If an object is passed that has no __toString method an exception is thrown;
+ * other objects are casted to string. However in the case that the object is an
+ * instance of a Twig_Markup object it is returned directly to support auto
+ * escaping.
+ *
+ * If an array is passed it is rendered via render() and scalar values are
+ * returned directly.
+ *
+ * @param mixed $arg
+ *   String, Object or Render Array
+ *
+ * @return
+ *   The rendered output or an Twig_Markup object.
+ *
+ * @see render
+ * @see TwigNodeVisitor
+ */
+function twig_render($arg) {
+  if ($arg instanceof TwigReference) {
+    $arg = &$arg->getReference();
+  }
+
+  // == is true also for empty arrays
+  if ($arg == null) {
+    return null;
+  }
+
+  // Keep Twig_Markup objects intact to prepare for later autoescaping support
+  if ($arg instanceOf Twig_Markup) {
+    return $arg;
+  }
+
+  if (is_scalar($arg)) {
+    return $arg;
+  }
+
+  if (is_object($arg)) {
+    if (method_exists($arg, '__toString')) {
+      return (string) $arg;
+    }
+    throw new Exception(t('Object of type "@class" cannot be printed.', array('@class' => get_class($arg))));
+  }
+
+  // This is a normal render array.
+  return render($arg);
+}
+
+/**
+ * Wrapper around hide() that does not return the content.
+ *
+ * @see hide
+ */
+function twig_hide($element) {
+  if ($element instanceof TwigReference) {
+    $element = &$element->getReference();
+    hide($element);
+  }
+  // @todo Add warning in else case
+}
+
+/**
+ * Wrapper around show() that does not return the content.
+ *
+ * @see show
+ */
+function twig_show($element) {
+  if ($element instanceof TwigReference) {
+    $element = &$element->getReference();
+    show($element);
+  }
+  // @todo Add warning in else case
+}
