fabpot/Twig — Issue #473: Consider Making Twig Even Smarter
Author: schmittjoh
Created: 2011-10-17 19:30:38+00:00
State: open

From my experience with working with Twig's internals, there is some potential for optimizations.

1. Some runtime checks could be shifted to compile-time.

- Most of the tests are implemented as functions, e.g.

```php
function twig_test_sameas($a, $b) {
return $a === $b;
}
```

- resolve templates at compile-time (or, is there a case where a template would become unavailable after compilation?)
- any feature detection could be shifted to compile-time, and appropriate functions could be inlined

2. Optimizations to generated code

- avoid redundant checks

```html+jinja
Hello {{ name|default("World") }}!
```

```php
// line 1
echo "Hello ";
if (isset($context["name"])) { $_name_ = $context["name"]; } else { $_name_ = null; }
echo twig_escape_filter($this->env, ((array_key_exists("name", $context)) ? (twig_default_filter($_name_, "World")) : ("World")), "html", null, true);
echo "!";

```

- avoid multiple assignment

```html+jinja
{% for i in 1..5 %}
{{- i -}}

{%- for j in range(i, i) -%}
{{ ", " ~ j }}
{%- endfor -%}

{%- if not loop.last %}, {% endif -%}
{% endfor %}
```

```php
// line 2
if (isset($context["i"])) { $_i_ = $context["i"]; } else { $_i_ = null; }
echo twig_escape_filter($this->env, $_i_, "html", null, true);
// line 4
if (isset($context["i"])) { $_i_ = $context["i"]; } else { $_i_ = null; }
$context['_parent'] = (array) $context;
$context['_seq'] = twig_ensure_traversable(range($_i_, $_i_));
```

Generally, many improvements could be made by using all information that is available at compile-time. This way we could avoid a lot of runtime checks. In particular, retaining information about assigned variables, and type information could lead to significant code improvements.

In the previous code snippet, we know for example that the range() function always returns an array, thus the twig_ensure_traversable check could be avoided. Similar heuristics could be applied in other situations.

Another example from the previous code, the variable i is set in the loop by Twig, but Twig still continues to check on each access whether it is set, and tries to assign null if not. These checks could be avoided completely.