Repository: PebbleTemplates/pebble
Pull request #239 (2016-11-14 09:16:01)

Replacing Guava cache with the one from Caffeine
I made the replacement of the cache, updated some dependencies' version and fixed the involved unit tests.

Instead of creating a cache with max size set to zero, I decided to set the cache to `null`. I believe it should be faster to not pass through the cache, since it would always creates a `CompletableFuture` to compute the value that we have to return.



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 769e8803..31284078 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,17 +1,3 @@
-## v3.0.0 (future)
-- Java 8
-- Macros have access to all variables within the template and are no longer restricted to a "local scope"
-- New signature for filters/functions/tests that accepts the PebbleTemplate, EvaluationContext, and line number
-- Converted EvaluationContext to an interface with limited access to the underlying implementation
-- A "null" used as a boolean expression now throws an error if strict variables is true, treated as "false" otherwise
-- Improved error reporting
-
-## v2.3.0 (future)
-- Upgrade SLF4J from 1.6.1 to 1.7.21
-- "raw" filter works for all variables, not just strings
-- Improved error reporting for binary operators
-- Added setting to disable the trimming of newlines after pebble tags
-
 ## v2.2.3 (2016-10-01)
 - Bug fix: Fix the use of the "set" tag within a for loop
 - Bug fix: Fix the concatenation of SafeString (ex. the output of two macros)
diff --git a/pom.xml b/pom.xml
index ff41aa8a..b9ca4773 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,242 +1,255 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
-	<parent>
-		<groupId>org.sonatype.oss</groupId>
-		<artifactId>oss-parent</artifactId>
-		<version>7</version>
-	</parent>
+    <parent>
+        <groupId>org.sonatype.oss</groupId>
+        <artifactId>oss-parent</artifactId>
+        <version>7</version>
+    </parent>
 
-	<modelVersion>4.0.0</modelVersion>
-	<groupId>com.mitchellbosecke</groupId>
-	<artifactId>pebble</artifactId>
-	<version>2.2.4-SNAPSHOT</version>
-	<packaging>jar</packaging>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.mitchellbosecke</groupId>
+    <artifactId>pebble</artifactId>
+    <version>2.2.4-SNAPSHOT</version>
+    <packaging>jar</packaging>
 
-	<name>Pebble</name>
-	<description>Templating engine for Java.</description>
-	<url>http://www.mitchellbosecke.com/pebble</url>
+    <name>Pebble</name>
+    <description>Templating engine for Java.</description>
+    <url>http://www.mitchellbosecke.com/pebble</url>
 
-	<properties>
-		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-	</properties>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
 
-	<licenses>
-		<license>
-			<name>BSD 3-Clause License</name>
-			<url>http://opensource.org/licenses/BSD-3-Clause</url>
-			<distribution>repo</distribution>
-		</license>
-	</licenses>
+    <licenses>
+        <license>
+            <name>BSD 3-Clause License</name>
+            <url>http://opensource.org/licenses/BSD-3-Clause</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
 
-	<developers>
-		<developer>
-			<name>Mitchell Bösecke</name>
-			<email>mitchellbosecke@gmail.com</email>
-		</developer>
-	</developers>
+    <developers>
+        <developer>
+            <name>Mitchell Bösecke</name>
+            <email>mitchellbosecke@gmail.com</email>
+        </developer>
+    </developers>
 
-	<build>
-		<plugins>
-			<plugin>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<version>2.3.2</version>
-				<configuration>
-					<source>1.7</source>
-					<target>1.7</target>
-				</configuration>
-			</plugin>
-			<plugin>
-				<artifactId>maven-assembly-plugin</artifactId>
-				<executions>
-					<execution>
-						<phase>package</phase>
-						<goals>
-							<goal>single</goal>
-						</goals>
-					</execution>
-				</executions>
-				<configuration>
-					<descriptorRefs>
-						<descriptorRef>jar-with-dependencies</descriptorRef>
-					</descriptorRefs>
-				</configuration>
-			</plugin>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-source-plugin</artifactId>
-				<version>2.2.1</version>
-				<executions>
-					<execution>
-						<id>attach-sources</id>
-						<goals>
-							<goal>jar</goal>
-						</goals>
-					</execution>
-				</executions>
-			</plugin>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-javadoc-plugin</artifactId>
-				<version>2.9.1</version>
-				<configuration>
-					<outputDirectory>${project.build.directory}/javadoc</outputDirectory>
-					<reportOutputDirectory>${project.reporting.outputDirectory}/javadoc</reportOutputDirectory>
-					<excludes>
-						<exclude>**/*.txt</exclude>
-					</excludes>
-					<header>
-			            <![CDATA[
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>2.3.2</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>2.2.1</version>
+                <executions>
+                    <execution>
+                        <id>attach-sources</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>2.9.1</version>
+                <configuration>
+                    <outputDirectory>${project.build.directory}/javadoc</outputDirectory>
+                    <reportOutputDirectory>${project.reporting.outputDirectory}/javadoc</reportOutputDirectory>
+                    <excludes>
+                        <exclude>**/*.txt</exclude>
+                    </excludes>
+                    <header>
+                        <![CDATA[
 			                <a href="http://www.mitchellbosecke.com/pebble" target="_blank">Home</a>
 			            ]]>
-					</header>
-				</configuration>
-				<executions>
-					<execution>
-						<id>attach-javadocs</id>
-						<goals>
-							<goal>jar</goal>
-						</goals>
-					</execution>
-					<execution>
-						<id>aggregate</id>
-						<goals>
-							<goal>aggregate</goal>
-						</goals>
-						<phase>site</phase>
-					</execution>
-				</executions>
-			</plugin>
-			<plugin>
-				<groupId>com.github.github</groupId>
-				<artifactId>site-maven-plugin</artifactId>
-				<version>0.12</version>
-				<configuration>
-					<!-- <dryRun>true</dryRun> -->
-					<path>${project.version}</path>
-					<message>Creating site for ${project.version}</message>
-					<!-- sets the ~/.m2/setting.xml profile -->
-					<server>github</server>
-					<outputDirectory>${project.build.directory}/site/javadoc</outputDirectory>
-					<repositoryName>pebble</repositoryName>
-					<repositoryOwner>mbosecke</repositoryOwner>
-				</configuration>
-				<executions>
-					<execution>
-						<goals>
-							<goal>site</goal>
-						</goals>
-						<phase>site</phase>
-					</execution>
-				</executions>
-			</plugin>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-release-plugin</artifactId>
-				<configuration>
-					<tagNameFormat>v@{project.version}</tagNameFormat>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
+                    </header>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>attach-javadocs</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>aggregate</id>
+                        <goals>
+                            <goal>aggregate</goal>
+                        </goals>
+                        <phase>site</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>com.github.github</groupId>
+                <artifactId>site-maven-plugin</artifactId>
+                <version>0.12</version>
+                <configuration>
+                    <!-- <dryRun>true</dryRun> -->
+                    <path>${project.version}</path>
+                    <message>Creating site for ${project.version}</message>
+                    <!-- sets the ~/.m2/setting.xml profile -->
+                    <server>github</server>
+                    <outputDirectory>${project.build.directory}/site/javadoc</outputDirectory>
+                    <repositoryName>pebble</repositoryName>
+                    <repositoryOwner>mbosecke</repositoryOwner>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>site</goal>
+                        </goals>
+                        <phase>site</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-release-plugin</artifactId>
+                <configuration>
+                    <tagNameFormat>v@{project.version}</tagNameFormat>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
-	<profiles>
-		<profile>
-			<id>release-sign-artifacts</id>
-			<activation>
-				<property>
-					<name>performRelease</name>
-					<value>true</value>
-				</property>
-			</activation>
-			<build>
-				<plugins>
-					<plugin>
-						<groupId>org.apache.maven.plugins</groupId>
-						<artifactId>maven-gpg-plugin</artifactId>
-						<version>1.4</version>
-						<executions>
-							<execution>
-								<id>sign-artifacts</id>
-								<phase>verify</phase>
-								<goals>
-									<goal>sign</goal>
-								</goals>
-							</execution>
-						</executions>
-					</plugin>
-				</plugins>
-			</build>
-		</profile>
-	</profiles>
+    <profiles>
+        <profile>
+            <id>release-sign-artifacts</id>
+            <activation>
+                <property>
+                    <name>performRelease</name>
+                    <value>true</value>
+                </property>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-gpg-plugin</artifactId>
+                        <version>1.4</version>
+                        <executions>
+                            <execution>
+                                <id>sign-artifacts</id>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>sign</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 
-	<dependencies>
-	
-		<!-- required dependencies -->
-		<dependency>
-			<groupId>com.google.guava</groupId>
-			<artifactId>guava</artifactId>
-			<version>16.0.1</version>
-		</dependency>
-		<dependency>
-			<groupId>com.coverity.security</groupId>
-			<artifactId>coverity-escapers</artifactId>
-			<version>1.1</version>
-		</dependency>
-		<dependency>
-			<groupId>org.slf4j</groupId>
-			<artifactId>slf4j-api</artifactId>
-			<version>1.7.21</version>
-			<scope>compile</scope>
-		</dependency>
-		
-		<!-- optional dependencies -->
-		<dependency>
+    <dependencies>
+
+        <!-- required dependencies -->
+        <dependency>
+            <groupId>com.github.ben-manes.caffeine</groupId>
+            <artifactId>caffeine</artifactId>
+            <version>2.3.5</version>
+        </dependency>
+        <dependency>
+            <groupId>com.coverity.security</groupId>
+            <artifactId>coverity-escapers</artifactId>
+            <version>1.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.21</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <!-- optional dependencies -->
+        <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>servlet-api</artifactId>
             <version>2.5</version>
             <scope>provided</scope>
             <optional>true</optional>
         </dependency>
-		
-		<!-- testing dependencies -->
-		<dependency>
-			<groupId>org.slf4j</groupId>
-			<artifactId>slf4j-log4j12</artifactId>
-			<version>1.6.1</version>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<groupId>log4j</groupId>
-			<artifactId>log4j</artifactId>
-			<version>1.2.15</version>
-			<scope>test</scope>
-			<exclusions>
-				<exclusion>
-					<groupId>com.sun.jdmk</groupId>
-					<artifactId>jmxtools</artifactId>
-				</exclusion>
-				<exclusion>
-					<groupId>com.sun.jmx</groupId>
-					<artifactId>jmxri</artifactId>
-				</exclusion>
-				<exclusion>
-					<groupId>javax.jms</groupId>
-					<artifactId>jms</artifactId>
-				</exclusion>
-			</exclusions>
-		</dependency>
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<version>4.11</version>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
 
-	<scm>
-		<connection>scm:git:git://github.com/mbosecke/pebble.git</connection>
-		<developerConnection>scm:git:git@github.com:mbosecke/pebble.git</developerConnection>
-		<url>http://github.com/mbosecke/pebble.git</url>
-		<tag>HEAD</tag>
-	</scm>
+        <!-- testing dependencies -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>1.7.21</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.17</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.sun.jdmk</groupId>
+                    <artifactId>jmxtools</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.sun.jmx</groupId>
+                    <artifactId>jmxri</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>javax.jms</groupId>
+                    <artifactId>jms</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>java-hamcrest</artifactId>
+            <version>2.0.0.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId> org.hamcrest</groupId>
+                    <artifactId>hamcrest-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+
+    <scm>
+        <connection>scm:git:git://github.com/mbosecke/pebble.git</connection>
+        <developerConnection>scm:git:git@github.com:mbosecke/pebble.git</developerConnection>
+        <url>http://github.com/mbosecke/pebble.git</url>
+        <tag>HEAD</tag>
+    </scm>
 </project>
diff --git a/src/main/java/com/mitchellbosecke/pebble/PebbleEngine.java b/src/main/java/com/mitchellbosecke/pebble/PebbleEngine.java
index 40eda2dd..0de521c9 100644
--- a/src/main/java/com/mitchellbosecke/pebble/PebbleEngine.java
+++ b/src/main/java/com/mitchellbosecke/pebble/PebbleEngine.java
@@ -8,11 +8,14 @@
  ******************************************************************************/
 package com.mitchellbosecke.pebble;
 
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
+
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
 import com.mitchellbosecke.pebble.cache.BaseTagCacheKey;
 import com.mitchellbosecke.pebble.error.LoaderException;
+import com.mitchellbosecke.pebble.error.ParserException;
 import com.mitchellbosecke.pebble.error.PebbleException;
+import com.mitchellbosecke.pebble.error.RuntimePebbleException;
 import com.mitchellbosecke.pebble.extension.Extension;
 import com.mitchellbosecke.pebble.extension.ExtensionRegistry;
 import com.mitchellbosecke.pebble.extension.NodeVisitorFactory;
@@ -38,10 +41,11 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Locale;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
+import java.util.concurrent.CompletionException;
 import java.util.concurrent.ExecutorService;
 
+import static java.util.Objects.isNull;
+
 /**
  * The main class used for compiling templates. The PebbleEngine is responsible
  * for delegating responsibility to the lexer, parser, compiler, and template
@@ -117,37 +121,28 @@ public class PebbleEngine {
         try {
             final Object cacheKey = this.loader.createCacheKey(templateName);
 
-            result = templateCache.get(cacheKey, new Callable<PebbleTemplate>() {
-
-                public PebbleTemplateImpl call() throws Exception {
-
-                    LexerImpl lexer = new LexerImpl(syntax, extensionRegistry.getUnaryOperators().values(),
-                            extensionRegistry.getBinaryOperators().values());
-                    Reader templateReader = self.retrieveReaderFromLoader(self.loader, cacheKey);
-                    TokenStream tokenStream = lexer.tokenize(templateReader, templateName);
-
-                    Parser parser = new ParserImpl(extensionRegistry.getUnaryOperators(),
-                            extensionRegistry.getBinaryOperators(), extensionRegistry.getTokenParsers());
-                    RootNode root = parser.parse(tokenStream);
-
-                    PebbleTemplateImpl instance = new PebbleTemplateImpl(self, root, templateName);
-
-                    for (NodeVisitorFactory visitorFactory : extensionRegistry.getNodeVisitors()) {
-                        visitorFactory.createVisitor(instance).visit(root);
+            if(isNull(templateCache)){
+                result = getPebbleTemplate(self, templateName, cacheKey);
+            }
+            else {
+                result = templateCache.get(cacheKey, k -> {
+                    try {
+                        return getPebbleTemplate(self, templateName, cacheKey);
+                    } catch (PebbleException e) {
+                        throw new RuntimePebbleException(e);
                     }
-
-                    return instance;
-                }
-            });
-        } catch (ExecutionException e) {
+                });
+            }
+        } catch (CompletionException e) {
             /*
-             * The execution exception is probably caused by a PebbleException
-             * being thrown in the above Callable. We will unravel it and throw
+             * The completion exception is probably caused by a PebbleException
+             * being thrown in the above function. We will unravel it and throw
              * the original PebbleException which is more helpful to the end
              * user.
              */
-            if (e.getCause() != null && e.getCause() instanceof PebbleException) {
-                throw (PebbleException) e.getCause();
+            if (e.getCause() != null && e.getCause() instanceof RuntimePebbleException) {
+                RuntimePebbleException runtimePebbleException = (RuntimePebbleException) e.getCause();
+                throw (PebbleException) runtimePebbleException.getCause();
             } else {
                 throw new PebbleException(e, String.format("An error occurred while compiling %s", templateName));
             }
@@ -156,6 +151,25 @@ public class PebbleEngine {
         return result;
     }
 
+    private PebbleTemplate getPebbleTemplate(final PebbleEngine self, final String templateName, final Object cacheKey) throws LoaderException, ParserException {
+        LexerImpl lexer = new LexerImpl(syntax, extensionRegistry.getUnaryOperators().values(),
+                extensionRegistry.getBinaryOperators().values());
+        Reader templateReader = self.retrieveReaderFromLoader(self.loader, cacheKey);
+        TokenStream tokenStream = lexer.tokenize(templateReader, templateName);
+
+        Parser parser = new ParserImpl(extensionRegistry.getUnaryOperators(),
+                extensionRegistry.getBinaryOperators(), extensionRegistry.getTokenParsers());
+        RootNode root = parser.parse(tokenStream);
+
+        PebbleTemplateImpl instance = new PebbleTemplateImpl(self, root, templateName);
+
+        for (NodeVisitorFactory visitorFactory : extensionRegistry.getNodeVisitors()) {
+            visitorFactory.createVisitor(instance).visit(root);
+        }
+
+        return instance;
+    }
+
     /**
      * This method calls the loader and fetches the reader. We use this method
      * to handle the generic cast.
@@ -254,12 +268,10 @@ public class PebbleEngine {
 
         private List<Extension> userProvidedExtensions = new ArrayList<>();
 
-        private Syntax syntax;
+        private Syntax syntax = new Syntax.Builder().build();
 
         private boolean strictVariables = false;
 
-        private boolean enableNewLineTrimming = true;
-
         private Locale defaultLocale;
 
         private ExecutorService executorService;
@@ -336,28 +348,6 @@ public class PebbleEngine {
             return this;
         }
 
-        /**
-         * Changes the <code>newLineTrimming</code> setting of the PebbleEngine.
-         * The default value of this setting is "true".
-         * <p>
-         *      By default, Pebble will trim a newline that immediately follows
-         *      a Pebble tag. For example, <code>{{key1}}\n{{key2}}</code> will
-         *      have the newline removed.
-         * </p>
-         * <p>
-         * If <code>newLineTrimming</code> is set to false, then the
-         * first newline following a Pebble tag won't be trimmed.  All newlines
-         * will be preserved
-         * </p>
-         *
-         * @param enableNewLineTrimming Whether or not the newline should be trimmed.
-         * @return This builder object
-         */
-        public Builder newLineTrimming(boolean enableNewLineTrimming) {
-            this.enableNewLineTrimming = enableNewLineTrimming;
-            return this;
-        }
-
         /**
          * Sets the Locale passed to all templates constructed by this PebbleEngine.
          * <p>
@@ -482,19 +472,15 @@ public class PebbleEngine {
             if (cacheActive) {
                 // default caches
                 if (templateCache == null) {
-                    templateCache = CacheBuilder.newBuilder().maximumSize(200).build();
+                    templateCache = Caffeine.newBuilder().maximumSize(200).build();
                 }
 
                 if (tagCache == null) {
-                    tagCache = CacheBuilder.newBuilder().maximumSize(200).build();
+                    tagCache = Caffeine.newBuilder().maximumSize(200).build();
                 }
             } else {
-                templateCache = CacheBuilder.newBuilder().maximumSize(0).build();
-                tagCache = CacheBuilder.newBuilder().maximumSize(0).build();
-            }
-
-            if(syntax == null) {
-                syntax = new Syntax.Builder().setEnableNewLineTrimming(enableNewLineTrimming).build();
+                templateCache = null;
+                tagCache = null;
             }
 
             return new PebbleEngine(loader, syntax, strictVariables, defaultLocale, tagCache, templateCache,
diff --git a/src/main/java/com/mitchellbosecke/pebble/error/RuntimePebbleException.java b/src/main/java/com/mitchellbosecke/pebble/error/RuntimePebbleException.java
new file mode 100644
index 00000000..3b85c0ec
--- /dev/null
+++ b/src/main/java/com/mitchellbosecke/pebble/error/RuntimePebbleException.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * This file is part of Pebble.
+ *
+ * Copyright (c) 2014 by Mitchell Bösecke
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ ******************************************************************************/
+package com.mitchellbosecke.pebble.error;
+
+public class RuntimePebbleException extends RuntimeException {
+
+    public RuntimePebbleException(PebbleException e){
+        super(e);
+    }
+
+}
diff --git a/src/main/java/com/mitchellbosecke/pebble/extension/core/CoreExtension.java b/src/main/java/com/mitchellbosecke/pebble/extension/core/CoreExtension.java
index d2f64c7b..553f3c82 100644
--- a/src/main/java/com/mitchellbosecke/pebble/extension/core/CoreExtension.java
+++ b/src/main/java/com/mitchellbosecke/pebble/extension/core/CoreExtension.java
@@ -43,7 +43,7 @@ public class CoreExtension extends AbstractExtension {
     @Override
     public List<UnaryOperator> getUnaryOperators() {
         ArrayList<UnaryOperator> operators = new ArrayList<>();
-        operators.add(new UnaryOperatorImpl("not", 500, UnaryNotExpression.class));
+        operators.add(new UnaryOperatorImpl("not", 5, UnaryNotExpression.class));
         operators.add(new UnaryOperatorImpl("+", 500, UnaryPlusExpression.class));
         operators.add(new UnaryOperatorImpl("-", 500, UnaryMinusExpression.class));
         return operators;
diff --git a/src/main/java/com/mitchellbosecke/pebble/lexer/Syntax.java b/src/main/java/com/mitchellbosecke/pebble/lexer/Syntax.java
index 27dd5b6f..04c0370e 100644
--- a/src/main/java/com/mitchellbosecke/pebble/lexer/Syntax.java
+++ b/src/main/java/com/mitchellbosecke/pebble/lexer/Syntax.java
@@ -51,7 +51,7 @@ public final class Syntax {
 
     public Syntax(final String delimiterCommentOpen, final String delimiterCommentClose,
             final String delimiterExecuteOpen, final String delimiterExecuteClose, final String delimiterPrintOpen,
-            final String delimiterPrintClose, final String whitespaceTrim, final boolean enableNewLineTrimming) {
+            final String delimiterPrintClose, final String whitespaceTrim) {
         this.delimiterCommentClose = delimiterCommentClose;
         this.delimiterCommentOpen = delimiterCommentOpen;
         this.delimiterExecuteOpen = delimiterExecuteOpen;
@@ -59,17 +59,13 @@ public final class Syntax {
         this.delimiterPrintOpen = delimiterPrintOpen;
         this.delimiterPrintClose = delimiterPrintClose;
         this.whitespaceTrim = whitespaceTrim;
-        
-        // Do we trim the newline following a tag?
-        String newlineRegexSuffix = enableNewLineTrimming ? POSSIBLE_NEW_LINE : "";
 
         // regexes used to find the individual delimiters
         this.regexPrintClose = Pattern.compile("^\\s*" + Pattern.quote(whitespaceTrim) + "?"
-                + Pattern.quote(delimiterPrintClose) + newlineRegexSuffix);
-        
+                + Pattern.quote(delimiterPrintClose) + POSSIBLE_NEW_LINE);
         this.regexExecuteClose = Pattern.compile("^\\s*" + Pattern.quote(whitespaceTrim) + "?"
-                + Pattern.quote(delimiterExecuteClose) + newlineRegexSuffix);
-        this.regexCommentClose = Pattern.compile(Pattern.quote(delimiterCommentClose) + newlineRegexSuffix);
+                + Pattern.quote(delimiterExecuteClose) + POSSIBLE_NEW_LINE);
+        this.regexCommentClose = Pattern.compile(Pattern.quote(delimiterCommentClose) + POSSIBLE_NEW_LINE);
 
         // combination regex used to find the next START delimiter of any kind
         this.regexStartDelimiters = Pattern.compile(Pattern.quote(delimiterPrintOpen) + "|"
@@ -77,10 +73,10 @@ public final class Syntax {
 
         // regex to find the verbatim tag
         this.regexVerbatimStart = Pattern.compile("^\\s*verbatim\\s*(" + Pattern.quote(whitespaceTrim) + ")?"
-                + Pattern.quote(delimiterExecuteClose) + newlineRegexSuffix);
+                + Pattern.quote(delimiterExecuteClose) + POSSIBLE_NEW_LINE);
         this.regexVerbatimEnd = Pattern.compile(Pattern.quote(delimiterExecuteOpen) + "("
                 + Pattern.quote(whitespaceTrim) + ")?" + "\\s*endverbatim\\s*(" + Pattern.quote(whitespaceTrim) + ")?"
-                + Pattern.quote(delimiterExecuteClose) + newlineRegexSuffix);
+                + Pattern.quote(delimiterExecuteClose) + POSSIBLE_NEW_LINE);
 
         // regex for the whitespace trim character
         this.regexLeadingWhitespaceTrim = Pattern.compile(Pattern.quote(whitespaceTrim) + "\\s+");
@@ -186,8 +182,6 @@ public final class Syntax {
         private String delimiterPrintClose = "}}";
 
         private String whitespaceTrim = "-";
-        
-        private boolean enableNewLineTrimming = true;
 
         /**
          * @return the commentOpenDelimiter
@@ -286,19 +280,10 @@ public final class Syntax {
         public void setWhitespaceTrim(String whitespaceTrim) {
             this.whitespaceTrim = whitespaceTrim;
         }
-        
-        public boolean isEnableNewLineTrimming() {
-            return enableNewLineTrimming;
-        }
-        
-        public Builder setEnableNewLineTrimming(boolean enableNewLineTrimming) {
-            this.enableNewLineTrimming = enableNewLineTrimming;
-            return this;
-        }
 
         public Syntax build() {
             return new Syntax(delimiterCommentOpen, delimiterCommentClose, delimiterExecuteOpen, delimiterExecuteClose,
-                    delimiterPrintOpen, delimiterPrintClose, whitespaceTrim, enableNewLineTrimming);
+                    delimiterPrintOpen, delimiterPrintClose, whitespaceTrim);
         }
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/AbstractRenderableNode.java b/src/main/java/com/mitchellbosecke/pebble/node/AbstractRenderableNode.java
index eebc1821..1a2a907e 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/AbstractRenderableNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/AbstractRenderableNode.java
@@ -13,7 +13,7 @@ import java.io.Writer;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public abstract class AbstractRenderableNode implements RenderableNode {
@@ -21,7 +21,7 @@ public abstract class AbstractRenderableNode implements RenderableNode {
     private int lineNumber;
 
     @Override
-    public abstract void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context)
+    public abstract void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context)
             throws PebbleException, IOException;
 
     @Override
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/ArgumentsNode.java b/src/main/java/com/mitchellbosecke/pebble/node/ArgumentsNode.java
index dce79424..91805170 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/ArgumentsNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/ArgumentsNode.java
@@ -11,7 +11,7 @@ package com.mitchellbosecke.pebble.node;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NamedArguments;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 import java.util.HashMap;
@@ -60,7 +60,7 @@ public class ArgumentsNode implements Node {
      * @throws PebbleException
      *             Thrown if an expected name argument does not exist
      */
-    public Map<String, Object> getArgumentMap(PebbleTemplateImpl self, EvaluationContextImpl context,
+    public Map<String, Object> getArgumentMap(PebbleTemplateImpl self, EvaluationContext context,
             NamedArguments invocableWithNamedArguments) throws PebbleException {
         Map<String, Object> result = new HashMap<>();
         List<String> argumentNames = invocableWithNamedArguments.getArgumentNames();
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/AutoEscapeNode.java b/src/main/java/com/mitchellbosecke/pebble/node/AutoEscapeNode.java
index c7de5891..171cf2c4 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/AutoEscapeNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/AutoEscapeNode.java
@@ -13,7 +13,7 @@ import java.io.Writer;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class AutoEscapeNode extends AbstractRenderableNode {
@@ -32,7 +32,7 @@ public class AutoEscapeNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws PebbleException,
+    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws PebbleException,
             IOException {
         body.render(self, writer, context);
     }
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/BlockNode.java b/src/main/java/com/mitchellbosecke/pebble/node/BlockNode.java
index b10b01e2..b3c08e5f 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/BlockNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/BlockNode.java
@@ -14,7 +14,7 @@ import java.io.Writer;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.template.Block;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class BlockNode extends AbstractRenderableNode {
@@ -34,7 +34,7 @@ public class BlockNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(final PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws PebbleException,
+    public void render(final PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws PebbleException,
             IOException {
         self.block(writer, context, name, false);
     }
@@ -53,7 +53,7 @@ public class BlockNode extends AbstractRenderableNode {
             }
 
             @Override
-            public void evaluate(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context)
+            public void evaluate(PebbleTemplateImpl self, Writer writer, EvaluationContext context)
                     throws PebbleException, IOException {
                 body.render(self, writer, context);
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/BodyNode.java b/src/main/java/com/mitchellbosecke/pebble/node/BodyNode.java
index 9e6028cd..f9dadc92 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/BodyNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/BodyNode.java
@@ -10,7 +10,7 @@ package com.mitchellbosecke.pebble.node;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 import java.io.IOException;
@@ -35,7 +35,7 @@ public class BodyNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context)
+    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context)
             throws PebbleException, IOException {
         for (RenderableNode child : children) {
             if (onlyRenderInheritanceSafeNodes && context.getHierarchy().getParent() != null) {
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/CacheNode.java b/src/main/java/com/mitchellbosecke/pebble/node/CacheNode.java
index be05e1ba..ecd26ac6 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/CacheNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/CacheNode.java
@@ -8,11 +8,13 @@
  ******************************************************************************/
 package com.mitchellbosecke.pebble.node;
 
+import com.github.benmanes.caffeine.cache.Cache;
 import com.mitchellbosecke.pebble.cache.BaseTagCacheKey;
 import com.mitchellbosecke.pebble.error.PebbleException;
+import com.mitchellbosecke.pebble.error.RuntimePebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.expression.Expression;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.tokenParser.CacheTokenParser;
 
@@ -20,8 +22,10 @@ import java.io.IOException;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.util.Locale;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
+import java.util.Objects;
+import java.util.concurrent.CompletionException;
+
+import static java.util.Objects.isNull;
 
 /**
  * Node for the cache tag
@@ -120,23 +124,37 @@ public class CacheNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(final PebbleTemplateImpl self, Writer writer, final EvaluationContextImpl context)
+    public void render(final PebbleTemplateImpl self, Writer writer, final EvaluationContext context)
             throws PebbleException, IOException {
         try {
-            CacheKey key = new CacheKey((String) this.name.evaluate(self, context), context.getLocale());
-            String body = (String) context.getTagCache().get(key, new Callable<Object>() {
-
-                @Override
-                public String call() throws Exception {
-                    StringWriter tempWriter = new StringWriter();
-                    CacheNode.this.body.render(self, tempWriter, context);
-
-                    return tempWriter.toString();
-                }
-            });
+            final String body;
+            Cache tagCache = context.getTagCache();
+            if(isNull(tagCache)){ //No cache
+                body = render(self, context);
+            }
+            else {
+                CacheKey key = new CacheKey((String) this.name.evaluate(self, context), context.getLocale());
+                body = (String) context.getTagCache().get(key, k -> {
+                    try {
+                        return render(self, context);
+                    } catch (PebbleException e) {
+                        throw new RuntimePebbleException(e);
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+            }
             writer.write(body);
-        } catch (ExecutionException e) {
+        } catch (CompletionException e) {
             throw new PebbleException(e, "Could not render cache block [" + this.name + "]");
         }
     }
+
+    private String render(final PebbleTemplateImpl self, final EvaluationContext context) throws PebbleException, IOException {
+        StringWriter tempWriter = new StringWriter();
+        CacheNode.this.body.render(self, tempWriter, context);
+
+        return tempWriter.toString();
+    }
+
 }
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/ExtendsNode.java b/src/main/java/com/mitchellbosecke/pebble/node/ExtendsNode.java
index fa56b6e2..b2ce1a89 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/ExtendsNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/ExtendsNode.java
@@ -14,7 +14,7 @@ import java.io.Writer;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.expression.Expression;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class ExtendsNode extends AbstractRenderableNode {
@@ -27,7 +27,7 @@ public class ExtendsNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(final PebbleTemplateImpl self, Writer writer, final EvaluationContextImpl context)
+    public void render(final PebbleTemplateImpl self, Writer writer, final EvaluationContext context)
             throws IOException, PebbleException {
         self.setParent(context, (String) parentExpression.evaluate(self, context));
     }
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/FlushNode.java b/src/main/java/com/mitchellbosecke/pebble/node/FlushNode.java
index 8daa468d..a03f5ede 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/FlushNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/FlushNode.java
@@ -12,7 +12,7 @@ import java.io.IOException;
 import java.io.Writer;
 
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class FlushNode extends AbstractRenderableNode {
@@ -22,7 +22,7 @@ public class FlushNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws IOException {
+    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws IOException {
         writer.flush();
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/ForNode.java b/src/main/java/com/mitchellbosecke/pebble/node/ForNode.java
index d0c10e6a..f1a6459b 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/ForNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/ForNode.java
@@ -11,7 +11,7 @@ package com.mitchellbosecke.pebble.node;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.expression.Expression;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.template.ScopeChain;
 
@@ -45,7 +45,7 @@ public class ForNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context)
+    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context)
             throws PebbleException, IOException {
         Object iterableEvaluation = iterableExpression.evaluate(self, context);
         Iterable<?> iterable = null;
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/FunctionOrMacroNameNode.java b/src/main/java/com/mitchellbosecke/pebble/node/FunctionOrMacroNameNode.java
index 958c5645..ebb20b1d 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/FunctionOrMacroNameNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/FunctionOrMacroNameNode.java
@@ -11,7 +11,7 @@ package com.mitchellbosecke.pebble.node;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.expression.Expression;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class FunctionOrMacroNameNode implements Expression<String> {
@@ -26,7 +26,7 @@ public class FunctionOrMacroNameNode implements Expression<String> {
     }
 
     @Override
-    public String evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public String evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         throw new UnsupportedOperationException();
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/IfNode.java b/src/main/java/com/mitchellbosecke/pebble/node/IfNode.java
index fa436a98..32017344 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/IfNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/IfNode.java
@@ -11,7 +11,7 @@ package com.mitchellbosecke.pebble.node;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.expression.Expression;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.Pair;
 
@@ -36,7 +36,7 @@ public class IfNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws PebbleException,
+    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws PebbleException,
             IOException {
 
         boolean satisfied = false;
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/ImportNode.java b/src/main/java/com/mitchellbosecke/pebble/node/ImportNode.java
index f03a3ba5..1480f5bd 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/ImportNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/ImportNode.java
@@ -13,7 +13,7 @@ import java.io.Writer;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.expression.Expression;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class ImportNode extends AbstractRenderableNode {
@@ -26,7 +26,7 @@ public class ImportNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws PebbleException {
+    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws PebbleException {
         self.importTemplate(context, (String) importExpression.evaluate(self, context));
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/IncludeNode.java b/src/main/java/com/mitchellbosecke/pebble/node/IncludeNode.java
index 6ad2d4cb..ef7a0ffb 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/IncludeNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/IncludeNode.java
@@ -17,7 +17,7 @@ import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.expression.Expression;
 import com.mitchellbosecke.pebble.node.expression.MapExpression;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class IncludeNode extends AbstractRenderableNode {
@@ -33,7 +33,7 @@ public class IncludeNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws PebbleException,
+    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws PebbleException,
             IOException {
         String templateName = (String) includeExpression.evaluate(self, context);
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/MacroNode.java b/src/main/java/com/mitchellbosecke/pebble/node/MacroNode.java
index cbc24657..b5679d3a 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/MacroNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/MacroNode.java
@@ -11,7 +11,10 @@ package com.mitchellbosecke.pebble.node;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.expression.Expression;
-import com.mitchellbosecke.pebble.template.*;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
+import com.mitchellbosecke.pebble.template.Macro;
+import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
+import com.mitchellbosecke.pebble.template.ScopeChain;
 
 import java.io.IOException;
 import java.io.StringWriter;
@@ -35,7 +38,7 @@ public class MacroNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws PebbleException,
+    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws PebbleException,
             IOException {
         // do nothing
     }
@@ -63,13 +66,13 @@ public class MacroNode extends AbstractRenderableNode {
             }
 
             @Override
-            public String call(PebbleTemplateImpl self, EvaluationContextImpl context, Map<String, Object> macroArgs)
+            public String call(PebbleTemplateImpl self, EvaluationContext context, Map<String, Object> macroArgs)
                     throws PebbleException {
                 Writer writer = new StringWriter();
                 ScopeChain scopeChain = context.getScopeChain();
 
                 // scope for default arguments
-                scopeChain.pushScope();
+                scopeChain.pushLocalScope();
                 for (NamedArgumentNode arg : getArgs().getNamedArgs()) {
                     Expression<?> valueExpression = arg.getValueExpression();
                     if (valueExpression == null) {
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/ParallelNode.java b/src/main/java/com/mitchellbosecke/pebble/node/ParallelNode.java
index 39379fcf..4122a13a 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/ParallelNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/ParallelNode.java
@@ -10,7 +10,7 @@ package com.mitchellbosecke.pebble.node;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.FutureWriter;
 import org.slf4j.Logger;
@@ -43,7 +43,7 @@ public class ParallelNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(final PebbleTemplateImpl self, Writer writer, final EvaluationContextImpl context)
+    public void render(final PebbleTemplateImpl self, Writer writer, final EvaluationContext context)
             throws IOException, PebbleException {
 
         ExecutorService es = context.getExecutorService();
@@ -66,7 +66,7 @@ public class ParallelNode extends AbstractRenderableNode {
             
         } else {
 
-            final EvaluationContextImpl contextCopy = context.threadSafeCopy(self);
+            final EvaluationContext contextCopy = context.threadSafeCopy(self);
 
             final StringWriter newStringWriter = new StringWriter();
             final Writer newFutureWriter = new FutureWriter(newStringWriter);
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/PrintNode.java b/src/main/java/com/mitchellbosecke/pebble/node/PrintNode.java
index 689b1a34..7b6444eb 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/PrintNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/PrintNode.java
@@ -11,7 +11,7 @@ package com.mitchellbosecke.pebble.node;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.expression.Expression;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.StringUtils;
 
@@ -28,7 +28,7 @@ public class PrintNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws IOException,
+    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws IOException,
             PebbleException {
         Object var = expression.evaluate(self, context);
         if (var != null) {
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/RenderableNode.java b/src/main/java/com/mitchellbosecke/pebble/node/RenderableNode.java
index eeb2e4b1..66f91c84 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/RenderableNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/RenderableNode.java
@@ -12,11 +12,11 @@ import java.io.IOException;
 import java.io.Writer;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public interface RenderableNode extends Node {
 
-    void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws PebbleException,
+    void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws PebbleException,
             IOException;
 }
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/RootNode.java b/src/main/java/com/mitchellbosecke/pebble/node/RootNode.java
index 564be505..8694be0b 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/RootNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/RootNode.java
@@ -13,7 +13,7 @@ import java.io.Writer;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class RootNode extends AbstractRenderableNode {
@@ -26,7 +26,7 @@ public class RootNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws PebbleException,
+    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws PebbleException,
             IOException {
         body.setOnlyRenderInheritanceSafeNodes(true);
         body.render(self, writer, context);
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/SetNode.java b/src/main/java/com/mitchellbosecke/pebble/node/SetNode.java
index 7b403cca..22ab351c 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/SetNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/SetNode.java
@@ -11,7 +11,7 @@ package com.mitchellbosecke.pebble.node;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.expression.Expression;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 import java.io.Writer;
@@ -29,7 +29,7 @@ public class SetNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws PebbleException {
+    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws PebbleException {
         context.getScopeChain().set(name, value.evaluate(self, context));
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/TextNode.java b/src/main/java/com/mitchellbosecke/pebble/node/TextNode.java
index 9c33dd9b..2e1fa531 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/TextNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/TextNode.java
@@ -12,7 +12,7 @@ import java.io.IOException;
 import java.io.Writer;
 
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 /**
@@ -38,7 +38,7 @@ public class TextNode extends AbstractRenderableNode {
     }
 
     @Override
-    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws IOException {
+    public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws IOException {
         writer.write(data);
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/AddExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/AddExpression.java
index 25b94520..a48daf67 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/AddExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/AddExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class AddExpression extends BinaryExpression<Object> {
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
 
         try{
             return OperatorUtils.add(getLeftExpression().evaluate(self, context),
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/AndExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/AndExpression.java
index fb77ac06..150d086a 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/AndExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/AndExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class AndExpression extends BinaryExpression<Boolean> {
 
     @SuppressWarnings("unchecked")
     @Override
-    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         Boolean left = ((Expression<Boolean>) getLeftExpression()).evaluate(self, context);
         Boolean right = ((Expression<Boolean>) getRightExpression()).evaluate(self, context);
         if(context.isStrictVariables()){
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/ArrayExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/ArrayExpression.java
index be575505..32349bd0 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/ArrayExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/ArrayExpression.java
@@ -14,7 +14,7 @@ import java.util.List;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class ArrayExpression implements Expression<List<?>> {
@@ -42,7 +42,7 @@ public class ArrayExpression implements Expression<List<?>> {
     }
 
     @Override
-    public List<?> evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public List<?> evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         List<Object> returnValues = new ArrayList<>(values.size());
         for (int i = 0; i < values.size(); i++) {
             Expression<?> expr = values.get(i);
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/BlockFunctionExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/BlockFunctionExpression.java
index 00559dd9..836aa91e 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/BlockFunctionExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/BlockFunctionExpression.java
@@ -15,7 +15,7 @@ import java.io.Writer;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.ArgumentsNode;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class BlockFunctionExpression implements Expression<String> {
@@ -30,7 +30,7 @@ public class BlockFunctionExpression implements Expression<String> {
     }
 
     @Override
-    public String evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public String evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         Writer writer = new StringWriter();
         String blockName = (String) blockNameExpression.evaluate(self, context);
         try {
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/ConcatenateExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/ConcatenateExpression.java
index 929fd3fc..8e62e576 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/ConcatenateExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/ConcatenateExpression.java
@@ -1,7 +1,7 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 /**
@@ -13,7 +13,7 @@ import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 public class ConcatenateExpression extends BinaryExpression<Object> {
 
     @Override
-    public String evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public String evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
 
         Object left = getLeftExpression().evaluate(self, context);
         Object right = getRightExpression().evaluate(self, context);
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/ContainsExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/ContainsExpression.java
index ca221a47..4f86c0c7 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/ContainsExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/ContainsExpression.java
@@ -12,14 +12,14 @@ import java.util.Collection;
 import java.util.Map;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class ContainsExpression extends BinaryExpression<Boolean> {
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
     @Override
-    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         Object leftValue = getLeftExpression().evaluate(self, context);
 
         if (leftValue == null) {
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/ContextVariableExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/ContextVariableExpression.java
index 6eed0603..b245e62a 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/ContextVariableExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/ContextVariableExpression.java
@@ -11,7 +11,7 @@ package com.mitchellbosecke.pebble.node.expression;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.error.RootAttributeNotFoundException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.template.ScopeChain;
 
@@ -36,7 +36,7 @@ public class ContextVariableExpression implements Expression<Object> {
     }
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         ScopeChain scopeChain = context.getScopeChain();
         Object result = scopeChain.get(name);
         if (result == null && context.isStrictVariables() && !scopeChain.containsKey(name)) {
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/DivideExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/DivideExpression.java
index e4b5eeb5..6ea1ec3b 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/DivideExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/DivideExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class DivideExpression extends BinaryExpression<Object> {
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         try {
             return OperatorUtils.divide(getLeftExpression().evaluate(self, context),
                     getRightExpression().evaluate(self, context));
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/EqualsExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/EqualsExpression.java
index fdc41ba0..3e421bff 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/EqualsExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/EqualsExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class EqualsExpression extends BinaryExpression<Boolean> {
 
     @Override
-    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
 
         try{
             return OperatorUtils.equals(getLeftExpression().evaluate(self, context),
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/Expression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/Expression.java
index 41ecaae0..0a6b6687 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/Expression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/Expression.java
@@ -10,12 +10,12 @@ package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.node.Node;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public interface Expression<T> extends Node {
 
-    T evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException;
+    T evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException;
 
     /**
      * Returns the line number on which the expression is defined on.
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/FilterExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/FilterExpression.java
index 852fc3ca..9912894f 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/FilterExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/FilterExpression.java
@@ -15,7 +15,7 @@ import com.mitchellbosecke.pebble.extension.core.DefaultFilter;
 import com.mitchellbosecke.pebble.extension.escaper.EscapeFilter;
 import com.mitchellbosecke.pebble.extension.escaper.SafeString;
 import com.mitchellbosecke.pebble.node.ArgumentsNode;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 import java.util.Map;
@@ -33,7 +33,7 @@ public class FilterExpression extends BinaryExpression<Object> {
     }
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
 
         FilterInvocationExpression filterInvocation = (FilterInvocationExpression) getRightExpression();
         ArgumentsNode args = filterInvocation.getArgs();
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/FilterInvocationExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/FilterInvocationExpression.java
index 89b0f2a8..ec03fb67 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/FilterInvocationExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/FilterInvocationExpression.java
@@ -11,7 +11,7 @@ package com.mitchellbosecke.pebble.node.expression;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.ArgumentsNode;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 /**
@@ -35,7 +35,7 @@ public class FilterInvocationExpression implements Expression<Object> {
     }
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         // see FilterExpression.java
         throw new UnsupportedOperationException();
     }
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/FunctionOrMacroInvocationExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/FunctionOrMacroInvocationExpression.java
index 5f201f72..aa007d4c 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/FunctionOrMacroInvocationExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/FunctionOrMacroInvocationExpression.java
@@ -12,7 +12,7 @@ import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.Function;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.ArgumentsNode;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 import java.util.ArrayList;
@@ -35,7 +35,7 @@ public class FunctionOrMacroInvocationExpression implements Expression<Object> {
     }
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         Function function = context.getExtensionRegistry().getFunction(functionName);
         if (function != null) {
             return applyFunction(self, context, function, args);
@@ -43,7 +43,7 @@ public class FunctionOrMacroInvocationExpression implements Expression<Object> {
         return self.macro(context, functionName, args, false);
     }
 
-    private Object applyFunction(PebbleTemplateImpl self, EvaluationContextImpl context, Function function,
+    private Object applyFunction(PebbleTemplateImpl self, EvaluationContext context, Function function,
                                  ArgumentsNode args) throws PebbleException {
         List<Object> arguments = new ArrayList<>();
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/GetAttributeExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/GetAttributeExpression.java
index aacd8084..cb8c9425 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/GetAttributeExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/GetAttributeExpression.java
@@ -20,7 +20,7 @@ import com.mitchellbosecke.pebble.error.RootAttributeNotFoundException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.ArgumentsNode;
 import com.mitchellbosecke.pebble.node.PositionalArgumentNode;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 import java.lang.reflect.*;
@@ -74,7 +74,7 @@ public class GetAttributeExpression implements Expression<Object> {
     }
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         Object object = node.evaluate(self, context);
         Object attributeNameValue = attributeNameExpression.evaluate(self, context);
         String attributeName = String.valueOf(attributeNameValue);
@@ -225,7 +225,7 @@ public class GetAttributeExpression implements Expression<Object> {
      * @return
      * @throws PebbleException
      */
-    private Object[] getArgumentValues(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    private Object[] getArgumentValues(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
 
         Object[] argumentValues;
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/GreaterThanEqualsExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/GreaterThanEqualsExpression.java
index 8e09ebb3..51cc0f20 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/GreaterThanEqualsExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/GreaterThanEqualsExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class GreaterThanEqualsExpression extends BinaryExpression<Boolean> {
 
     @Override
-    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
 
         try {
             return OperatorUtils.gte(getLeftExpression().evaluate(self, context),
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/GreaterThanExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/GreaterThanExpression.java
index a4279379..b1f9044f 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/GreaterThanExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/GreaterThanExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class GreaterThanExpression extends BinaryExpression<Boolean> {
 
     @Override
-    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         try {
             return OperatorUtils.gt(getLeftExpression().evaluate(self, context),
                     getRightExpression().evaluate(self, context));
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/LessThanEqualsExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/LessThanEqualsExpression.java
index a8e0feee..6741580e 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/LessThanEqualsExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/LessThanEqualsExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class LessThanEqualsExpression extends BinaryExpression<Boolean> {
 
     @Override
-    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         try{
             return OperatorUtils.lte(getLeftExpression().evaluate(self, context),
                     getRightExpression().evaluate(self, context));
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/LessThanExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/LessThanExpression.java
index 11231541..746526e7 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/LessThanExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/LessThanExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class LessThanExpression extends BinaryExpression<Boolean> {
 
     @Override
-    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         try {
             return OperatorUtils.lt(getLeftExpression().evaluate(self, context),
                     getRightExpression().evaluate(self, context));
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralBooleanExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralBooleanExpression.java
index 4820efaf..d1a4e74e 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralBooleanExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralBooleanExpression.java
@@ -10,7 +10,7 @@ package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class LiteralBooleanExpression implements Expression<Boolean> {
@@ -30,7 +30,7 @@ public class LiteralBooleanExpression implements Expression<Boolean> {
     }
 
     @Override
-    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         return value;
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralDoubleExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralDoubleExpression.java
index 2f44a2c9..50e98a69 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralDoubleExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralDoubleExpression.java
@@ -10,7 +10,7 @@ package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class LiteralDoubleExpression implements Expression<Double> {
@@ -30,7 +30,7 @@ public class LiteralDoubleExpression implements Expression<Double> {
     }
 
     @Override
-    public Double evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Double evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         return value;
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralLongExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralLongExpression.java
index b57f4f7b..fef4aa53 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralLongExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralLongExpression.java
@@ -10,7 +10,7 @@ package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class LiteralLongExpression implements Expression<Long> {
@@ -29,7 +29,7 @@ public class LiteralLongExpression implements Expression<Long> {
     }
 
     @Override
-    public Long evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Long evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         return value;
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralNullExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralNullExpression.java
index 16be4ce2..0fe46c37 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralNullExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralNullExpression.java
@@ -10,7 +10,7 @@ package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class LiteralNullExpression implements Expression<Object> {
@@ -27,7 +27,7 @@ public class LiteralNullExpression implements Expression<Object> {
     }
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         return null;
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralStringExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralStringExpression.java
index 49b6a41b..de721005 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralStringExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralStringExpression.java
@@ -10,7 +10,7 @@ package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class LiteralStringExpression implements Expression<String> {
@@ -30,7 +30,7 @@ public class LiteralStringExpression implements Expression<String> {
     }
 
     @Override
-    public String evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public String evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         return value;
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/MapExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/MapExpression.java
index 7e27524f..522b7792 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/MapExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/MapExpression.java
@@ -15,7 +15,7 @@ import java.util.Map.Entry;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class MapExpression implements Expression<Map<?, ?>> {
@@ -44,7 +44,7 @@ public class MapExpression implements Expression<Map<?, ?>> {
     }
 
     @Override
-    public Map<?, ?> evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Map<?, ?> evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         Map<Object, Object> returnEntries = new HashMap<>(Long.valueOf(Math.round(Math.ceil(entries.size() / 0.75)))
                 .intValue());
         for (Entry<Expression<?>, Expression<?>> entry : entries.entrySet()) {
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/ModulusExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/ModulusExpression.java
index 823cf54b..04b74c9b 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/ModulusExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/ModulusExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class ModulusExpression extends BinaryExpression<Object> {
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         try {
             return OperatorUtils.mod(getLeftExpression().evaluate(self, context),
                     getRightExpression().evaluate(self, context));
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/MultiplyExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/MultiplyExpression.java
index d7669378..0bd69dfb 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/MultiplyExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/MultiplyExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class MultiplyExpression extends BinaryExpression<Object> {
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         try {
             return OperatorUtils.multiply(getLeftExpression().evaluate(self, context),
                     getRightExpression().evaluate(self, context));
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/NotEqualsExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/NotEqualsExpression.java
index 5c7b661b..37d4f904 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/NotEqualsExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/NotEqualsExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class NotEqualsExpression extends BinaryExpression<Boolean> {
 
     @Override
-    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         try{
             return !OperatorUtils
                     .equals(getLeftExpression().evaluate(self, context), getRightExpression().evaluate(self, context));
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/OrExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/OrExpression.java
index d041f85b..f5e60d4f 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/OrExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/OrExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class OrExpression extends BinaryExpression<Boolean> {
 
     @SuppressWarnings("unchecked")
     @Override
-    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         Boolean left = ((Expression<Boolean>) getLeftExpression()).evaluate(self, context);
         Boolean right = ((Expression<Boolean>) getRightExpression()).evaluate(self, context);
         if(context.isStrictVariables()){
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/ParentFunctionExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/ParentFunctionExpression.java
index a18f7897..c499c2a4 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/ParentFunctionExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/ParentFunctionExpression.java
@@ -10,7 +10,7 @@ package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.Hierarchy;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
@@ -30,7 +30,7 @@ public class ParentFunctionExpression implements Expression<String> {
     }
 
     @Override
-    public String evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public String evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         Writer writer = new StringWriter();
         try {
             Hierarchy hierarchy = context.getHierarchy();
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/RangeExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/RangeExpression.java
index 69baa3d8..d314aa31 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/RangeExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/RangeExpression.java
@@ -7,7 +7,7 @@ import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.core.RangeFunction;
 import com.mitchellbosecke.pebble.node.ArgumentsNode;
 import com.mitchellbosecke.pebble.node.PositionalArgumentNode;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 /**
@@ -19,7 +19,7 @@ import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 public class RangeExpression extends BinaryExpression<Object> {
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         List<PositionalArgumentNode> positionalArgs = new ArrayList<>();
         positionalArgs.add(new PositionalArgumentNode(getLeftExpression()));
         positionalArgs.add(new PositionalArgumentNode(getRightExpression()));
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/RenderableNodeExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/RenderableNodeExpression.java
index 27dc02f3..0bd78f3e 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/RenderableNodeExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/RenderableNodeExpression.java
@@ -14,7 +14,7 @@ import java.io.Writer;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.node.RenderableNode;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 /**
@@ -37,7 +37,7 @@ public class RenderableNodeExpression extends UnaryExpression {
     }
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         Writer writer = new StringWriter();
         try {
             node.render(self, writer, context);
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/SubtractExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/SubtractExpression.java
index d5c2d9e1..ad02eeee 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/SubtractExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/SubtractExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class SubtractExpression extends BinaryExpression<Object> {
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         try{
             return OperatorUtils.subtract(getLeftExpression().evaluate(self, context),
                     getRightExpression().evaluate(self, context));
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/TernaryExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/TernaryExpression.java
index 64b7e0ef..ebf05e9d 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/TernaryExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/TernaryExpression.java
@@ -10,7 +10,7 @@ package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class TernaryExpression implements Expression<Object> {
@@ -31,7 +31,7 @@ public class TernaryExpression implements Expression<Object> {
     }
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         if (expression1.evaluate(self, context) != null && expression1.evaluate(self, context)) {
             return expression2.evaluate(self, context);
         } else {
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/UnaryMinusExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/UnaryMinusExpression.java
index 0d9af609..703441e4 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/UnaryMinusExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/UnaryMinusExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class UnaryMinusExpression extends UnaryExpression {
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         return OperatorUtils.unaryMinus(getChildExpression().evaluate(self, context));
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/UnaryNotExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/UnaryNotExpression.java
index ff61f8ed..e5e0f24a 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/UnaryNotExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/UnaryNotExpression.java
@@ -9,13 +9,13 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class UnaryNotExpression extends UnaryExpression {
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         Boolean result = (Boolean) getChildExpression().evaluate(self, context);
         if (context.isStrictVariables()){
             if(result == null)
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/UnaryPlusExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/UnaryPlusExpression.java
index 05e5bc86..016353d9 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/UnaryPlusExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/UnaryPlusExpression.java
@@ -9,14 +9,14 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.utils.OperatorUtils;
 
 public class UnaryPlusExpression extends UnaryExpression {
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         return OperatorUtils.unaryPlus(getChildExpression().evaluate(self, context));
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/template/Block.java b/src/main/java/com/mitchellbosecke/pebble/template/Block.java
index 811736e3..727808da 100644
--- a/src/main/java/com/mitchellbosecke/pebble/template/Block.java
+++ b/src/main/java/com/mitchellbosecke/pebble/template/Block.java
@@ -17,6 +17,6 @@ public interface Block {
 
     String getName();
 
-    void evaluate(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context) throws PebbleException,
+    void evaluate(PebbleTemplateImpl self, Writer writer, EvaluationContext context) throws PebbleException,
             IOException;
 }
diff --git a/src/main/java/com/mitchellbosecke/pebble/template/EvaluationContext.java b/src/main/java/com/mitchellbosecke/pebble/template/EvaluationContext.java
index fe1943d9..88c6de98 100644
--- a/src/main/java/com/mitchellbosecke/pebble/template/EvaluationContext.java
+++ b/src/main/java/com/mitchellbosecke/pebble/template/EvaluationContext.java
@@ -1,13 +1,205 @@
+/*******************************************************************************
+ * This file is part of Pebble.
+ * <p>
+ * Copyright (c) 2014 by Mitchell Bösecke
+ * <p>
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ ******************************************************************************/
 package com.mitchellbosecke.pebble.template;
 
+import com.github.benmanes.caffeine.cache.Cache;
+import com.mitchellbosecke.pebble.cache.BaseTagCacheKey;
+import com.mitchellbosecke.pebble.extension.ExtensionRegistry;
+
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
+import java.util.concurrent.ExecutorService;
 
 /**
- * Created by mitchell on 2016-11-13.
+ * An evaluation context will store all stateful data that is necessary for the
+ * evaluation of a template. Passing the entire state around will assist with
+ * thread safety.
+ *
+ * @author Mitchell
  */
-public interface EvaluationContext {
+public class EvaluationContext {
+
+    private final boolean strictVariables;
+
+    /**
+     * A template will look to it's parent and children for overridden macros
+     * and other features; this inheritance chain will help the template keep
+     * track of where in the inheritance chain it currently is.
+     */
+    private final Hierarchy hierarchy;
+
+    /**
+     * A scope is a set of visible variables. A trivial template will only have
+     * one scope. New scopes are added with for loops and macros for example.
+     * <p>
+     * Most scopes will have a link to their parent scope which allow an
+     * evaluation to look up the scope chain for variables. A macro is an
+     * exception to this as it only has access to it's local variables.
+     */
+    private final ScopeChain scopeChain;
+
+    /**
+     * The locale of this template.
+     */
+    private final Locale locale;
+
+    /**
+     * All the available filters/tests/functions for this template.
+     */
+    private final ExtensionRegistry extensionRegistry;
+
+    /**
+     * The tag cache
+     */
+    private final Cache<BaseTagCacheKey, Object> tagCache;
+
+    /**
+     * The user-provided ExecutorService (can be null).
+     */
+    private final ExecutorService executorService;
+
+    /**
+     * The imported templates are used to look up macros.
+     */
+    private final List<PebbleTemplateImpl> importedTemplates;
+
+    /**
+     * Constructor used to provide all final variables.
+     *
+     * @param self              The template implementation
+     * @param strictVariables   Whether strict variables is to be used
+     * @param locale            The locale of the template
+     * @param extensionRegistry The extension registry
+     * @param executorService   The optional executor service
+     * @param scopeChain        The scope chain
+     * @param hierarchy         The inheritance chain
+     * @param tagCache          The cache used by the "cache" tag
+     */
+    public EvaluationContext(PebbleTemplateImpl self, boolean strictVariables, Locale locale,
+                             ExtensionRegistry extensionRegistry, Cache<BaseTagCacheKey, Object> tagCache,
+                             ExecutorService executorService, List<PebbleTemplateImpl> importedTemplates, ScopeChain scopeChain,
+                             Hierarchy hierarchy) {
+
+        if (hierarchy == null) {
+            hierarchy = new Hierarchy(self);
+        }
+
+        this.strictVariables = strictVariables;
+        this.locale = locale;
+        this.extensionRegistry = extensionRegistry;
+        this.tagCache = tagCache;
+        this.executorService = executorService;
+        this.importedTemplates = importedTemplates;
+        this.scopeChain = scopeChain;
+        this.hierarchy = hierarchy;
+    }
+
+    /**
+     * Makes an exact copy of the evaluation context EXCEPT for the inheritance
+     * chain. This is necessary for the "include" tag.
+     *
+     * @param self The template implementation
+     * @return A copy of the evaluation context
+     */
+    public EvaluationContext shallowCopyWithoutInheritanceChain(PebbleTemplateImpl self) {
+        EvaluationContext result = new EvaluationContext(self, strictVariables, locale, extensionRegistry, tagCache,
+                executorService, importedTemplates, scopeChain, null);
+        return result;
+    }
+
+    /**
+     * Makes a "snapshot" of the evaluation context. The scopeChain
+     * object will be a deep copy and the imported templates will be
+     * a new list. This is used for the "parallel" tag.
+     *
+     * @param self The template implementation
+     * @return A copy of the evaluation context
+     */
+    public EvaluationContext threadSafeCopy(PebbleTemplateImpl self) {
+        EvaluationContext result = new EvaluationContext(self, strictVariables, locale, extensionRegistry, tagCache,
+                executorService, new ArrayList<>(importedTemplates), scopeChain.deepCopy(), hierarchy);
+        return result;
+    }
+
+    /**
+     * Returns whether or not this template is being evaluated in "strict templates" mode
+     *
+     * @return Whether or not this template is being evaluated in "strict tempaltes" mode.
+     */
+    public boolean isStrictVariables() {
+        return strictVariables;
+    }
+
+    /**
+     * Returns the locale
+     *
+     * @return The current locale
+     */
+    public Locale getLocale() {
+        return locale;
+    }
+
+    /**
+     * Returns the extension registry used to access all of the tests/filters/functions
+     *
+     * @return The extension registry
+     */
+    public ExtensionRegistry getExtensionRegistry() {
+        return extensionRegistry;
+    }
+
+    /**
+     * Returns the executor service if exists or null
+     *
+     * @return The executor service if exists, or null
+     */
+    public ExecutorService getExecutorService() {
+        return executorService;
+    }
+
+    /**
+     * Returns a list of imported templates.
+     *
+     * @return A list of imported templates.
+     */
+    public List<PebbleTemplateImpl> getImportedTemplates() {
+        return this.importedTemplates;
+    }
+
+    /**
+     * Returns the cache used for the "cache" tag
+     *
+     * @return The cache used for the "cache" tag
+     */
+    public Cache<BaseTagCacheKey, Object> getTagCache() {
+        return tagCache;
+    }
+
+    /**
+     * Returns the scope chain data structure that allows variables to be added/removed from the current scope
+     * and retrieved from the nearest visible scopes.
+     *
+     * @return The scope chain.
+     */
+    public ScopeChain getScopeChain() {
+        return scopeChain;
+    }
 
-    boolean isStrictVariables();
+    /**
+     * Returns the data structure representing the entire hierarchy of
+     * the template currently being evaluated.
+     *
+     * @return The inheritance chain
+     */
+    public Hierarchy getHierarchy() {
+        return hierarchy;
+    }
 
-    Locale getLocale();
 }
diff --git a/src/main/java/com/mitchellbosecke/pebble/template/EvaluationContextImpl.java b/src/main/java/com/mitchellbosecke/pebble/template/EvaluationContextImpl.java
deleted file mode 100644
index cbc3f0e1..00000000
--- a/src/main/java/com/mitchellbosecke/pebble/template/EvaluationContextImpl.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*******************************************************************************
- * This file is part of Pebble.
- * <p>
- * Copyright (c) 2014 by Mitchell Bösecke
- * <p>
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- ******************************************************************************/
-package com.mitchellbosecke.pebble.template;
-
-import com.google.common.cache.Cache;
-import com.mitchellbosecke.pebble.cache.BaseTagCacheKey;
-import com.mitchellbosecke.pebble.extension.ExtensionRegistry;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.concurrent.ExecutorService;
-
-/**
- * An evaluation context will store all stateful data that is necessary for the
- * evaluation of a template. Passing the entire state around will assist with
- * thread safety.
- *
- * @author Mitchell
- */
-public class EvaluationContextImpl implements EvaluationContext {
-
-    private final boolean strictVariables;
-
-    /**
-     * A template will look to it's parent and children for overridden macros
-     * and other features; this inheritance chain will help the template keep
-     * track of where in the inheritance chain it currently is.
-     */
-    private final Hierarchy hierarchy;
-
-    /**
-     * A scope is a set of visible variables. A trivial template will only have
-     * one scope. New scopes are added with for loops and macros for example.
-     * <p>
-     * Most scopes will have a link to their parent scope which allow an
-     * evaluation to look up the scope chain for variables. A macro is an
-     * exception to this as it only has access to it's local variables.
-     */
-    private final ScopeChain scopeChain;
-
-    /**
-     * The locale of this template.
-     */
-    private final Locale locale;
-
-    /**
-     * All the available filters/tests/functions for this template.
-     */
-    private final ExtensionRegistry extensionRegistry;
-
-    /**
-     * The tag cache
-     */
-    private final Cache<BaseTagCacheKey, Object> tagCache;
-
-    /**
-     * The user-provided ExecutorService (can be null).
-     */
-    private final ExecutorService executorService;
-
-    /**
-     * The imported templates are used to look up macros.
-     */
-    private final List<PebbleTemplateImpl> importedTemplates;
-
-    /**
-     * Constructor used to provide all final variables.
-     *
-     * @param self              The template implementation
-     * @param strictVariables   Whether strict variables is to be used
-     * @param locale            The locale of the template
-     * @param extensionRegistry The extension registry
-     * @param executorService   The optional executor service
-     * @param scopeChain        The scope chain
-     * @param hierarchy         The inheritance chain
-     * @param tagCache          The cache used by the "cache" tag
-     */
-    public EvaluationContextImpl(PebbleTemplateImpl self, boolean strictVariables, Locale locale,
-                                 ExtensionRegistry extensionRegistry, Cache<BaseTagCacheKey, Object> tagCache,
-                                 ExecutorService executorService, List<PebbleTemplateImpl> importedTemplates, ScopeChain scopeChain,
-                                 Hierarchy hierarchy) {
-
-        if (hierarchy == null) {
-            hierarchy = new Hierarchy(self);
-        }
-
-        this.strictVariables = strictVariables;
-        this.locale = locale;
-        this.extensionRegistry = extensionRegistry;
-        this.tagCache = tagCache;
-        this.executorService = executorService;
-        this.importedTemplates = importedTemplates;
-        this.scopeChain = scopeChain;
-        this.hierarchy = hierarchy;
-    }
-
-    /**
-     * Makes an exact copy of the evaluation context EXCEPT for the inheritance
-     * chain. This is necessary for the "include" tag.
-     *
-     * @param self The template implementation
-     * @return A copy of the evaluation context
-     */
-    public EvaluationContextImpl shallowCopyWithoutInheritanceChain(PebbleTemplateImpl self) {
-        EvaluationContextImpl result = new EvaluationContextImpl(self, strictVariables, locale, extensionRegistry, tagCache,
-                executorService, importedTemplates, scopeChain, null);
-        return result;
-    }
-
-    /**
-     * Makes a "snapshot" of the evaluation context. The scopeChain
-     * object will be a deep copy and the imported templates will be
-     * a new list. This is used for the "parallel" tag.
-     *
-     * @param self The template implementation
-     * @return A copy of the evaluation context
-     */
-    public EvaluationContextImpl threadSafeCopy(PebbleTemplateImpl self) {
-        EvaluationContextImpl result = new EvaluationContextImpl(self, strictVariables, locale, extensionRegistry, tagCache,
-                executorService, new ArrayList<>(importedTemplates), scopeChain.deepCopy(), hierarchy);
-        return result;
-    }
-
-    /**
-     * Returns whether or not this template is being evaluated in "strict templates" mode
-     *
-     * @return Whether or not this template is being evaluated in "strict tempaltes" mode.
-     */
-    @Override
-    public boolean isStrictVariables() {
-        return strictVariables;
-    }
-
-    /**
-     * Returns the locale
-     *
-     * @return The current locale
-     */
-    @Override
-    public Locale getLocale() {
-        return locale;
-    }
-
-    /**
-     * Returns the extension registry used to access all of the tests/filters/functions
-     *
-     * @return The extension registry
-     */
-    public ExtensionRegistry getExtensionRegistry() {
-        return extensionRegistry;
-    }
-
-    /**
-     * Returns the executor service if exists or null
-     *
-     * @return The executor service if exists, or null
-     */
-    public ExecutorService getExecutorService() {
-        return executorService;
-    }
-
-    /**
-     * Returns a list of imported templates.
-     *
-     * @return A list of imported templates.
-     */
-    public List<PebbleTemplateImpl> getImportedTemplates() {
-        return this.importedTemplates;
-    }
-
-    /**
-     * Returns the cache used for the "cache" tag
-     *
-     * @return The cache used for the "cache" tag
-     */
-    public Cache<BaseTagCacheKey, Object> getTagCache() {
-        return tagCache;
-    }
-
-    /**
-     * Returns the scope chain data structure that allows variables to be added/removed from the current scope
-     * and retrieved from the nearest visible scopes.
-     *
-     * @return The scope chain.
-     */
-    public ScopeChain getScopeChain() {
-        return scopeChain;
-    }
-
-    /**
-     * Returns the data structure representing the entire hierarchy of
-     * the template currently being evaluated.
-     *
-     * @return The inheritance chain
-     */
-    public Hierarchy getHierarchy() {
-        return hierarchy;
-    }
-
-}
diff --git a/src/main/java/com/mitchellbosecke/pebble/template/Macro.java b/src/main/java/com/mitchellbosecke/pebble/template/Macro.java
index c20f0b00..e0a10a0a 100644
--- a/src/main/java/com/mitchellbosecke/pebble/template/Macro.java
+++ b/src/main/java/com/mitchellbosecke/pebble/template/Macro.java
@@ -17,6 +17,6 @@ public interface Macro extends NamedArguments {
 
     String getName();
 
-    String call(PebbleTemplateImpl self, EvaluationContextImpl context, Map<String, Object> args)
+    String call(PebbleTemplateImpl self, EvaluationContext context, Map<String, Object> args)
             throws PebbleException;
 }
diff --git a/src/main/java/com/mitchellbosecke/pebble/template/PebbleTemplateImpl.java b/src/main/java/com/mitchellbosecke/pebble/template/PebbleTemplateImpl.java
index 977952eb..cf828f56 100644
--- a/src/main/java/com/mitchellbosecke/pebble/template/PebbleTemplateImpl.java
+++ b/src/main/java/com/mitchellbosecke/pebble/template/PebbleTemplateImpl.java
@@ -71,23 +71,23 @@ public class PebbleTemplateImpl implements PebbleTemplate {
     }
 
     public void evaluate(Writer writer) throws PebbleException, IOException {
-        EvaluationContextImpl context = initContext(null);
+        EvaluationContext context = initContext(null);
         evaluate(writer, context);
     }
 
     public void evaluate(Writer writer, Locale locale) throws PebbleException, IOException {
-        EvaluationContextImpl context = initContext(locale);
+        EvaluationContext context = initContext(locale);
         evaluate(writer, context);
     }
 
     public void evaluate(Writer writer, Map<String, Object> map) throws PebbleException, IOException {
-        EvaluationContextImpl context = initContext(null);
+        EvaluationContext context = initContext(null);
         context.getScopeChain().pushScope(map);
         evaluate(writer, context);
     }
 
     public void evaluate(Writer writer, Map<String, Object> map, Locale locale) throws PebbleException, IOException {
-        EvaluationContextImpl context = initContext(locale);
+        EvaluationContext context = initContext(locale);
         context.getScopeChain().pushScope(map);
         evaluate(writer, context);
     }
@@ -101,7 +101,7 @@ public class PebbleTemplateImpl implements PebbleTemplate {
      * @throws PebbleException Thrown if any sort of template error occurs
      * @throws IOException     Thrown from the writer object
      */
-    private void evaluate(Writer writer, EvaluationContextImpl context) throws PebbleException, IOException {
+    private void evaluate(Writer writer, EvaluationContext context) throws PebbleException, IOException {
         if (context.getExecutorService() != null) {
             writer = new FutureWriter(writer);
         }
@@ -127,7 +127,7 @@ public class PebbleTemplateImpl implements PebbleTemplate {
      * @param locale The desired locale
      * @return The evaluation context
      */
-    private EvaluationContextImpl initContext(Locale locale) {
+    private EvaluationContext initContext(Locale locale) {
         locale = locale == null ? engine.getDefaultLocale() : locale;
 
         // globals
@@ -139,7 +139,7 @@ public class PebbleTemplateImpl implements PebbleTemplate {
         // global vars provided from extensions
         scopeChain.pushScope(engine.getExtensionRegistry().getGlobalVariables());
 
-        EvaluationContextImpl context = new EvaluationContextImpl(this, engine.isStrictVariables(), locale,
+        EvaluationContext context = new EvaluationContext(this, engine.isStrictVariables(), locale,
                 engine.getExtensionRegistry(), engine.getTagCache(), engine.getExecutorService(),
                 new ArrayList<PebbleTemplateImpl>(), scopeChain, null);
         return context;
@@ -153,7 +153,7 @@ public class PebbleTemplateImpl implements PebbleTemplate {
      * @throws PebbleException Thrown if an error occurs while rendering the imported
      *                         template
      */
-    public void importTemplate(EvaluationContextImpl context, String name) throws PebbleException {
+    public void importTemplate(EvaluationContext context, String name) throws PebbleException {
         context.getImportedTemplates().add((PebbleTemplateImpl) engine.getTemplate(this.resolveRelativePath(name)));
     }
 
@@ -168,10 +168,10 @@ public class PebbleTemplateImpl implements PebbleTemplate {
      * @throws PebbleException Any error occurring during the compilation of the template
      * @throws IOException     Any error during the loading of the template
      */
-    public void includeTemplate(Writer writer, EvaluationContextImpl context, String name, Map<?, ?> additionalVariables)
+    public void includeTemplate(Writer writer, EvaluationContext context, String name, Map<?, ?> additionalVariables)
             throws PebbleException, IOException {
         PebbleTemplateImpl template = (PebbleTemplateImpl) engine.getTemplate(this.resolveRelativePath(name));
-        EvaluationContextImpl newContext = context.shallowCopyWithoutInheritanceChain(template);
+        EvaluationContext newContext = context.shallowCopyWithoutInheritanceChain(template);
         ScopeChain scopeChain = newContext.getScopeChain();
         scopeChain.pushScope();
         for (Entry<?, ?> entry : additionalVariables.entrySet()) {
@@ -250,7 +250,7 @@ public class PebbleTemplateImpl implements PebbleTemplate {
      * @throws PebbleException Thrown if an error occurs
      * @throws IOException     Thrown from the writer object
      */
-    public void block(Writer writer, EvaluationContextImpl context, String blockName, boolean ignoreOverriden)
+    public void block(Writer writer, EvaluationContext context, String blockName, boolean ignoreOverriden)
             throws PebbleException, IOException {
 
         Hierarchy hierarchy = context.getHierarchy();
@@ -289,7 +289,7 @@ public class PebbleTemplateImpl implements PebbleTemplate {
      * @return The results of the macro invocation
      * @throws PebbleException An exception that may have occurred
      */
-    public SafeString macro(EvaluationContextImpl context, String macroName, ArgumentsNode args, boolean ignoreOverriden)
+    public SafeString macro(EvaluationContext context, String macroName, ArgumentsNode args, boolean ignoreOverriden)
             throws PebbleException {
         SafeString result = null;
         boolean found = false;
@@ -337,7 +337,7 @@ public class PebbleTemplateImpl implements PebbleTemplate {
         return result;
     }
 
-    public void setParent(EvaluationContextImpl context, String parentName) throws PebbleException {
+    public void setParent(EvaluationContext context, String parentName) throws PebbleException {
         context.getHierarchy()
                 .pushAncestor((PebbleTemplateImpl) engine.getTemplate(this.resolveRelativePath(parentName)));
     }
diff --git a/src/main/java/com/mitchellbosecke/pebble/template/Scope.java b/src/main/java/com/mitchellbosecke/pebble/template/Scope.java
index f8e3ebc3..509b3a13 100644
--- a/src/main/java/com/mitchellbosecke/pebble/template/Scope.java
+++ b/src/main/java/com/mitchellbosecke/pebble/template/Scope.java
@@ -20,6 +20,13 @@ import java.util.Map;
  */
 public class Scope {
 
+    /**
+     * A "local" scope ensures that
+     * the search for a particular variable will end at this scope
+     * whether or not it was found.
+     */
+    private final boolean isLocal;
+
     /**
      * The map of variables known at this scope
      */
@@ -29,9 +36,11 @@ public class Scope {
      * Constructor
      *
      * @param backingMap The backing map of variables
+     * @param isLocal    Whether this scope is local or not
      */
-    public Scope(Map<String, Object> backingMap) {
+    public Scope(Map<String, Object> backingMap, boolean isLocal) {
         this.backingMap = backingMap == null ? new HashMap<String, Object>() : backingMap;
+        this.isLocal = isLocal;
     }
 
     /**
@@ -52,7 +61,16 @@ public class Scope {
         Map<String, Object> backingMapCopy = new HashMap<>();
         backingMapCopy.putAll(backingMap);
 
-        return new Scope(backingMapCopy);
+        return new Scope(backingMapCopy, isLocal);
+    }
+
+    /**
+     * Returns whether or not this scope is "local".
+     *
+     * @return boolean stating whether this scope is local or not.
+     */
+    public boolean isLocal() {
+        return isLocal;
     }
 
     /**
diff --git a/src/main/java/com/mitchellbosecke/pebble/template/ScopeChain.java b/src/main/java/com/mitchellbosecke/pebble/template/ScopeChain.java
index 23df2458..3e84ecee 100644
--- a/src/main/java/com/mitchellbosecke/pebble/template/ScopeChain.java
+++ b/src/main/java/com/mitchellbosecke/pebble/template/ScopeChain.java
@@ -37,7 +37,7 @@ public class ScopeChain {
      * @param map The map of variables used to initialize a scope.
      */
     public ScopeChain(Map<String, Object> map) {
-        Scope scope = new Scope(new HashMap<>(map));
+        Scope scope = new Scope(new HashMap<>(map), false);
         stack.push(scope);
     }
 
@@ -76,7 +76,15 @@ public class ScopeChain {
      * @param map The known variables of this scope.
      */
     public void pushScope(Map<String, Object> map) {
-        Scope scope = new Scope(map);
+        Scope scope = new Scope(map, false);
+        stack.push(scope);
+    }
+
+    /**
+     * Adds a new local scope to the scope chain
+     */
+    public void pushLocalScope() {
+        Scope scope = new Scope(new HashMap<String, Object>(), true);
         stack.push(scope);
     }
 
@@ -126,6 +134,9 @@ public class ScopeChain {
                 scope = iterator.next();
 
                 result = scope.get(key);
+                if (scope.isLocal()) {
+                    break;
+                }
             }
         }
 
@@ -163,6 +174,9 @@ public class ScopeChain {
             if (scope.containsKey(key)) {
                 return true;
             }
+            if (scope.isLocal()) {
+                break;
+            }
         }
 
         return false;
@@ -194,7 +208,7 @@ public class ScopeChain {
          * create an iterator, etc. This is solely for performance.
          */
         Scope scope = stack.getFirst();
-        if (scope.containsKey(key)) {
+        if (scope.isLocal() || scope.containsKey(key)) {
             scope.put(key, value);
             return;
         }
@@ -207,7 +221,7 @@ public class ScopeChain {
         while (iterator.hasNext()) {
             scope = iterator.next();
 
-            if (scope.containsKey(key)) {
+            if (scope.isLocal() || scope.containsKey(key)) {
                 scope.put(key, value);
                 return;
             }


Test patch:
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/TestInvocationExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/TestInvocationExpression.java
index 2204c447..3c572895 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/TestInvocationExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/TestInvocationExpression.java
@@ -11,7 +11,7 @@ package com.mitchellbosecke.pebble.node;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.extension.NodeVisitor;
 import com.mitchellbosecke.pebble.node.expression.Expression;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 /**
@@ -29,7 +29,7 @@ public class TestInvocationExpression implements Expression<Object> {
     private final int lineNumber;
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         throw new UnsupportedOperationException();
     }
 
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/NegativeTestExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/NegativeTestExpression.java
index 0faca3b3..c30d60bd 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/NegativeTestExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/NegativeTestExpression.java
@@ -9,13 +9,13 @@
 package com.mitchellbosecke.pebble.node.expression;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 public class NegativeTestExpression extends PositiveTestExpression {
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
         return !((Boolean) super.evaluate(self, context));
     }
 }
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/PositiveTestExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/PositiveTestExpression.java
index 1b05ec40..c73bd74d 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/PositiveTestExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/PositiveTestExpression.java
@@ -14,7 +14,7 @@ import com.mitchellbosecke.pebble.extension.Test;
 import com.mitchellbosecke.pebble.extension.core.DefinedTest;
 import com.mitchellbosecke.pebble.node.ArgumentsNode;
 import com.mitchellbosecke.pebble.node.TestInvocationExpression;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
 import java.util.Map;
@@ -24,7 +24,7 @@ public class PositiveTestExpression extends BinaryExpression<Object> {
     private Test cachedTest;
 
     @Override
-    public Object evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) throws PebbleException {
+    public Object evaluate(PebbleTemplateImpl self, EvaluationContext context) throws PebbleException {
 
         TestInvocationExpression testInvocation = (TestInvocationExpression) getRightExpression();
         ArgumentsNode args = testInvocation.getArgs();
diff --git a/src/test/java/com/mitchellbosecke/pebble/ArraySyntaxTest.java b/src/test/java/com/mitchellbosecke/pebble/ArraySyntaxTest.java
index e329c636..ff4a5eb0 100644
--- a/src/test/java/com/mitchellbosecke/pebble/ArraySyntaxTest.java
+++ b/src/test/java/com/mitchellbosecke/pebble/ArraySyntaxTest.java
@@ -10,9 +10,12 @@ package com.mitchellbosecke.pebble;
 
 import com.mitchellbosecke.pebble.error.ParserException;
 import com.mitchellbosecke.pebble.error.PebbleException;
+import com.mitchellbosecke.pebble.error.RuntimePebbleException;
 import com.mitchellbosecke.pebble.loader.StringLoader;
 import com.mitchellbosecke.pebble.template.PebbleTemplate;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.io.IOException;
 import java.io.StringWriter;
@@ -20,11 +23,16 @@ import java.io.Writer;
 import java.util.HashMap;
 import java.util.Map;
 
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.StringStartsWith.startsWith;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
 public class ArraySyntaxTest extends AbstractTest {
 
+    @Rule
+    public final ExpectedException thrown = ExpectedException.none();
+
     @Test
     public void testArraySyntax() throws PebbleException, IOException {
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
@@ -87,15 +95,18 @@ public class ArraySyntaxTest extends AbstractTest {
                 writer.toString());
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testIncompleteArraySyntax() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ [,] }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
     @SuppressWarnings("serial")
@@ -440,16 +451,21 @@ public class ArraySyntaxTest extends AbstractTest {
         assertEquals("[0, 1, 2, 3]", writer.toString());
     }
 
-    @Test(expected = PebbleException.class)
+    @Test
     public void testAdditionOverloading3() throws PebbleException, IOException {
-
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{% set arr = 1 + [0,1] %}{{ arr }}";
         PebbleTemplate template = pebble.getTemplate(source);
 
         Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+
+        thrown.expect(PebbleException.class);
+        thrown.expectMessage(startsWith("Could not perform addition"));
+
+        //Act + Assert
+        template.evaluate(writer, new HashMap<>());
     }
 
     @Test
@@ -478,16 +494,21 @@ public class ArraySyntaxTest extends AbstractTest {
         assertEquals("[1]", writer.toString());
     }
 
-    @Test(expected = PebbleException.class)
+    @Test
     public void testSubtractionOverloading3() throws PebbleException, IOException {
-
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{% set arr = 1 - [0,2] %}{{ arr }}";
         PebbleTemplate template = pebble.getTemplate(source);
 
         Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+
+        thrown.expect(PebbleException.class);
+        thrown.expectMessage(startsWith("Could not perform subtraction"));
+
+        //Act + Assert
+        template.evaluate(writer, new HashMap<>());
     }
 
     @Test
@@ -599,12 +620,12 @@ public class ArraySyntaxTest extends AbstractTest {
 
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
-        String source = "{% if [0,1,2] contains 10 %}true{% else %}false{% endif %}";
+        String source = "{% if not [0,1,2] contains 10 %}true{% endif %}";
         PebbleTemplate template = pebble.getTemplate(source);
 
         Writer writer = new StringWriter();
         template.evaluate(writer, new HashMap<String, Object>());
-        assertEquals("false", writer.toString());
+        assertEquals("true", writer.toString());
     }
 
     @Test
@@ -612,7 +633,7 @@ public class ArraySyntaxTest extends AbstractTest {
 
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
-        String source = "{% if [0,1,2] contains 1 and not ([0,1] contains 0) %}true{% else %}false{% endif %}";
+        String source = "{% if [0,1,2] contains 1 and not [0,1] contains 0 %}true{% else %}false{% endif %}";
         PebbleTemplate template = pebble.getTemplate(source);
 
         Writer writer = new StringWriter();
diff --git a/src/test/java/com/mitchellbosecke/pebble/CoreTagsTest.java b/src/test/java/com/mitchellbosecke/pebble/CoreTagsTest.java
index 8c86bf0c..99cbc9e7 100755
--- a/src/test/java/com/mitchellbosecke/pebble/CoreTagsTest.java
+++ b/src/test/java/com/mitchellbosecke/pebble/CoreTagsTest.java
@@ -11,8 +11,12 @@
 package com.mitchellbosecke.pebble;
 
 import com.mitchellbosecke.pebble.error.PebbleException;
+import com.mitchellbosecke.pebble.error.RuntimePebbleException;
+import com.mitchellbosecke.pebble.extension.InvocationCountingFunction;
+import com.mitchellbosecke.pebble.extension.TestingExtension;
 import com.mitchellbosecke.pebble.loader.StringLoader;
 import com.mitchellbosecke.pebble.template.PebbleTemplate;
+
 import org.junit.Test;
 
 import java.io.IOException;
@@ -22,6 +26,7 @@ import java.util.*;
 import java.util.concurrent.Executors;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 public class CoreTagsTest extends AbstractTest {
 
@@ -358,7 +363,116 @@ public class CoreTagsTest extends AbstractTest {
         assertEquals("yes", writer.toString());
     }
 
+    @Test
+    public void testMacro() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
+        PebbleTemplate template = pebble.getTemplate("templates/template.macro1.peb");
+
+        Writer writer = new StringWriter();
+        template.evaluate(writer);
+        assertEquals("	<input name=\"company\" value=\"google\" type=\"text\" />" + LINE_SEPARATOR,
+                writer.toString());
+    }
+
+    /**
+     * This ensures that macro inheritance works properly even if it skips a
+     * generation.
+     *
+     * @throws PebbleException
+     * @throws IOException
+     */
+    @Test
+    public void skipGenerationMacro() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
+        PebbleTemplate template = pebble.getTemplate("templates/template.skipGenerationMacro1.peb");
+        Writer writer = new StringWriter();
+        template.evaluate(writer);
+        assertEquals("success", writer.toString());
+    }
+
+    @Test(expected = RuntimeException.class)
+    public void testMacrosWithSameName() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
+        PebbleTemplate template = pebble.getTemplate(
+                "{{ test() }}{% macro test(one) %}ONE{% endmacro %}{% macro test(one,two) %}TWO{% endmacro %}");
+
+        Writer writer = new StringWriter();
+        template.evaluate(writer);
+        assertEquals("	<input name=\"company\" value=\"google\" type=\"text\" />" + LINE_SEPARATOR,
+                writer.toString());
+    }
+
+    @Test
+    public void testMacroWithDefaultArgument() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
+        PebbleTemplate template = pebble.getTemplate(
+                "{{ input(name='country') }}{% macro input(type='text', name) %}{{ type }} {{ name }}{% endmacro %}");
+
+        Writer writer = new StringWriter();
+        template.evaluate(writer);
+        assertEquals("text country", writer.toString());
+    }
+
+    /**
+     * There was an issue where the second invokation of a macro did not have
+     * access to the original arguments any more.
+     *
+     * @throws PebbleException
+     * @throws IOException
+     */
+    @Test
+    public void testMacroInvokedTwice() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
+        PebbleTemplate template = pebble.getTemplate("templates/template.macroDouble.peb");
+
+        Writer writer = new StringWriter();
+        template.evaluate(writer);
+        assertEquals("onetwo", writer.toString());
+    }
+
+    @Test
+    public void testFunctionInMacroInvokedTwice() throws PebbleException, IOException {
+
+        TestingExtension extension = new TestingExtension();
+        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false)
+                .extension(extension).build();
+
+        PebbleTemplate template = pebble
+                .getTemplate("{{ test() }}{% macro test() %}{{ invocationCountingFunction() }}{% endmacro %}");
+
+        Writer writer = new StringWriter();
+        template.evaluate(writer);
+
+        InvocationCountingFunction function = extension.getInvocationCountingFunction();
+        assertEquals(1, function.getInvocationCount());
+    }
+
+    @Test
+    public void testMacroInvocationWithoutAllArguments() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
+        PebbleTemplate template = pebble
+                .getTemplate("{{ test('1') }}{% macro test(one,two) %}{{ one }}{{ two }}{% endmacro %}");
 
+        Writer writer = new StringWriter();
+        template.evaluate(writer);
+        assertEquals("1", writer.toString());
+    }
+
+    /**
+     * I was once writing macro output directly to writer which was preventing
+     * output from being filtered. I have fixed this now.
+     *
+     * @throws PebbleException
+     */
+    @Test
+    public void testMacroBeingFiltered() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
+        PebbleTemplate template = pebble.getTemplate("templates/template.macro3.peb");
+
+        Writer writer = new StringWriter();
+        template.evaluate(writer);
+        assertEquals("HELLO" + LINE_SEPARATOR, writer.toString());
+    }
 
     @Test
     public void testCache() throws PebbleException, IOException {
@@ -425,7 +539,7 @@ public class CoreTagsTest extends AbstractTest {
         assertEquals("true", writer.toString());
     }
 
-    @Test(expected = PebbleException.class)
+    @Test(expected = RuntimePebbleException.class)
     public void testCacheWithNoName() throws PebbleException, IOException {
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
@@ -552,7 +666,45 @@ public class CoreTagsTest extends AbstractTest {
                 writer.toString());
     }
 
+    @Test
+    public void testImportFile() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
+        PebbleTemplate template = pebble.getTemplate("templates/template.macro2.peb");
+
+        Writer writer = new StringWriter();
+        template.evaluate(writer);
+        assertEquals("	<input name=\"company\" value=\"forcorp\" type=\"text\" />" + LINE_SEPARATOR,
+                writer.toString());
+    }
 
+    @Test
+    public void testImportInChildTemplateOutsideOfBlock() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
+        PebbleTemplate template = pebble.getTemplate("templates/template.macro.child.peb");
+
+        Writer writer = new StringWriter();
+        template.evaluate(writer);
+        assertEquals("	<input name=\"company\" value=\"forcorp\" type=\"text\" />" + LINE_SEPARATOR,
+                writer.toString());
+    }
+    
+    @Test
+    public void testDynamicImport() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
+        PebbleTemplate template = pebble.getTemplate("templates/template.import.dynamic.peb");
+
+        Map<String, Object> context = new HashMap<>();
+
+        context.put("modern", false);
+        Writer writer = new StringWriter();
+        template.evaluate(writer, context);
+        assertEquals("classic macro" + LINE_SEPARATOR, writer.toString());
+
+        context.put("modern", true);
+        writer = new StringWriter();
+        template.evaluate(writer, context);
+        assertEquals("ajax macro" + LINE_SEPARATOR, writer.toString());
+    }
 
     @Test
     public void testDynamicInclude() throws PebbleException, IOException {
diff --git a/src/test/java/com/mitchellbosecke/pebble/CoreTestsTest.java b/src/test/java/com/mitchellbosecke/pebble/CoreTestsTest.java
index 2c484a95..f321ef18 100644
--- a/src/test/java/com/mitchellbosecke/pebble/CoreTestsTest.java
+++ b/src/test/java/com/mitchellbosecke/pebble/CoreTestsTest.java
@@ -180,7 +180,7 @@ public class CoreTestsTest extends AbstractTest {
     public void testNegativeTest() throws PebbleException, IOException {
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
-        String source = "{% if not (2 is odd) %}yes{% else %}no{% endif %}";
+        String source = "{% if not 2 is odd %}yes{% else %}no{% endif %}";
         PebbleTemplate template = pebble.getTemplate(source);
 
         Writer writer = new StringWriter();
@@ -201,7 +201,7 @@ public class CoreTestsTest extends AbstractTest {
     public void testNegativeTestOnAttribute() throws PebbleException, IOException {
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
-        String source = "{% if not (classroom.students is empty) %}yes{% else %}no{% endif %}";
+        String source = "{% if not classroom.students is empty %}yes{% else %}no{% endif %}";
         PebbleTemplate template = pebble.getTemplate(source);
         Map<String, Object> context = new HashMap<>();
         context.put("classroom", new Classroom());
diff --git a/src/test/java/com/mitchellbosecke/pebble/ErrorReportingTest.java b/src/test/java/com/mitchellbosecke/pebble/ErrorReportingTest.java
index 559de879..61a17f8d 100644
--- a/src/test/java/com/mitchellbosecke/pebble/ErrorReportingTest.java
+++ b/src/test/java/com/mitchellbosecke/pebble/ErrorReportingTest.java
@@ -11,70 +11,82 @@ package com.mitchellbosecke.pebble;
 import com.mitchellbosecke.pebble.error.ParserException;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.error.RootAttributeNotFoundException;
+import com.mitchellbosecke.pebble.error.RuntimePebbleException;
 import com.mitchellbosecke.pebble.loader.StringLoader;
 import com.mitchellbosecke.pebble.template.PebbleTemplate;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.io.IOException;
 import java.io.StringWriter;
 
-import static org.junit.Assert.assertEquals;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
+import static org.hamcrest.core.AllOf.allOf;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.StringEndsWith.endsWith;
 
 public class ErrorReportingTest extends AbstractTest {
 
-    @Test(expected = ParserException.class)
+    @Rule
+    public final ExpectedException thrown = ExpectedException.none();
+
+    @Test
     public void testLineNumberErrorReportingWithUnixNewlines() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
-        try {
-            @SuppressWarnings("unused")
-            PebbleTemplate template = pebble.getTemplate("test\n\n\ntest\ntest\ntest\n{% error %}\ntest");
-        } catch (ParserException ex) {
-            String message = ex.getMessage();
-            System.out.println(message.substring(message.length() - 3, message.length()));
-            assertEquals(":7)", message.substring(message.length() - 3, message.length()));
-            throw ex;
-        }
+
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectMessage(endsWith(":7)"));
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate("test\n\n\ntest\ntest\ntest\n{% error %}\ntest");
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testLineNumberErrorReportingWithWindowsNewlines() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
-        try {
-            @SuppressWarnings("unused")
-            PebbleTemplate template = pebble.getTemplate("test\r\n\r\ntest\r\ntest\r\ntest\r\n{% error %}\r\ntest");
-        } catch (ParserException ex) {
-            String message = ex.getMessage();
-            assertEquals(":6)", message.substring(message.length() - 3, message.length()));
-            throw ex;
-        }
+
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectMessage(endsWith(":6)"));
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate("test\r\n\r\ntest\r\ntest\r\ntest\r\n{% error %}\r\ntest");
     }
 
-    @Test(expected = PebbleException.class)
+    @Test
     public void testLineNumberErrorReportingDuringEvaluation() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
-        try {
-            PebbleTemplate template = pebble.getTemplate("templates/template.errorReporting.peb");
-            template.evaluate(new StringWriter());
-        } catch (PebbleException ex) {
-            String message = ex.getMessage();
-            assertEquals(":8)", message.substring(message.length() - 3, message.length()));
-            throw ex;
-        }
+
+        PebbleTemplate template = pebble.getTemplate("templates/template.errorReporting.peb");
+
+        thrown.expect(PebbleException.class);
+        thrown.expectMessage(endsWith(":8)"));
+
+        //Act + Assert
+        template.evaluate(new StringWriter());
     }
 
-    @Test(expected = RootAttributeNotFoundException.class)
+    @Test
     public void testMissingRootPropertyInStrictMode() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(true).build();
-        try {
-            PebbleTemplate template = pebble.getTemplate("templates/template.errorReportingMissingRootProperty.peb");
-            template.evaluate(new StringWriter());
-        } catch (PebbleException ex) {
-            String message = ex.getMessage();
-            assertEquals("root", ((RootAttributeNotFoundException) ex).getAttributeName());
-            assertEquals(message,
-                    "Root attribute [root] does not exist or can not be accessed and strict variables is set to true. (templates/template.errorReportingMissingRootProperty.peb:2)");
-            throw ex;
-        }
+        PebbleTemplate template = pebble.getTemplate("templates/template.errorReportingMissingRootProperty.peb");
+
+        thrown.expect(allOf(
+                    instanceOf(RootAttributeNotFoundException.class),
+                    hasProperty("attributeName", is("root"))
+                )
+        );
+        thrown.expectMessage("Root attribute [root] does not exist or can not be accessed and strict variables is set to true. (templates/template.errorReportingMissingRootProperty.peb:2)");
+
+        //Act
+        template.evaluate(new StringWriter());
     }
 
 }
diff --git a/src/test/java/com/mitchellbosecke/pebble/LogicTest.java b/src/test/java/com/mitchellbosecke/pebble/LogicTest.java
index 66cbcd15..dcd77932 100644
--- a/src/test/java/com/mitchellbosecke/pebble/LogicTest.java
+++ b/src/test/java/com/mitchellbosecke/pebble/LogicTest.java
@@ -904,7 +904,7 @@ public class LogicTest extends AbstractTest {
         
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
-        String source = "{% if not (names contains 'Cobra') %}yes{% else %}no{% endif %}";
+        String source = "{% if not names contains 'Cobra' %}yes{% else %}no{% endif %}";
         PebbleTemplate template = pebble.getTemplate(source);
 
         Map<String, Object> context = new HashMap<>();
diff --git a/src/test/java/com/mitchellbosecke/pebble/MacroTest.java b/src/test/java/com/mitchellbosecke/pebble/MacroTest.java
deleted file mode 100644
index 8e481874..00000000
--- a/src/test/java/com/mitchellbosecke/pebble/MacroTest.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package com.mitchellbosecke.pebble;
-
-import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.extension.InvocationCountingFunction;
-import com.mitchellbosecke.pebble.extension.TestingExtension;
-import com.mitchellbosecke.pebble.loader.StringLoader;
-import com.mitchellbosecke.pebble.template.PebbleTemplate;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Created by mitch_000 on 2016-11-13.
- */
-public class MacroTest extends AbstractTest {
-
-    public static final String LINE_SEPARATOR = System.lineSeparator();
-
-    @Test
-    public void testMacro() throws PebbleException, IOException {
-        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
-        PebbleTemplate template = pebble.getTemplate("templates/template.macro1.peb");
-
-        Writer writer = new StringWriter();
-        template.evaluate(writer);
-        assertEquals("	<input name=\"company\" value=\"google\" type=\"text\" />" + LINE_SEPARATOR,
-                writer.toString());
-    }
-
-    /**
-     * This ensures that macro inheritance works properly even if it skips a
-     * generation.
-     *
-     * @throws PebbleException
-     * @throws IOException
-     */
-    @Test
-    public void skipGenerationMacro() throws PebbleException, IOException {
-        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
-        PebbleTemplate template = pebble.getTemplate("templates/template.skipGenerationMacro1.peb");
-        Writer writer = new StringWriter();
-        template.evaluate(writer);
-        assertEquals("success", writer.toString());
-    }
-
-    @Test(expected = RuntimeException.class)
-    public void testMacrosWithSameName() throws PebbleException, IOException {
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
-        PebbleTemplate template = pebble.getTemplate(
-                "{{ test() }}{% macro test(one) %}ONE{% endmacro %}{% macro test(one,two) %}TWO{% endmacro %}");
-
-        Writer writer = new StringWriter();
-        template.evaluate(writer);
-        assertEquals("	<input name=\"company\" value=\"google\" type=\"text\" />" + LINE_SEPARATOR,
-                writer.toString());
-    }
-
-    @Test
-    public void testMacroWithDefaultArgument() throws PebbleException, IOException {
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
-        PebbleTemplate template = pebble.getTemplate(
-                "{{ input(name='country') }}{% macro input(type='text', name) %}{{ type }} {{ name }}{% endmacro %}");
-
-        Writer writer = new StringWriter();
-        template.evaluate(writer);
-        assertEquals("text country", writer.toString());
-    }
-
-    /**
-     * There was an issue where the second invokation of a macro did not have
-     * access to the original arguments any more.
-     *
-     * @throws PebbleException
-     * @throws IOException
-     */
-    @Test
-    public void testMacroInvokedTwice() throws PebbleException, IOException {
-        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
-        PebbleTemplate template = pebble.getTemplate("templates/template.macroDouble.peb");
-
-        Writer writer = new StringWriter();
-        template.evaluate(writer);
-        assertEquals("onetwo", writer.toString());
-    }
-
-    @Test
-    public void testFunctionInMacroInvokedTwice() throws PebbleException, IOException {
-
-        TestingExtension extension = new TestingExtension();
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false)
-                .extension(extension).build();
-
-        PebbleTemplate template = pebble
-                .getTemplate("{{ test() }}{% macro test() %}{{ invocationCountingFunction() }}{% endmacro %}");
-
-        Writer writer = new StringWriter();
-        template.evaluate(writer);
-
-        InvocationCountingFunction function = extension.getInvocationCountingFunction();
-        assertEquals(1, function.getInvocationCount());
-    }
-
-    @Test
-    public void testMacroInvocationWithoutAllArguments() throws PebbleException, IOException {
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
-        PebbleTemplate template = pebble
-                .getTemplate("{{ test('1') }}{% macro test(one,two) %}{{ one }}{{ two }}{% endmacro %}");
-
-        Writer writer = new StringWriter();
-        template.evaluate(writer);
-        assertEquals("1", writer.toString());
-    }
-
-    /**
-     * I was once writing macro output directly to writer which was preventing
-     * output from being filtered. I have fixed this now.
-     *
-     * @throws PebbleException
-     */
-    @Test
-    public void testMacroBeingFiltered() throws PebbleException, IOException {
-        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
-        PebbleTemplate template = pebble.getTemplate("templates/template.macro3.peb");
-
-        Writer writer = new StringWriter();
-        template.evaluate(writer);
-        assertEquals("HELLO" + LINE_SEPARATOR, writer.toString());
-    }
-
-    @Test
-    public void testMacroHasAccessToGlobalVariables() throws PebbleException, IOException {
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
-        PebbleTemplate template = pebble
-                .getTemplate("{% set foo = 'bar' %}{{ test() }}{% macro test() %}{{ foo }}{% endmacro %}");
-
-        Writer writer = new StringWriter();
-        template.evaluate(writer);
-        assertEquals("bar", writer.toString());
-    }
-
-    @Test
-    public void testImportFile() throws PebbleException, IOException {
-        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
-        PebbleTemplate template = pebble.getTemplate("templates/template.macro2.peb");
-
-        Writer writer = new StringWriter();
-        template.evaluate(writer);
-        assertEquals("	<input name=\"company\" value=\"forcorp\" type=\"text\" />" + LINE_SEPARATOR,
-                writer.toString());
-    }
-
-    @Test
-    public void testImportInChildTemplateOutsideOfBlock() throws PebbleException, IOException {
-        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
-        PebbleTemplate template = pebble.getTemplate("templates/template.macro.child.peb");
-
-        Writer writer = new StringWriter();
-        template.evaluate(writer);
-        assertEquals("	<input name=\"company\" value=\"forcorp\" type=\"text\" />" + LINE_SEPARATOR,
-                writer.toString());
-    }
-
-    @Test
-    public void testDynamicImport() throws PebbleException, IOException {
-        PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
-        PebbleTemplate template = pebble.getTemplate("templates/template.import.dynamic.peb");
-
-        Map<String, Object> context = new HashMap<>();
-
-        context.put("modern", false);
-        Writer writer = new StringWriter();
-        template.evaluate(writer, context);
-        assertEquals("classic macro" + LINE_SEPARATOR, writer.toString());
-
-        context.put("modern", true);
-        writer = new StringWriter();
-        template.evaluate(writer, context);
-        assertEquals("ajax macro" + LINE_SEPARATOR, writer.toString());
-    }
-}
diff --git a/src/test/java/com/mitchellbosecke/pebble/MapSyntaxTest.java b/src/test/java/com/mitchellbosecke/pebble/MapSyntaxTest.java
index 3b9e7f32..2d84b291 100644
--- a/src/test/java/com/mitchellbosecke/pebble/MapSyntaxTest.java
+++ b/src/test/java/com/mitchellbosecke/pebble/MapSyntaxTest.java
@@ -10,10 +10,13 @@ package com.mitchellbosecke.pebble;
 
 import com.mitchellbosecke.pebble.error.ParserException;
 import com.mitchellbosecke.pebble.error.PebbleException;
+import com.mitchellbosecke.pebble.error.RuntimePebbleException;
 import com.mitchellbosecke.pebble.extension.TestingExtension;
 import com.mitchellbosecke.pebble.loader.StringLoader;
 import com.mitchellbosecke.pebble.template.PebbleTemplate;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.io.IOException;
 import java.io.StringWriter;
@@ -21,11 +24,16 @@ import java.io.Writer;
 import java.util.HashMap;
 import java.util.Map;
 
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.StringEndsWith.endsWith;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 public class MapSyntaxTest extends AbstractTest {
 
+    @Rule
+    public final ExpectedException thrown = ExpectedException.none();
+
     @Test
     public void testMapSyntax() throws PebbleException, IOException {
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
@@ -89,59 +97,74 @@ public class MapSyntaxTest extends AbstractTest {
         assertEquals("{key1=value1, key2=value2, key3=value3, key4=value4, key5=value5}", writer.toString());
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testIncompleteMapSyntax() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ {,} }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testIncompleteMapSyntax2() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ {'key'} }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testIncompleteMapSyntax3() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ {'key':} }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testIncompleteMapSyntax4() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ {:'value'} }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testIncompleteMapSyntax5() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ {'key':'value',} }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
     @SuppressWarnings("serial")
@@ -368,7 +391,7 @@ public class MapSyntaxTest extends AbstractTest {
     public void testContainsOperator2() throws PebbleException, IOException {
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
-        String source = "{% if not ( {'Bob':'Marley','Maria':'Callas','John':'Cobra'} contains 'Freddie') %}true{% else %}false{% endif %}";
+        String source = "{% if not {'Bob':'Marley','Maria':'Callas','John':'Cobra'} contains 'Freddie' %}true{% else %}false{% endif %}";
         PebbleTemplate template = pebble.getTemplate(source);
 
         Writer writer = new StringWriter();
@@ -380,7 +403,7 @@ public class MapSyntaxTest extends AbstractTest {
     public void testContainsOperator3() throws PebbleException, IOException {
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
-        String source = "{% if {'Bob':'Marley','Maria':'Callas','John':'Cobra'} contains 'John' and not ({'Freddie':'Mercury'} contains 'Bob') %}true{% else %}false{% endif %}";
+        String source = "{% if {'Bob':'Marley','Maria':'Callas','John':'Cobra'} contains 'John' and not {'Freddie':'Mercury'} contains 'Bob' %}true{% else %}false{% endif %}";
         PebbleTemplate template = pebble.getTemplate(source);
 
         Writer writer = new StringWriter();
diff --git a/src/test/java/com/mitchellbosecke/pebble/NewlineTrimmingTest.java b/src/test/java/com/mitchellbosecke/pebble/NewlineTrimmingTest.java
deleted file mode 100644
index f8ce6526..00000000
--- a/src/test/java/com/mitchellbosecke/pebble/NewlineTrimmingTest.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*******************************************************************************
- * This file is part of Pebble.
- * <p>
- * Copyright (c) 2014 by Mitchell Bösecke
- * <p>
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- ******************************************************************************/
-package com.mitchellbosecke.pebble;
-
-import com.mitchellbosecke.pebble.error.PebbleException;
-import com.mitchellbosecke.pebble.loader.StringLoader;
-import com.mitchellbosecke.pebble.template.PebbleTemplate;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-
-public class NewlineTrimmingTest extends AbstractTest {
-
-    @Test
-    public void testPrintDefault() throws PebbleException, IOException {
-
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
-                                                        .build();
-
-        PebbleTemplate template = pebble.getTemplate("{{param1}}\n{{param2}}");
-
-        Writer writer = new StringWriter();
-
-        Map<String, Object> params = new HashMap<String, Object>();
-        params.put("param1", "val1");
-        params.put("param2", "val2");
-
-        template.evaluate(writer, params);
-
-        assertEquals("val1val2", writer.toString());
-    }
-
-    @Test
-    public void testPrintForceToTrue() throws PebbleException, IOException {
-
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
-                                                        .newLineTrimming(true)
-                                                        .build();
-
-        PebbleTemplate template = pebble.getTemplate("{{param1}}\n{{param2}}");
-
-        Writer writer = new StringWriter();
-
-        Map<String, Object> params = new HashMap<>();
-        params.put("param1", "val1");
-        params.put("param2", "val2");
-
-        template.evaluate(writer, params);
-
-        assertEquals("val1val2", writer.toString());
-    }
-
-    @Test
-    public void testPrintSetToFalse() throws PebbleException, IOException {
-
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
-                                                        .newLineTrimming(false)
-                                                        .build();
-
-        PebbleTemplate template = pebble.getTemplate("{{param1}}\n{{param2}}");
-
-        Writer writer = new StringWriter();
-
-        Map<String, Object> params = new HashMap<String, Object>();
-        params.put("param1", "val1");
-        params.put("param2", "val2");
-
-        template.evaluate(writer, params);
-
-        assertEquals("val1\nval2", writer.toString());
-    }
-    
-    @Test
-    public void testPrintDefaultTwoNewlines() throws PebbleException, IOException {
-
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
-                                                        .build();
-
-        PebbleTemplate template = pebble.getTemplate("{{param1}}\n\n{{param2}}");
-
-        Writer writer = new StringWriter();
-
-        Map<String, Object> params = new HashMap<String, Object>();
-        params.put("param1", "val1");
-        params.put("param2", "val2");
-
-        template.evaluate(writer, params);
-
-        assertEquals("val1\nval2", writer.toString());
-    }
-    
-    @Test
-    public void testPrintSetToFalseTwoNewlines() throws PebbleException, IOException {
-
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
-                                                        .newLineTrimming(false)
-                                                        .build();
-
-        PebbleTemplate template = pebble.getTemplate("{{param1}}\n\n{{param2}}");
-
-        Writer writer = new StringWriter();
-
-        Map<String, Object> params = new HashMap<String, Object>();
-        params.put("param1", "val1");
-        params.put("param2", "val2");
-
-        template.evaluate(writer, params);
-
-        assertEquals("val1\n\nval2", writer.toString());
-    }
-
-    @Test
-    public void testCommentDefault() throws PebbleException, IOException {
-
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
-                                                        .build();
-
-        PebbleTemplate template = pebble.getTemplate("{# comment1 #}\n{# comment2 #}");
-
-        Writer writer = new StringWriter();
-
-        template.evaluate(writer);
-
-        assertEquals("", writer.toString());
-    }
-
-    @Test
-    public void testCommentForceToTrue() throws PebbleException, IOException {
-
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
-                                                        .newLineTrimming(true)
-                                                        .build();
-
-        PebbleTemplate template = pebble.getTemplate("{# comment1 #}\n{# comment2 #}");
-
-        Writer writer = new StringWriter();
-
-        template.evaluate(writer);
-
-        assertEquals("", writer.toString());
-    }
-
-    @Test
-    public void testCommentSetToFalse() throws PebbleException, IOException {
-
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
-                                                        .newLineTrimming(false)
-                                                        .build();
-
-        PebbleTemplate template = pebble.getTemplate("{# comment1 #}\n{# comment2 #}");
-
-        Writer writer = new StringWriter();
-
-        template.evaluate(writer);
-
-        assertEquals("\n", writer.toString());
-    }
-
-    @Test
-    public void testExecuteDefault() throws PebbleException, IOException {
-
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
-                                                        .build();
-
-        PebbleTemplate template = pebble.getTemplate("{% if true %}\n{% endif %}");
-
-        Writer writer = new StringWriter();
-
-        template.evaluate(writer);
-
-        assertEquals("", writer.toString());
-    }
-
-    @Test
-    public void testExecuteForceToTrue() throws PebbleException, IOException {
-
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
-                                                        .newLineTrimming(true)
-                                                        .build();
-
-        PebbleTemplate template = pebble.getTemplate("{% if true %}\n{% endif %}");
-
-        Writer writer = new StringWriter();
-
-        template.evaluate(writer);
-
-        assertEquals("", writer.toString());
-    }
-
-    @Test
-    public void testExecuteSetToFalse() throws PebbleException, IOException {
-
-        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
-                                                        .newLineTrimming(false)
-                                                        .build();
-
-        PebbleTemplate template = pebble.getTemplate("{% if true %}\n{% endif %}");
-
-        Writer writer = new StringWriter();
-
-        template.evaluate(writer);
-
-        assertEquals("\n", writer.toString());
-    }
-    
-
-}
diff --git a/src/test/java/com/mitchellbosecke/pebble/ParsingOdditiesTest.java b/src/test/java/com/mitchellbosecke/pebble/ParsingOdditiesTest.java
index c30a7fd5..a7ec4ed7 100755
--- a/src/test/java/com/mitchellbosecke/pebble/ParsingOdditiesTest.java
+++ b/src/test/java/com/mitchellbosecke/pebble/ParsingOdditiesTest.java
@@ -10,9 +10,12 @@ package com.mitchellbosecke.pebble;
 
 import com.mitchellbosecke.pebble.error.ParserException;
 import com.mitchellbosecke.pebble.error.PebbleException;
+import com.mitchellbosecke.pebble.error.RuntimePebbleException;
 import com.mitchellbosecke.pebble.loader.StringLoader;
 import com.mitchellbosecke.pebble.template.PebbleTemplate;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.io.IOException;
 import java.io.StringWriter;
@@ -25,10 +28,14 @@ import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
 import static org.junit.Assert.assertEquals;
 
 public class ParsingOdditiesTest extends AbstractTest {
 
+    @Rule
+    public final ExpectedException thrown = ExpectedException.none();
+
     @Test
     public void testEscapeCharactersText() throws PebbleException, IOException {
         PebbleEngine pebble = new PebbleEngine.Builder().strictVariables(false).build();
@@ -68,22 +75,19 @@ public class ParsingOdditiesTest extends AbstractTest {
         assertEquals("2012/July/1", writer.toString());
     }
 
-    @Test(expected = PebbleException.class)
+    @Test
     public void testPositionalArgumentAfterNamedArguments() throws PebbleException, IOException, ParseException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false)
                 .defaultLocale(Locale.ENGLISH).build();
 
         String source = "{{ stringDate | date(existingFormat='yyyy-MMMM-d', 'yyyy/MMMM/d') }}";
 
-        PebbleTemplate template = pebble.getTemplate(source);
-        Map<String, Object> context = new HashMap<>();
-        DateFormat format = new SimpleDateFormat("yyyy-MMMM-d");
-        Date realDate = format.parse("2012-July-01");
-        context.put("stringDate", format.format(realDate));
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, context);
-        assertEquals("2012/July/1", writer.toString());
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
     @Test
@@ -147,15 +151,18 @@ public class ParsingOdditiesTest extends AbstractTest {
         assertEquals("test\ntest", writer.toString());
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testStringWithDifferentQuotationMarks() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
-        PebbleTemplate template = pebble.getTemplate("{{'test\"}}");
+        String source = "{{'test\"}}";
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer);
-        assertEquals("test", writer.toString());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
     @Test
diff --git a/src/test/java/com/mitchellbosecke/pebble/ScopeChainTest.java b/src/test/java/com/mitchellbosecke/pebble/ScopeChainTest.java
index 0f124ac6..fd49e03f 100644
--- a/src/test/java/com/mitchellbosecke/pebble/ScopeChainTest.java
+++ b/src/test/java/com/mitchellbosecke/pebble/ScopeChainTest.java
@@ -29,5 +29,10 @@ public class ScopeChainTest extends AbstractTest {
         assertEquals("value2", scopeChain.get("key"));
         scopeChain.popScope();
         assertEquals("value2", scopeChain.get("key"));
+        scopeChain.pushLocalScope();
+        scopeChain.set("key", "value3");
+        assertEquals("value3", scopeChain.get("key"));
+        scopeChain.popScope();
+        assertEquals("value2", scopeChain.get("key"));
     }
 }
diff --git a/src/test/java/com/mitchellbosecke/pebble/TernaryExpressionTest.java b/src/test/java/com/mitchellbosecke/pebble/TernaryExpressionTest.java
index d4346e34..c1967846 100644
--- a/src/test/java/com/mitchellbosecke/pebble/TernaryExpressionTest.java
+++ b/src/test/java/com/mitchellbosecke/pebble/TernaryExpressionTest.java
@@ -10,9 +10,12 @@ package com.mitchellbosecke.pebble;
 
 import com.mitchellbosecke.pebble.error.ParserException;
 import com.mitchellbosecke.pebble.error.PebbleException;
+import com.mitchellbosecke.pebble.error.RuntimePebbleException;
 import com.mitchellbosecke.pebble.loader.StringLoader;
 import com.mitchellbosecke.pebble.template.PebbleTemplate;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.io.IOException;
 import java.io.StringWriter;
@@ -20,151 +23,194 @@ import java.io.Writer;
 import java.util.HashMap;
 import java.util.Map;
 
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
 import static org.junit.Assert.assertEquals;
 
 public class TernaryExpressionTest extends AbstractTest {
 
-    @Test(expected = ParserException.class)
+    @Rule
+    public final ExpectedException thrown = ExpectedException.none();
+
+    @Test
     public void testTernaryFail1() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? 'true' }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testTernaryFail2() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? : 'true' }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testTernaryFail3() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? 'true' : }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testTernaryFail4() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? : }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testTernaryFail5() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? : ? 'true' : 'false' }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testTernaryFail6() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? true ? 'true' : 'false' }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testTernaryFail7() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? : false ? 'true' : 'false' }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testTernaryFail8() throws PebbleException, IOException {
+        //arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? 2 > 2 ? 'true' : 'false' }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testTernaryFail9() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? 2 > 2 ? : 'false' : 'false' }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testTernaryFail10() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? 2 > 2 ? : : 'false' }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testTernaryFail11() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? 'true' : 3 > 3 ? 'false' }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testTernaryFail12() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? 'true' : 3 > 3 ? : 'false' }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
-    @Test(expected = ParserException.class)
+    @Test
     public void testTernaryFail13() throws PebbleException, IOException {
+        //Arrange
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
 
         String source = "{{ 1 > 1 ? 'true' : 3 > 3 ? : }}";
-        PebbleTemplate template = pebble.getTemplate(source);
 
-        Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        thrown.expect(RuntimePebbleException.class);
+        thrown.expectCause(instanceOf(ParserException.class));
+
+        //Act + Assert
+        pebble.getTemplate(source);
     }
 
     @Test
@@ -175,7 +221,7 @@ public class TernaryExpressionTest extends AbstractTest {
         PebbleTemplate template = pebble.getTemplate(source);
 
         Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        template.evaluate(writer, new HashMap<>());
         assertEquals("true", writer.toString());
     }
 
@@ -187,7 +233,7 @@ public class TernaryExpressionTest extends AbstractTest {
         PebbleTemplate template = pebble.getTemplate(source);
 
         Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        template.evaluate(writer, new HashMap<>());
         assertEquals("false", writer.toString());
     }
 
@@ -199,7 +245,7 @@ public class TernaryExpressionTest extends AbstractTest {
         PebbleTemplate template = pebble.getTemplate(source);
 
         Writer writer = new StringWriter();
-        template.evaluate(writer, new HashMap<String, Object>());
+        template.evaluate(writer, new HashMap<>());
         assertEquals("c", writer.toString());
     }
 
@@ -209,7 +255,7 @@ public class TernaryExpressionTest extends AbstractTest {
 
         String source = "{{ ('a' == 'b' ? 2 + 2 : (val - 2 is not even ? true : false) ) ? (min(otherVal,-1) | abs <  3 / 3 - 1 ? false : ['yay!'] contains 'yay!' ) : ('?' is not empty ? ''~'?' : 0) }}";
         PebbleTemplate template = pebble.getTemplate(source);
-        Map<String, Object> params = new HashMap<String, Object>();
+        Map<String, Object> params = new HashMap<>();
         params.put("val", 3);
         params.put("otherVal", 100);
         Writer writer = new StringWriter();
@@ -223,7 +269,7 @@ public class TernaryExpressionTest extends AbstractTest {
 
         String source = "{{ 'a' == 'b' ? 2 + 2 : val - 2 is not even ? true : false ? min(otherVal,-1) | abs <  3 / 3 - 1 ? false : ['yay!'] contains 'yay!' : '?' is not empty ? ''~'?' : 0 }}";
         PebbleTemplate template = pebble.getTemplate(source);
-        Map<String, Object> params = new HashMap<String, Object>();
+        Map<String, Object> params = new HashMap<>();
         params.put("val", 3);
         params.put("otherVal", 100);
         Writer writer = new StringWriter();
diff --git a/src/test/java/com/mitchellbosecke/pebble/TestParallelParsing.java b/src/test/java/com/mitchellbosecke/pebble/TestParallelParsing.java
index 7b0c7eb8..9f637c20 100644
--- a/src/test/java/com/mitchellbosecke/pebble/TestParallelParsing.java
+++ b/src/test/java/com/mitchellbosecke/pebble/TestParallelParsing.java
@@ -8,7 +8,7 @@ import com.mitchellbosecke.pebble.lexer.Token;
 import com.mitchellbosecke.pebble.lexer.TokenStream;
 import com.mitchellbosecke.pebble.node.RenderableNode;
 import com.mitchellbosecke.pebble.parser.Parser;
-import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
 import com.mitchellbosecke.pebble.template.PebbleTemplate;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 import com.mitchellbosecke.pebble.tokenParser.AbstractTokenParser;
@@ -147,7 +147,7 @@ public class TestParallelParsing extends AbstractTest {
                 }
 
                 @Override
-                public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context)
+                public void render(PebbleTemplateImpl self, Writer writer, EvaluationContext context)
                         throws PebbleException, IOException {
                     // Do nothing.
                 }