make_result and code cleaning
diff --git a/include/inja/parser.hpp b/include/inja/parser.hpp
index 410f5db..dbf8846 100644
--- a/include/inja/parser.hpp
+++ b/include/inja/parser.hpp
@@ -5,7 +5,6 @@
 #include <stack>
 #include <string>
 #include <utility>
-#include <queue>
 #include <vector>
 
 #include "config.hpp"
diff --git a/include/inja/renderer.hpp b/include/inja/renderer.hpp
index 4e8f803..2e369c4 100644
--- a/include/inja/renderer.hpp
+++ b/include/inja/renderer.hpp
@@ -22,16 +22,16 @@
   using Op = FunctionStorage::Operation;
 
   const RenderConfig config;
-  const TemplateStorage &template_storage;
-  const FunctionStorage &function_storage;
+  const TemplateStorage& template_storage;
+  const FunctionStorage& function_storage;
 
-  const Template *current_template;
+  const Template* current_template;
   size_t current_level {0};
   std::vector<const Template*> template_stack;
   std::vector<const BlockStatementNode*> block_statement_stack;
 
-  const json *data_input;
-  std::ostream *output_stream;
+  const json* data_input;
+  std::ostream* output_stream;
 
   json additional_data;
   json* current_loop_data = &additional_data["loop"];
@@ -42,7 +42,7 @@
 
   bool break_rendering {false};
 
-  bool truthy(const json* data) const {
+  static bool truthy(const json* data) {
     if (data->is_boolean()) {
       return data->get<bool>();
     } else if (data->is_number()) {
@@ -93,11 +93,17 @@
     return std::make_shared<json>(*result);
   }
 
-  void throw_renderer_error(const std::string &message, const AstNode& node) {
+  void throw_renderer_error(const std::string& message, const AstNode& node) {
     SourceLocation loc = get_source_location(current_template->content, node.pos);
     INJA_THROW(RenderError(message, loc));
   }
 
+  void make_result(const json&& result) {
+    auto result_ptr = std::make_shared<json>(result);
+    data_tmp_stack.push_back(result_ptr);
+    data_eval_stack.push(result_ptr.get());
+  }
+
   template<size_t N, size_t N_start = 0, bool throw_not_found=true>
   std::array<const json*, N> get_arguments(const FunctionNode& node) {
     if (node.arguments.size() < N_start + N) {
@@ -201,130 +207,91 @@
   }
 
   void visit(const FunctionNode& node) {
-    std::shared_ptr<json> result_ptr;
-
     switch (node.operation) {
     case Op::Not: {
       const auto args = get_arguments<1>(node);
-      result_ptr = std::make_shared<json>(!truthy(args[0]));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(!truthy(args[0]));
     } break;
     case Op::And: {
-      result_ptr = std::make_shared<json>(truthy(get_arguments<1, 0>(node)[0]) && truthy(get_arguments<1, 1>(node)[0]));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(truthy(get_arguments<1, 0>(node)[0]) && truthy(get_arguments<1, 1>(node)[0]));
     } break;
     case Op::Or: {
-      result_ptr = std::make_shared<json>(truthy(get_arguments<1, 0>(node)[0]) || truthy(get_arguments<1, 1>(node)[0]));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(truthy(get_arguments<1, 0>(node)[0]) || truthy(get_arguments<1, 1>(node)[0]));
     } break;
     case Op::In: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(std::find(args[1]->begin(), args[1]->end(), *args[0]) != args[1]->end());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(std::find(args[1]->begin(), args[1]->end(), *args[0]) != args[1]->end());
     } break;
     case Op::Equal: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(*args[0] == *args[1]);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(*args[0] == *args[1]);
     } break;
     case Op::NotEqual: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(*args[0] != *args[1]);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(*args[0] != *args[1]);
     } break;
     case Op::Greater: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(*args[0] > *args[1]);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(*args[0] > *args[1]);
     } break;
     case Op::GreaterEqual: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(*args[0] >= *args[1]);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(*args[0] >= *args[1]);
     } break;
     case Op::Less: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(*args[0] < *args[1]);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(*args[0] < *args[1]);
     } break;
     case Op::LessEqual: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(*args[0] <= *args[1]);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(*args[0] <= *args[1]);
     } break;
     case Op::Add: {
       const auto args = get_arguments<2>(node);
       if (args[0]->is_string() && args[1]->is_string()) {
-        result_ptr = std::make_shared<json>(args[0]->get_ref<const std::string&>() + args[1]->get_ref<const std::string&>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get_ref<const std::string&>() + args[1]->get_ref<const std::string&>());
       } else if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
-        result_ptr = std::make_shared<json>(args[0]->get<int>() + args[1]->get<int>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get<int>() + args[1]->get<int>());
       } else {
-        result_ptr = std::make_shared<json>(args[0]->get<double>() + args[1]->get<double>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get<double>() + args[1]->get<double>());
       }
-      data_eval_stack.push(result_ptr.get());
     } break;
     case Op::Subtract: {
       const auto args = get_arguments<2>(node);
       if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
-        result_ptr = std::make_shared<json>(args[0]->get<int>() - args[1]->get<int>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get<int>() - args[1]->get<int>());
       } else {
-        result_ptr = std::make_shared<json>(args[0]->get<double>() - args[1]->get<double>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get<double>() - args[1]->get<double>());
       }
-      data_eval_stack.push(result_ptr.get());
     } break;
     case Op::Multiplication: {
       const auto args = get_arguments<2>(node);
       if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
-        result_ptr = std::make_shared<json>(args[0]->get<int>() * args[1]->get<int>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get<int>() * args[1]->get<int>());
       } else {
-        result_ptr = std::make_shared<json>(args[0]->get<double>() * args[1]->get<double>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get<double>() * args[1]->get<double>());
       }
-      data_eval_stack.push(result_ptr.get());
     } break;
     case Op::Division: {
       const auto args = get_arguments<2>(node);
       if (args[1]->get<double>() == 0) {
         throw_renderer_error("division by zero", node);
       }
-      result_ptr = std::make_shared<json>(args[0]->get<double>() / args[1]->get<double>());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(args[0]->get<double>() / args[1]->get<double>());
     } break;
     case Op::Power: {
       const auto args = get_arguments<2>(node);
       if (args[0]->is_number_integer() && args[1]->get<int>() >= 0) {
         int result = static_cast<int>(std::pow(args[0]->get<int>(), args[1]->get<int>()));
-        result_ptr = std::make_shared<json>(std::move(result));
-        data_tmp_stack.push_back(result_ptr);
+        make_result(result);
       } else {
         double result = std::pow(args[0]->get<double>(), args[1]->get<int>());
-        result_ptr = std::make_shared<json>(std::move(result));
-        data_tmp_stack.push_back(result_ptr);
+        make_result(result);
       }
-      data_eval_stack.push(result_ptr.get());
     } break;
     case Op::Modulo: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(args[0]->get<int>() % args[1]->get<int>());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(args[0]->get<int>() % args[1]->get<int>());
     } break;
     case Op::AtId: {
       const auto container = get_arguments<1, 0, false>(node)[0];
@@ -352,41 +319,29 @@
     case Op::DivisibleBy: {
       const auto args = get_arguments<2>(node);
       const int divisor = args[1]->get<int>();
-      result_ptr = std::make_shared<json>((divisor != 0) && (args[0]->get<int>() % divisor == 0));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result((divisor != 0) && (args[0]->get<int>() % divisor == 0));
     } break;
     case Op::Even: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->get<int>() % 2 == 0);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->get<int>() % 2 == 0);
     } break;
     case Op::Exists: {
       auto &&name = get_arguments<1>(node)[0]->get_ref<const std::string &>();
-      result_ptr = std::make_shared<json>(data_input->contains(json::json_pointer(DataNode::convert_dot_to_ptr(name))));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(data_input->contains(json::json_pointer(DataNode::convert_dot_to_ptr(name))));
     } break;
     case Op::ExistsInObject: {
       const auto args = get_arguments<2>(node);
       auto &&name = args[1]->get_ref<const std::string &>();
-      result_ptr = std::make_shared<json>(args[0]->find(name) != args[0]->end());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(args[0]->find(name) != args[0]->end());
     } break;
     case Op::First: {
       const auto result = &get_arguments<1>(node)[0]->front();
       data_eval_stack.push(result);
     } break;
     case Op::Float: {
-      result_ptr = std::make_shared<json>(std::stod(get_arguments<1>(node)[0]->get_ref<const std::string &>()));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(std::stod(get_arguments<1>(node)[0]->get_ref<const std::string &>()));
     } break;
     case Op::Int: {
-      result_ptr = std::make_shared<json>(std::stoi(get_arguments<1>(node)[0]->get_ref<const std::string &>()));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(std::stoi(get_arguments<1>(node)[0]->get_ref<const std::string &>()));
     } break;
     case Op::Last: {
       const auto result = &get_arguments<1>(node)[0]->back();
@@ -395,19 +350,15 @@
     case Op::Length: {
       const auto val = get_arguments<1>(node)[0];
       if (val->is_string()) {
-        result_ptr = std::make_shared<json>(val->get_ref<const std::string &>().length());
+        make_result(val->get_ref<const std::string &>().length());
       } else {
-        result_ptr = std::make_shared<json>(val->size());
+        make_result(val->size());
       }
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
     } break;
     case Op::Lower: {
       std::string result = get_arguments<1>(node)[0]->get<std::string>();
       std::transform(result.begin(), result.end(), result.begin(), ::tolower);
-      result_ptr = std::make_shared<json>(std::move(result));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(std::move(result));
     } break;
     case Op::Max: {
       const auto args = get_arguments<1>(node);
@@ -420,31 +371,25 @@
       data_eval_stack.push(&(*result));
     } break;
     case Op::Odd: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->get<int>() % 2 != 0);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->get<int>() % 2 != 0);
     } break;
     case Op::Range: {
       std::vector<int> result(get_arguments<1>(node)[0]->get<int>());
       std::iota(result.begin(), result.end(), 0);
-      result_ptr = std::make_shared<json>(std::move(result));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(std::move(result));
     } break;
     case Op::Round: {
       const auto args = get_arguments<2>(node);
       const int precision = args[1]->get<int>();
       const double result = std::round(args[0]->get<double>() * std::pow(10.0, precision)) / std::pow(10.0, precision);
-      if(0==precision){
-        result_ptr = std::make_shared<json>(int(result));
-      }else{
-        result_ptr = std::make_shared<json>(std::move(result));
+      if (precision == 0) {
+        make_result(int(result));
+      } else {
+        make_result(result);
       }
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
     } break;
     case Op::Sort: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->get<std::vector<json>>());
+      auto result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->get<std::vector<json>>());
       std::sort(result_ptr->begin(), result_ptr->end());
       data_tmp_stack.push_back(result_ptr);
       data_eval_stack.push(result_ptr.get());
@@ -452,50 +397,32 @@
     case Op::Upper: {
       std::string result = get_arguments<1>(node)[0]->get<std::string>();
       std::transform(result.begin(), result.end(), result.begin(), ::toupper);
-      result_ptr = std::make_shared<json>(std::move(result));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(std::move(result));
     } break;
     case Op::IsBoolean: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_boolean());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_boolean());
     } break;
     case Op::IsNumber: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_number());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_number());
     } break;
     case Op::IsInteger: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_number_integer());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_number_integer());
     } break;
     case Op::IsFloat: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_number_float());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_number_float());
     } break;
     case Op::IsObject: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_object());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_object());
     } break;
     case Op::IsArray: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_array());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_array());
     } break;
     case Op::IsString: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_string());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_string());
     } break;
     case Op::Callback: {
       auto args = get_argument_vector(node);
-      result_ptr = std::make_shared<json>(node.callback(args));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(node.callback(args));
     } break;
     case Op::Super: {
       const auto args = get_argument_vector(node);
@@ -512,8 +439,8 @@
       }
 
       const auto current_block_statement = block_statement_stack.back();
-      const Template *new_template = template_stack.at(level);
-      const Template *old_template = current_template;
+      const Template* new_template = template_stack.at(level);
+      const Template* old_template = current_template;
       const auto block_it = new_template->block_storage.find(current_block_statement->name);
       if (block_it != new_template->block_storage.end()) {
         current_template = new_template;
@@ -524,9 +451,7 @@
       } else {
         throw_renderer_error("could not find block with name '" + current_block_statement->name + "'", node);
       }
-      result_ptr = std::make_shared<json>(nullptr);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(nullptr);
     } break;
     case Op::Join: {
       const auto args = get_arguments<2>(node);
@@ -542,9 +467,7 @@
         }
         sep = separator;
       }
-      result_ptr = std::make_shared<json>(os.str());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(os.str());
     } break;
     case Op::ParenLeft:
     case Op::ParenRight:
@@ -691,10 +614,10 @@
   }
 
 public:
-  Renderer(const RenderConfig& config, const TemplateStorage &template_storage, const FunctionStorage &function_storage)
+  Renderer(const RenderConfig& config, const TemplateStorage& template_storage, const FunctionStorage& function_storage)
       : config(config), template_storage(template_storage), function_storage(function_storage) { }
 
-  void render_to(std::ostream &os, const Template &tmpl, const json &data, json *loop_data = nullptr) {
+  void render_to(std::ostream& os, const Template& tmpl, const json& data, json* loop_data = nullptr) {
     output_stream = &os;
     current_template = &tmpl;
     data_input = &data;
diff --git a/single_include/inja/inja.hpp b/single_include/inja/inja.hpp
index 775a719..d8fb413 100644
--- a/single_include/inja/inja.hpp
+++ b/single_include/inja/inja.hpp
@@ -904,7 +904,6 @@
 #include <stack>
 #include <string>
 #include <utility>
-#include <queue>
 #include <vector>
 
 // #include "config.hpp"
@@ -2119,16 +2118,16 @@
   using Op = FunctionStorage::Operation;
 
   const RenderConfig config;
-  const TemplateStorage &template_storage;
-  const FunctionStorage &function_storage;
+  const TemplateStorage& template_storage;
+  const FunctionStorage& function_storage;
 
-  const Template *current_template;
+  const Template* current_template;
   size_t current_level {0};
   std::vector<const Template*> template_stack;
   std::vector<const BlockStatementNode*> block_statement_stack;
 
-  const json *data_input;
-  std::ostream *output_stream;
+  const json* data_input;
+  std::ostream* output_stream;
 
   json additional_data;
   json* current_loop_data = &additional_data["loop"];
@@ -2139,7 +2138,7 @@
 
   bool break_rendering {false};
 
-  bool truthy(const json* data) const {
+  static bool truthy(const json* data) {
     if (data->is_boolean()) {
       return data->get<bool>();
     } else if (data->is_number()) {
@@ -2190,11 +2189,17 @@
     return std::make_shared<json>(*result);
   }
 
-  void throw_renderer_error(const std::string &message, const AstNode& node) {
+  void throw_renderer_error(const std::string& message, const AstNode& node) {
     SourceLocation loc = get_source_location(current_template->content, node.pos);
     INJA_THROW(RenderError(message, loc));
   }
 
+  void make_result(const json&& result) {
+    auto result_ptr = std::make_shared<json>(result);
+    data_tmp_stack.push_back(result_ptr);
+    data_eval_stack.push(result_ptr.get());
+  }
+
   template<size_t N, size_t N_start = 0, bool throw_not_found=true>
   std::array<const json*, N> get_arguments(const FunctionNode& node) {
     if (node.arguments.size() < N_start + N) {
@@ -2298,130 +2303,91 @@
   }
 
   void visit(const FunctionNode& node) {
-    std::shared_ptr<json> result_ptr;
-
     switch (node.operation) {
     case Op::Not: {
       const auto args = get_arguments<1>(node);
-      result_ptr = std::make_shared<json>(!truthy(args[0]));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(!truthy(args[0]));
     } break;
     case Op::And: {
-      result_ptr = std::make_shared<json>(truthy(get_arguments<1, 0>(node)[0]) && truthy(get_arguments<1, 1>(node)[0]));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(truthy(get_arguments<1, 0>(node)[0]) && truthy(get_arguments<1, 1>(node)[0]));
     } break;
     case Op::Or: {
-      result_ptr = std::make_shared<json>(truthy(get_arguments<1, 0>(node)[0]) || truthy(get_arguments<1, 1>(node)[0]));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(truthy(get_arguments<1, 0>(node)[0]) || truthy(get_arguments<1, 1>(node)[0]));
     } break;
     case Op::In: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(std::find(args[1]->begin(), args[1]->end(), *args[0]) != args[1]->end());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(std::find(args[1]->begin(), args[1]->end(), *args[0]) != args[1]->end());
     } break;
     case Op::Equal: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(*args[0] == *args[1]);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(*args[0] == *args[1]);
     } break;
     case Op::NotEqual: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(*args[0] != *args[1]);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(*args[0] != *args[1]);
     } break;
     case Op::Greater: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(*args[0] > *args[1]);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(*args[0] > *args[1]);
     } break;
     case Op::GreaterEqual: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(*args[0] >= *args[1]);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(*args[0] >= *args[1]);
     } break;
     case Op::Less: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(*args[0] < *args[1]);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(*args[0] < *args[1]);
     } break;
     case Op::LessEqual: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(*args[0] <= *args[1]);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(*args[0] <= *args[1]);
     } break;
     case Op::Add: {
       const auto args = get_arguments<2>(node);
       if (args[0]->is_string() && args[1]->is_string()) {
-        result_ptr = std::make_shared<json>(args[0]->get_ref<const std::string&>() + args[1]->get_ref<const std::string&>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get_ref<const std::string&>() + args[1]->get_ref<const std::string&>());
       } else if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
-        result_ptr = std::make_shared<json>(args[0]->get<int>() + args[1]->get<int>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get<int>() + args[1]->get<int>());
       } else {
-        result_ptr = std::make_shared<json>(args[0]->get<double>() + args[1]->get<double>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get<double>() + args[1]->get<double>());
       }
-      data_eval_stack.push(result_ptr.get());
     } break;
     case Op::Subtract: {
       const auto args = get_arguments<2>(node);
       if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
-        result_ptr = std::make_shared<json>(args[0]->get<int>() - args[1]->get<int>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get<int>() - args[1]->get<int>());
       } else {
-        result_ptr = std::make_shared<json>(args[0]->get<double>() - args[1]->get<double>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get<double>() - args[1]->get<double>());
       }
-      data_eval_stack.push(result_ptr.get());
     } break;
     case Op::Multiplication: {
       const auto args = get_arguments<2>(node);
       if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
-        result_ptr = std::make_shared<json>(args[0]->get<int>() * args[1]->get<int>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get<int>() * args[1]->get<int>());
       } else {
-        result_ptr = std::make_shared<json>(args[0]->get<double>() * args[1]->get<double>());
-        data_tmp_stack.push_back(result_ptr);
+        make_result(args[0]->get<double>() * args[1]->get<double>());
       }
-      data_eval_stack.push(result_ptr.get());
     } break;
     case Op::Division: {
       const auto args = get_arguments<2>(node);
       if (args[1]->get<double>() == 0) {
         throw_renderer_error("division by zero", node);
       }
-      result_ptr = std::make_shared<json>(args[0]->get<double>() / args[1]->get<double>());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(args[0]->get<double>() / args[1]->get<double>());
     } break;
     case Op::Power: {
       const auto args = get_arguments<2>(node);
       if (args[0]->is_number_integer() && args[1]->get<int>() >= 0) {
         int result = static_cast<int>(std::pow(args[0]->get<int>(), args[1]->get<int>()));
-        result_ptr = std::make_shared<json>(std::move(result));
-        data_tmp_stack.push_back(result_ptr);
+        make_result(result);
       } else {
         double result = std::pow(args[0]->get<double>(), args[1]->get<int>());
-        result_ptr = std::make_shared<json>(std::move(result));
-        data_tmp_stack.push_back(result_ptr);
+        make_result(result);
       }
-      data_eval_stack.push(result_ptr.get());
     } break;
     case Op::Modulo: {
       const auto args = get_arguments<2>(node);
-      result_ptr = std::make_shared<json>(args[0]->get<int>() % args[1]->get<int>());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(args[0]->get<int>() % args[1]->get<int>());
     } break;
     case Op::AtId: {
       const auto container = get_arguments<1, 0, false>(node)[0];
@@ -2449,41 +2415,29 @@
     case Op::DivisibleBy: {
       const auto args = get_arguments<2>(node);
       const int divisor = args[1]->get<int>();
-      result_ptr = std::make_shared<json>((divisor != 0) && (args[0]->get<int>() % divisor == 0));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result((divisor != 0) && (args[0]->get<int>() % divisor == 0));
     } break;
     case Op::Even: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->get<int>() % 2 == 0);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->get<int>() % 2 == 0);
     } break;
     case Op::Exists: {
       auto &&name = get_arguments<1>(node)[0]->get_ref<const std::string &>();
-      result_ptr = std::make_shared<json>(data_input->contains(json::json_pointer(DataNode::convert_dot_to_ptr(name))));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(data_input->contains(json::json_pointer(DataNode::convert_dot_to_ptr(name))));
     } break;
     case Op::ExistsInObject: {
       const auto args = get_arguments<2>(node);
       auto &&name = args[1]->get_ref<const std::string &>();
-      result_ptr = std::make_shared<json>(args[0]->find(name) != args[0]->end());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(args[0]->find(name) != args[0]->end());
     } break;
     case Op::First: {
       const auto result = &get_arguments<1>(node)[0]->front();
       data_eval_stack.push(result);
     } break;
     case Op::Float: {
-      result_ptr = std::make_shared<json>(std::stod(get_arguments<1>(node)[0]->get_ref<const std::string &>()));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(std::stod(get_arguments<1>(node)[0]->get_ref<const std::string &>()));
     } break;
     case Op::Int: {
-      result_ptr = std::make_shared<json>(std::stoi(get_arguments<1>(node)[0]->get_ref<const std::string &>()));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(std::stoi(get_arguments<1>(node)[0]->get_ref<const std::string &>()));
     } break;
     case Op::Last: {
       const auto result = &get_arguments<1>(node)[0]->back();
@@ -2492,19 +2446,15 @@
     case Op::Length: {
       const auto val = get_arguments<1>(node)[0];
       if (val->is_string()) {
-        result_ptr = std::make_shared<json>(val->get_ref<const std::string &>().length());
+        make_result(val->get_ref<const std::string &>().length());
       } else {
-        result_ptr = std::make_shared<json>(val->size());
+        make_result(val->size());
       }
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
     } break;
     case Op::Lower: {
       std::string result = get_arguments<1>(node)[0]->get<std::string>();
       std::transform(result.begin(), result.end(), result.begin(), ::tolower);
-      result_ptr = std::make_shared<json>(std::move(result));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(std::move(result));
     } break;
     case Op::Max: {
       const auto args = get_arguments<1>(node);
@@ -2517,31 +2467,25 @@
       data_eval_stack.push(&(*result));
     } break;
     case Op::Odd: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->get<int>() % 2 != 0);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->get<int>() % 2 != 0);
     } break;
     case Op::Range: {
       std::vector<int> result(get_arguments<1>(node)[0]->get<int>());
       std::iota(result.begin(), result.end(), 0);
-      result_ptr = std::make_shared<json>(std::move(result));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(std::move(result));
     } break;
     case Op::Round: {
       const auto args = get_arguments<2>(node);
       const int precision = args[1]->get<int>();
       const double result = std::round(args[0]->get<double>() * std::pow(10.0, precision)) / std::pow(10.0, precision);
-      if(0==precision){
-        result_ptr = std::make_shared<json>(int(result));
-      }else{
-        result_ptr = std::make_shared<json>(std::move(result));
+      if (precision == 0) {
+        make_result(int(result));
+      } else {
+        make_result(result);
       }
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
     } break;
     case Op::Sort: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->get<std::vector<json>>());
+      auto result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->get<std::vector<json>>());
       std::sort(result_ptr->begin(), result_ptr->end());
       data_tmp_stack.push_back(result_ptr);
       data_eval_stack.push(result_ptr.get());
@@ -2549,50 +2493,32 @@
     case Op::Upper: {
       std::string result = get_arguments<1>(node)[0]->get<std::string>();
       std::transform(result.begin(), result.end(), result.begin(), ::toupper);
-      result_ptr = std::make_shared<json>(std::move(result));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(std::move(result));
     } break;
     case Op::IsBoolean: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_boolean());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_boolean());
     } break;
     case Op::IsNumber: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_number());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_number());
     } break;
     case Op::IsInteger: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_number_integer());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_number_integer());
     } break;
     case Op::IsFloat: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_number_float());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_number_float());
     } break;
     case Op::IsObject: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_object());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_object());
     } break;
     case Op::IsArray: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_array());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_array());
     } break;
     case Op::IsString: {
-      result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_string());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(get_arguments<1>(node)[0]->is_string());
     } break;
     case Op::Callback: {
       auto args = get_argument_vector(node);
-      result_ptr = std::make_shared<json>(node.callback(args));
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(node.callback(args));
     } break;
     case Op::Super: {
       const auto args = get_argument_vector(node);
@@ -2609,8 +2535,8 @@
       }
 
       const auto current_block_statement = block_statement_stack.back();
-      const Template *new_template = template_stack.at(level);
-      const Template *old_template = current_template;
+      const Template* new_template = template_stack.at(level);
+      const Template* old_template = current_template;
       const auto block_it = new_template->block_storage.find(current_block_statement->name);
       if (block_it != new_template->block_storage.end()) {
         current_template = new_template;
@@ -2621,9 +2547,7 @@
       } else {
         throw_renderer_error("could not find block with name '" + current_block_statement->name + "'", node);
       }
-      result_ptr = std::make_shared<json>(nullptr);
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(nullptr);
     } break;
     case Op::Join: {
       const auto args = get_arguments<2>(node);
@@ -2639,9 +2563,7 @@
         }
         sep = separator;
       }
-      result_ptr = std::make_shared<json>(os.str());
-      data_tmp_stack.push_back(result_ptr);
-      data_eval_stack.push(result_ptr.get());
+      make_result(os.str());
     } break;
     case Op::ParenLeft:
     case Op::ParenRight:
@@ -2788,10 +2710,10 @@
   }
 
 public:
-  Renderer(const RenderConfig& config, const TemplateStorage &template_storage, const FunctionStorage &function_storage)
+  Renderer(const RenderConfig& config, const TemplateStorage& template_storage, const FunctionStorage& function_storage)
       : config(config), template_storage(template_storage), function_storage(function_storage) { }
 
-  void render_to(std::ostream &os, const Template &tmpl, const json &data, json *loop_data = nullptr) {
+  void render_to(std::ostream& os, const Template& tmpl, const json& data, json* loop_data = nullptr) {
     output_stream = &os;
     current_template = &tmpl;
     data_input = &data;