From 7c7975df1484aa7354dd95c71d4ea75aab5c2e27 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Tue, 30 May 2023 08:17:30 +0200
Subject: [PATCH] Add ASTBacktrace to improve error management

This allow to show the executed pgs line on failure
---
 src/language/PugsParser.cpp                   | 11 +--
 src/language/ast/ASTBacktrace.cpp             | 55 ++++++++++++++
 src/language/ast/ASTBacktrace.hpp             | 54 +++++++++++++
 src/language/ast/ASTNode.cpp                  |  3 +
 src/language/ast/ASTNode.hpp                  | 41 +++++++++-
 src/language/ast/CMakeLists.txt               |  2 +
 .../ASTNodeExpressionListProcessor.hpp        |  6 ++
 .../node_processor/ASTNodeListProcessor.hpp   |  6 ++
 .../node_processor/AffectationProcessor.hpp   | 48 ++++++++++++
 .../ArraySubscriptProcessor.hpp               |  6 ++
 .../BinaryExpressionProcessor.hpp             | 24 ++++++
 .../node_processor/BreakProcessor.hpp         |  6 ++
 .../BuiltinFunctionProcessor.hpp              | 12 +++
 .../ConcatExpressionProcessor.hpp             |  6 ++
 .../node_processor/ContinueProcessor.hpp      |  6 ++
 .../node_processor/DoWhileProcessor.hpp       |  6 ++
 src/language/node_processor/FakeProcessor.hpp |  6 ++
 src/language/node_processor/ForProcessor.hpp  |  6 ++
 .../node_processor/FunctionProcessor.hpp      | 12 +++
 .../node_processor/INodeProcessor.hpp         | 31 ++++++++
 src/language/node_processor/IfProcessor.hpp   |  6 ++
 .../IncDecExpressionProcessor.hpp             |  6 ++
 .../InnerListToVectorProcessor.hpp            |  6 ++
 .../node_processor/LocalNameProcessor.hpp     |  6 ++
 src/language/node_processor/NameProcessor.hpp |  6 ++
 .../TinyMatrixExpressionProcessor.hpp         |  6 ++
 .../TinyVectorExpressionProcessor.hpp         |  6 ++
 .../UnaryExpressionProcessor.hpp              | 12 +++
 .../node_processor/ValueProcessor.hpp         |  6 ++
 .../node_processor/WhileProcessor.hpp         |  6 ++
 src/utils/SignalManager.cpp                   | 75 +++++++++++--------
 tests/test_ASTModulesImporter.cpp             |  3 +
 tests/test_ASTNode.cpp                        |  5 ++
 tests/test_ASTNodeListProcessor.cpp           |  3 +
 tests/test_AffectationProcessor.cpp           |  7 ++
 tests/test_AffectationToStringProcessor.cpp   |  3 +
 tests/test_AffectationToTupleProcessor.cpp    |  5 ++
 tests/test_ArraySubscriptProcessor.cpp        |  5 ++
 ...t_BinaryExpressionProcessor_arithmetic.cpp |  4 +
 .../test_BinaryExpressionProcessor_shift.cpp  |  2 +
 .../test_BinaryExpressionProcessor_utils.hpp  |  3 +
 tests/test_BuiltinFunctionProcessor.cpp       |  5 ++
 tests/test_DiscreteFunctionIntegrator.cpp     |  5 ++
 .../test_DiscreteFunctionIntegratorByZone.cpp |  5 ++
 tests/test_DiscreteFunctionInterpoler.cpp     |  5 ++
 .../test_DiscreteFunctionInterpolerByZone.cpp |  5 ++
 .../test_DiscreteFunctionVectorIntegrator.cpp |  5 ++
 ...DiscreteFunctionVectorIntegratorByZone.cpp |  5 ++
 .../test_DiscreteFunctionVectorInterpoler.cpp |  5 ++
 ...DiscreteFunctionVectorInterpolerByZone.cpp |  5 ++
 tests/test_InterpolateItemArray.cpp           |  5 ++
 tests/test_InterpolateItemValue.cpp           |  5 ++
 ...est_ItemArrayVariantFunctionInterpoler.cpp |  5 ++
 ...est_ItemValueVariantFunctionInterpoler.cpp |  5 ++
 54 files changed, 555 insertions(+), 38 deletions(-)
 create mode 100644 src/language/ast/ASTBacktrace.cpp
 create mode 100644 src/language/ast/ASTBacktrace.hpp
 create mode 100644 src/language/ast/ASTNode.cpp

diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp
index 9f528bfce..bf573ac54 100644
--- a/src/language/PugsParser.cpp
+++ b/src/language/PugsParser.cpp
@@ -1,6 +1,7 @@
 #include <language/PugsParser.hpp>
 
 #include <language/PEGGrammar.hpp>
+#include <language/ast/ASTBacktrace.hpp>
 #include <language/ast/ASTBuilder.hpp>
 #include <language/ast/ASTModulesImporter.hpp>
 #include <language/ast/ASTNode.hpp>
@@ -31,6 +32,7 @@
 
 #include <fstream>
 #include <iostream>
+#include <memory>
 #include <sstream>
 #include <unordered_map>
 #include <variant>
@@ -53,8 +55,8 @@ parser(const std::string& filename)
 
   auto parse_and_execute = [](auto& input) {
     OperatorRepository::create();
-
-    std::unique_ptr<ASTNode> root_node = ASTBuilder::build(input);
+    ASTBacktrace::create(input);
+    std::unique_ptr<ASTNode> root_node = ASTBuilder::build(*input);
 
     ASTModulesImporter module_importer{*root_node};
     ASTNodeTypeCleaner<language::import_instruction>{*root_node};
@@ -94,8 +96,8 @@ parser(const std::string& filename)
     OperatorRepository::destroy();
   };
 
+  auto input = std::make_shared<TAO_PEGTL_NAMESPACE::file_input<>>(filename);
   if (not SignalManager::pauseOnError()) {
-    TAO_PEGTL_NAMESPACE::file_input input(filename);
     try {
       parse_and_execute(input);
     }
@@ -119,13 +121,12 @@ parser(const std::string& filename)
       std::cerr << rang::style::bold << p.source << ':' << p.line << ':' << p.column << ": " << rang::style::reset
                 << rang::fgB::red << "error: " << rang::fg::reset << rang::style::bold << message << rang::style::reset
                 << '\n'
-                << input.line_at(p) << '\n'
+                << input->line_at(p) << '\n'
                 << std::string(p.column - 1, ' ') << rang::fgB::yellow << '^' << rang::fg::reset << '\n';
       finalize();
       std::exit(1);
     }
   } else {
-    TAO_PEGTL_NAMESPACE::file_input input(filename);
     parse_and_execute(input);
   }
 }
diff --git a/src/language/ast/ASTBacktrace.cpp b/src/language/ast/ASTBacktrace.cpp
new file mode 100644
index 000000000..90f84bf13
--- /dev/null
+++ b/src/language/ast/ASTBacktrace.cpp
@@ -0,0 +1,55 @@
+#include <language/ast/ASTBacktrace.hpp>
+
+#include <language/ast/ASTNode.hpp>
+
+ASTBacktrace* ASTBacktrace::m_instance = nullptr;
+
+ASTBacktrace::ASTBacktrace(const std::shared_ptr<TAO_PEGTL_NAMESPACE::file_input<>>& file_input)
+  : m_file_input(file_input)
+{}
+
+std::string
+ASTBacktrace::stackInfo() const
+{
+  auto& stack = ASTBacktrace::getInstance().m_stack;
+  std::ostringstream error_msg;
+
+  auto p = stack[stack.size() - 1]->begin();
+  error_msg << rang::style::bold << p.source << ':' << p.line << ':' << p.column << ": " << rang::style::reset
+            << rang::fgB::red << "error: " << rang::fg::reset << rang::style::bold << "emitted while executing"
+            << rang::style::reset << '\n';
+
+  if (m_file_input.use_count() > 0) {
+    error_msg << m_file_input->line_at(p) << '\n'
+              << std::string(p.column - 1, ' ') << rang::fgB::yellow << '^' << rang::fg::reset << '\n';
+  }
+
+  return error_msg.str();
+}
+
+void
+ASTBacktrace::create()
+{
+  if (m_instance == nullptr) {
+    m_instance = new ASTBacktrace();
+  } else {
+    throw UnexpectedError("ASTBackTrace was already created!");
+  }
+}
+
+void
+ASTBacktrace::create(const std::shared_ptr<TAO_PEGTL_NAMESPACE::file_input<>>& file_input)
+{
+  if (m_instance == nullptr) {
+    m_instance = new ASTBacktrace(file_input);
+  } else {
+    throw UnexpectedError("ASTBackTrace was already created!");
+  }
+}
+
+void
+ASTBacktrace::destroy()
+{
+  delete m_instance;
+  m_instance = nullptr;
+}
diff --git a/src/language/ast/ASTBacktrace.hpp b/src/language/ast/ASTBacktrace.hpp
new file mode 100644
index 000000000..4dfc3c2ba
--- /dev/null
+++ b/src/language/ast/ASTBacktrace.hpp
@@ -0,0 +1,54 @@
+#ifndef AST_BACTRACE_HPP
+#define AST_BACTRACE_HPP
+
+#include <utils/PugsAssert.hpp>
+
+#include <pegtl/file_input.hpp>
+#include <string>
+#include <vector>
+
+class ASTNode;
+class ASTBacktrace
+{
+ private:
+  std::vector<const ASTNode*> m_stack;
+
+  std::shared_ptr<TAO_PEGTL_NAMESPACE::file_input<>> m_file_input;
+
+  static ASTBacktrace* m_instance;
+
+  ASTBacktrace() = default;
+  ASTBacktrace(const std::shared_ptr<TAO_PEGTL_NAMESPACE::file_input<>>& file_input);
+  ~ASTBacktrace() = default;
+
+ public:
+  std::string stackInfo() const;
+
+  void
+  push(const ASTNode* node)
+  {
+    m_stack.push_back(node);
+  }
+
+  void
+  pop()
+  {
+    m_stack.pop_back();
+  }
+
+  static void create();   // for unit tests only
+  static void create(const std::shared_ptr<TAO_PEGTL_NAMESPACE::file_input<>>& file_input);
+  static void destroy();
+
+  static ASTBacktrace&
+  getInstance()
+  {
+    Assert(m_instance != nullptr);
+    return *m_instance;
+  }
+
+  ASTBacktrace(const ASTBacktrace&) = delete;
+  ASTBacktrace(ASTBacktrace&&)      = delete;
+};
+
+#endif   // AST_BACTRACE_HPP
diff --git a/src/language/ast/ASTNode.cpp b/src/language/ast/ASTNode.cpp
new file mode 100644
index 000000000..cddc0b489
--- /dev/null
+++ b/src/language/ast/ASTNode.cpp
@@ -0,0 +1,3 @@
+#include <language/ast/ASTNode.hpp>
+
+bool ASTNode::m_stack_details = true;
diff --git a/src/language/ast/ASTNode.hpp b/src/language/ast/ASTNode.hpp
index f9f9ad6db..19b43a927 100644
--- a/src/language/ast/ASTNode.hpp
+++ b/src/language/ast/ASTNode.hpp
@@ -1,6 +1,7 @@
 #ifndef AST_NODE_HPP
 #define AST_NODE_HPP
 
+#include <language/ast/ASTBacktrace.hpp>
 #include <language/node_processor/ExecutionPolicy.hpp>
 #include <language/node_processor/INodeProcessor.hpp>
 #include <language/utils/ASTNodeDataType.hpp>
@@ -9,13 +10,18 @@
 #include <utils/PugsAssert.hpp>
 #include <utils/PugsMacros.hpp>
 
+#include <pegtl.hpp>
 #include <pegtl/contrib/parse_tree.hpp>
 
+inline TAO_PEGTL_NAMESPACE::file_input<>* p_file_input = nullptr;
+
 class SymbolTable;
 
 class ASTNode : public TAO_PEGTL_NAMESPACE::parse_tree::basic_node<ASTNode>
 {
  private:
+  static bool m_stack_details;
+
   PUGS_INLINE
   decltype(m_end)
   _getEnd() const
@@ -41,6 +47,18 @@ class ASTNode : public TAO_PEGTL_NAMESPACE::parse_tree::basic_node<ASTNode>
   }
 
  public:
+  static bool
+  getStackDetails()
+  {
+    return m_stack_details;
+  }
+
+  static void
+  setStackDetails(const bool stack_details)
+  {
+    m_stack_details = stack_details;
+  }
+
   std::shared_ptr<SymbolTable> m_symbol_table;
   std::unique_ptr<INodeProcessor> m_node_processor;
 
@@ -88,8 +106,29 @@ class ASTNode : public TAO_PEGTL_NAMESPACE::parse_tree::basic_node<ASTNode>
   execute(ExecutionPolicy& exec_policy)
   {
     Assert(m_node_processor, "undefined node processor");
+
     if (exec_policy.exec()) {
-      return m_node_processor->execute(exec_policy);
+      if (m_stack_details) {
+        if (m_node_processor->type() == INodeProcessor::Type::builtin_function_processor) {
+          ASTBacktrace::getInstance().push(this);
+
+          m_stack_details = false;
+          auto result     = m_node_processor->execute(exec_policy);
+          m_stack_details = true;
+
+          ASTBacktrace::getInstance().pop();
+
+          return result;
+        } else {
+          ASTBacktrace::getInstance().push(this);
+          auto result = m_node_processor->execute(exec_policy);
+          ASTBacktrace::getInstance().pop();
+
+          return result;
+        }
+      } else {
+        return m_node_processor->execute(exec_policy);
+      }
     } else {
       return {};
     }
diff --git a/src/language/ast/CMakeLists.txt b/src/language/ast/CMakeLists.txt
index a901d7c09..63e208c2b 100644
--- a/src/language/ast/CMakeLists.txt
+++ b/src/language/ast/CMakeLists.txt
@@ -1,8 +1,10 @@
 # ------------------- Source files --------------------
 
 add_library(PugsLanguageAST
+  ASTBacktrace.cpp
   ASTBuilder.cpp
   ASTModulesImporter.cpp
+  ASTNode.cpp
   ASTNodeAffectationExpressionBuilder.cpp
   ASTNodeArraySubscriptExpressionBuilder.cpp
   ASTNodeBinaryOperatorExpressionBuilder.cpp
diff --git a/src/language/node_processor/ASTNodeExpressionListProcessor.hpp b/src/language/node_processor/ASTNodeExpressionListProcessor.hpp
index 21823176e..bc6f2788f 100644
--- a/src/language/node_processor/ASTNodeExpressionListProcessor.hpp
+++ b/src/language/node_processor/ASTNodeExpressionListProcessor.hpp
@@ -76,6 +76,12 @@ class ASTNodeExpressionListProcessor final : public INodeProcessor
   }
 
  public:
+  Type
+  type() const
+  {
+    return Type::expression_list_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/ASTNodeListProcessor.hpp b/src/language/node_processor/ASTNodeListProcessor.hpp
index 5a9d8c0b8..142d33f7d 100644
--- a/src/language/node_processor/ASTNodeListProcessor.hpp
+++ b/src/language/node_processor/ASTNodeListProcessor.hpp
@@ -12,6 +12,12 @@ class ASTNodeListProcessor final : public INodeProcessor
   ASTNode& m_node;
 
  public:
+  Type
+  type() const
+  {
+    return Type::list_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp
index 8fea3a754..b18665a0f 100644
--- a/src/language/node_processor/AffectationProcessor.hpp
+++ b/src/language/node_processor/AffectationProcessor.hpp
@@ -453,6 +453,12 @@ class AffectationProcessor final : public INodeProcessor
   }
 
  public:
+  Type
+  type() const
+  {
+    return Type::affectation_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
@@ -495,6 +501,12 @@ class AffectationToTupleProcessor final : public AffectationToDataVariantProcess
   ASTNode& m_rhs_node;
 
  public:
+  Type
+  type() const
+  {
+    return Type::affectation_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
@@ -555,6 +567,12 @@ class AffectationFromTupleProcessor final : public AffectationToDataVariantProce
   ASTNode& m_rhs_node;
 
  public:
+  Type
+  type() const
+  {
+    return Type::affectation_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
@@ -682,6 +700,12 @@ class AffectationToTupleFromListProcessor final : public AffectationToDataVarian
   }
 
  public:
+  Type
+  type() const
+  {
+    return Type::affectation_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
@@ -755,6 +779,12 @@ class AffectationToTupleFromTupleProcessor final : public AffectationToDataVaria
   }
 
  public:
+  Type
+  type() const
+  {
+    return Type::affectation_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
@@ -787,6 +817,12 @@ template <typename ValueT>
 class AffectationFromZeroProcessor final : public AffectationToDataVariantProcessorBase
 {
  public:
+  Type
+  type() const
+  {
+    return Type::affectation_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy&)
   {
@@ -830,6 +866,12 @@ class ListAffectationProcessor final : public INodeProcessor
     }
   }
 
+  Type
+  type() const
+  {
+    return Type::affectation_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
@@ -938,6 +980,12 @@ class ListAffectationFromTupleProcessor final : public INodeProcessor
     }
   }
 
+  Type
+  type() const
+  {
+    return Type::affectation_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/ArraySubscriptProcessor.hpp b/src/language/node_processor/ArraySubscriptProcessor.hpp
index 43eb962b9..4166c0d98 100644
--- a/src/language/node_processor/ArraySubscriptProcessor.hpp
+++ b/src/language/node_processor/ArraySubscriptProcessor.hpp
@@ -12,6 +12,12 @@ class ArraySubscriptProcessor : public INodeProcessor
   ASTNode& m_array_subscript_expression;
 
  public:
+  Type
+  type() const
+  {
+    return Type::array_subscript_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/BinaryExpressionProcessor.hpp b/src/language/node_processor/BinaryExpressionProcessor.hpp
index a2111464c..d91f39d90 100644
--- a/src/language/node_processor/BinaryExpressionProcessor.hpp
+++ b/src/language/node_processor/BinaryExpressionProcessor.hpp
@@ -223,6 +223,12 @@ struct BinaryExpressionProcessor final : public INodeProcessor
   }
 
  public:
+  Type
+  type() const
+  {
+    return Type::binary_expression_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
@@ -253,6 +259,12 @@ struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, std::shared
   }
 
  public:
+  Type
+  type() const
+  {
+    return Type::binary_expression_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
@@ -290,6 +302,12 @@ struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, A_DataT, st
   }
 
  public:
+  Type
+  type() const
+  {
+    return Type::binary_expression_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
@@ -328,6 +346,12 @@ struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, std::shared
   }
 
  public:
+  Type
+  type() const
+  {
+    return Type::binary_expression_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/BreakProcessor.hpp b/src/language/node_processor/BreakProcessor.hpp
index 6f6d4a306..d403d89fe 100644
--- a/src/language/node_processor/BreakProcessor.hpp
+++ b/src/language/node_processor/BreakProcessor.hpp
@@ -6,6 +6,12 @@
 class BreakProcessor final : public INodeProcessor
 {
  public:
+  Type
+  type() const
+  {
+    return Type::break_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/BuiltinFunctionProcessor.hpp b/src/language/node_processor/BuiltinFunctionProcessor.hpp
index 7e5a112b4..708141d17 100644
--- a/src/language/node_processor/BuiltinFunctionProcessor.hpp
+++ b/src/language/node_processor/BuiltinFunctionProcessor.hpp
@@ -15,6 +15,12 @@ class BuiltinFunctionExpressionProcessor final : public INodeProcessor
   std::shared_ptr<IBuiltinFunctionEmbedder> m_embedded;
 
  public:
+  Type
+  type() const
+  {
+    return Type::builtin_function_expression_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
@@ -46,6 +52,12 @@ class BuiltinFunctionProcessor : public INodeProcessor
     m_function_expression_processor = std::move(function_processor);
   }
 
+  Type
+  type() const
+  {
+    return Type::builtin_function_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/ConcatExpressionProcessor.hpp b/src/language/node_processor/ConcatExpressionProcessor.hpp
index 4653c341c..5fa6bbbda 100644
--- a/src/language/node_processor/ConcatExpressionProcessor.hpp
+++ b/src/language/node_processor/ConcatExpressionProcessor.hpp
@@ -41,6 +41,12 @@ class ConcatExpressionProcessor final : public INodeProcessor
   }
 
  public:
+  Type
+  type() const
+  {
+    return Type::concat_expression_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/ContinueProcessor.hpp b/src/language/node_processor/ContinueProcessor.hpp
index e8e5d6c7d..c98ad4312 100644
--- a/src/language/node_processor/ContinueProcessor.hpp
+++ b/src/language/node_processor/ContinueProcessor.hpp
@@ -6,6 +6,12 @@
 class ContinueProcessor final : public INodeProcessor
 {
  public:
+  Type
+  type() const
+  {
+    return Type::continue_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/DoWhileProcessor.hpp b/src/language/node_processor/DoWhileProcessor.hpp
index 6f3c14b7f..593fd4bf1 100644
--- a/src/language/node_processor/DoWhileProcessor.hpp
+++ b/src/language/node_processor/DoWhileProcessor.hpp
@@ -11,6 +11,12 @@ class DoWhileProcessor final : public INodeProcessor
   ASTNode& m_node;
 
  public:
+  Type
+  type() const
+  {
+    return Type::do_while_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/FakeProcessor.hpp b/src/language/node_processor/FakeProcessor.hpp
index ce3b7d257..f947ec2a1 100644
--- a/src/language/node_processor/FakeProcessor.hpp
+++ b/src/language/node_processor/FakeProcessor.hpp
@@ -6,6 +6,12 @@
 class FakeProcessor final : public INodeProcessor
 {
  public:
+  Type
+  type() const
+  {
+    return Type::fake_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy&)
   {
diff --git a/src/language/node_processor/ForProcessor.hpp b/src/language/node_processor/ForProcessor.hpp
index 4199e0c42..674c7d05e 100644
--- a/src/language/node_processor/ForProcessor.hpp
+++ b/src/language/node_processor/ForProcessor.hpp
@@ -11,6 +11,12 @@ class ForProcessor final : public INodeProcessor
   ASTNode& m_node;
 
  public:
+  Type
+  type() const
+  {
+    return Type::for_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/FunctionProcessor.hpp b/src/language/node_processor/FunctionProcessor.hpp
index 2b3e65ecb..69ca0e488 100644
--- a/src/language/node_processor/FunctionProcessor.hpp
+++ b/src/language/node_processor/FunctionProcessor.hpp
@@ -16,6 +16,12 @@ class FunctionExpressionProcessor final : public INodeProcessor
   ASTNode& m_function_expression;
 
  public:
+  Type
+  type() const
+  {
+    return Type::function_expression_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
@@ -292,6 +298,12 @@ class FunctionProcessor : public INodeProcessor
     m_function_expression_processors.emplace_back(std::move(function_processor));
   }
 
+  Type
+  type() const
+  {
+    return Type::function_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/INodeProcessor.hpp b/src/language/node_processor/INodeProcessor.hpp
index 2c35b6c49..942a22717 100644
--- a/src/language/node_processor/INodeProcessor.hpp
+++ b/src/language/node_processor/INodeProcessor.hpp
@@ -11,6 +11,37 @@
 class INodeProcessor
 {
  public:
+  enum class Type
+  {
+    affectation_processor,
+    array_subscript_processor,
+    binary_expression_processor,
+    break_processor,
+    builtin_function_expression_processor,
+    builtin_function_processor,
+    concat_expression_processor,
+    continue_processor,
+    do_while_processor,
+    expression_list_processor,
+    fake_processor,
+    for_processor,
+    function_expression_processor,
+    function_processor,
+    if_processor,
+    inc_dec_expression_processor,
+    inner_list_to_vector_processor,
+    list_processor,
+    local_name_processor,
+    name_processor,
+    tiny_matrix_expression_processor,
+    tiny_vector_expression_processor,
+    unary_expression_processor,
+    value_processor,
+    while_processor
+  };
+
+  virtual Type type() const = 0;
+
   virtual DataVariant execute(ExecutionPolicy& exec_policy) = 0;
 
   std::string
diff --git a/src/language/node_processor/IfProcessor.hpp b/src/language/node_processor/IfProcessor.hpp
index 18d87bb89..0d7497eaf 100644
--- a/src/language/node_processor/IfProcessor.hpp
+++ b/src/language/node_processor/IfProcessor.hpp
@@ -11,6 +11,12 @@ class IfProcessor final : public INodeProcessor
   ASTNode& m_node;
 
  public:
+  Type
+  type() const
+  {
+    return Type::if_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/IncDecExpressionProcessor.hpp b/src/language/node_processor/IncDecExpressionProcessor.hpp
index 199d3ebb8..186d3da7c 100644
--- a/src/language/node_processor/IncDecExpressionProcessor.hpp
+++ b/src/language/node_processor/IncDecExpressionProcessor.hpp
@@ -71,6 +71,12 @@ class IncDecExpressionProcessor final : public INodeProcessor
   DataVariant* p_value{nullptr};
 
  public:
+  Type
+  type() const
+  {
+    return Type::inc_dec_expression_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy&)
   {
diff --git a/src/language/node_processor/InnerListToVectorProcessor.hpp b/src/language/node_processor/InnerListToVectorProcessor.hpp
index ef74daaab..12ab335b1 100644
--- a/src/language/node_processor/InnerListToVectorProcessor.hpp
+++ b/src/language/node_processor/InnerListToVectorProcessor.hpp
@@ -11,6 +11,12 @@ class InnerListToVectorProcessor final : public INodeProcessor
   std::unique_ptr<ASTNodeExpressionListProcessor> m_expression_list_processor;
 
  public:
+  Type
+  type() const
+  {
+    return Type::inner_list_to_vector_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/LocalNameProcessor.hpp b/src/language/node_processor/LocalNameProcessor.hpp
index 51d442b26..e7d7f40d8 100644
--- a/src/language/node_processor/LocalNameProcessor.hpp
+++ b/src/language/node_processor/LocalNameProcessor.hpp
@@ -13,6 +13,12 @@ class LocalNameProcessor final : public INodeProcessor
   int32_t m_context_id;
 
  public:
+  Type
+  type() const
+  {
+    return Type::local_name_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/NameProcessor.hpp b/src/language/node_processor/NameProcessor.hpp
index d5dee9085..04bbde4d0 100644
--- a/src/language/node_processor/NameProcessor.hpp
+++ b/src/language/node_processor/NameProcessor.hpp
@@ -12,6 +12,12 @@ class NameProcessor final : public INodeProcessor
   DataVariant* p_value{nullptr};
 
  public:
+  Type
+  type() const
+  {
+    return Type::name_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy&)
   {
diff --git a/src/language/node_processor/TinyMatrixExpressionProcessor.hpp b/src/language/node_processor/TinyMatrixExpressionProcessor.hpp
index bcb3e65f3..91d1a53b2 100644
--- a/src/language/node_processor/TinyMatrixExpressionProcessor.hpp
+++ b/src/language/node_processor/TinyMatrixExpressionProcessor.hpp
@@ -13,6 +13,12 @@ class TinyMatrixExpressionProcessor final : public INodeProcessor
   ASTNode& m_node;
 
  public:
+  Type
+  type() const
+  {
+    return Type::tiny_matrix_expression_processor;
+  }
+
   PUGS_INLINE
   DataVariant
   execute(ExecutionPolicy& exec_policy)
diff --git a/src/language/node_processor/TinyVectorExpressionProcessor.hpp b/src/language/node_processor/TinyVectorExpressionProcessor.hpp
index ac86b9025..5c1a2d946 100644
--- a/src/language/node_processor/TinyVectorExpressionProcessor.hpp
+++ b/src/language/node_processor/TinyVectorExpressionProcessor.hpp
@@ -13,6 +13,12 @@ class TinyVectorExpressionProcessor final : public INodeProcessor
   ASTNode& m_node;
 
  public:
+  Type
+  type() const
+  {
+    return Type::tiny_vector_expression_processor;
+  }
+
   PUGS_INLINE
   DataVariant
   execute(ExecutionPolicy& exec_policy)
diff --git a/src/language/node_processor/UnaryExpressionProcessor.hpp b/src/language/node_processor/UnaryExpressionProcessor.hpp
index cdc4fc541..06bbfde45 100644
--- a/src/language/node_processor/UnaryExpressionProcessor.hpp
+++ b/src/language/node_processor/UnaryExpressionProcessor.hpp
@@ -46,6 +46,12 @@ class UnaryExpressionProcessor final : public INodeProcessor
   }
 
  public:
+  Type
+  type() const
+  {
+    return Type::unary_expression_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
@@ -72,6 +78,12 @@ class UnaryExpressionProcessor<UnaryOpT, std::shared_ptr<ValueT>, std::shared_pt
   }
 
  public:
+  Type
+  type() const
+  {
+    return Type::unary_expression_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/language/node_processor/ValueProcessor.hpp b/src/language/node_processor/ValueProcessor.hpp
index 342198223..66f054fe8 100644
--- a/src/language/node_processor/ValueProcessor.hpp
+++ b/src/language/node_processor/ValueProcessor.hpp
@@ -12,6 +12,12 @@ class ValueProcessor final : public INodeProcessor
   DataVariant m_value;
 
  public:
+  Type
+  type() const
+  {
+    return Type::value_processor;
+  }
+
   PUGS_INLINE
   DataVariant
   execute(ExecutionPolicy&)
diff --git a/src/language/node_processor/WhileProcessor.hpp b/src/language/node_processor/WhileProcessor.hpp
index af7cc604b..72c8f4186 100644
--- a/src/language/node_processor/WhileProcessor.hpp
+++ b/src/language/node_processor/WhileProcessor.hpp
@@ -11,6 +11,12 @@ class WhileProcessor final : public INodeProcessor
   ASTNode& m_node;
 
  public:
+  Type
+  type() const
+  {
+    return Type::while_processor;
+  }
+
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
diff --git a/src/utils/SignalManager.cpp b/src/utils/SignalManager.cpp
index 399f3164c..1fb5c9949 100644
--- a/src/utils/SignalManager.cpp
+++ b/src/utils/SignalManager.cpp
@@ -1,5 +1,6 @@
 #include <utils/SignalManager.hpp>
 
+#include <language/ast/ASTBacktrace.hpp>
 #include <utils/BacktraceManager.hpp>
 #include <utils/ConsoleManager.hpp>
 #include <utils/Messenger.hpp>
@@ -67,41 +68,51 @@ SignalManager::pauseForDebug(int signal)
 void
 SignalManager::handler(int signal)
 {
-  std::signal(SIGFPE, SIG_DFL);
-  std::signal(SIGSEGV, SIG_IGN);
-  std::signal(SIGTERM, SIG_DFL);
-  std::signal(SIGINT, SIG_DFL);
-  std::signal(SIGABRT, SIG_DFL);
-
-  // Each failing process must write
-  std::cerr.setstate(std::ios::goodbit);
-
-  BacktraceManager bm;
-  std::cerr << bm << '\n';
-
-  std::exception_ptr eptr = std::current_exception();
-  try {
-    if (eptr) {
-      std::rethrow_exception(eptr);
+  static std::mutex mutex;
+
+  if (mutex.try_lock()) {
+    std::signal(SIGTERM, SIG_DFL);
+    std::signal(SIGINT, SIG_DFL);
+    std::signal(SIGABRT, SIG_DFL);
+
+    // Each failing process must write
+    std::cerr.setstate(std::ios::goodbit);
+
+    std::ostringstream error_msg;
+
+    BacktraceManager bm;
+    error_msg << bm;
+
+    std::cerr << error_msg.str() << '\n';
+
+    std::exception_ptr eptr = std::current_exception();
+    try {
+      if (eptr) {
+        std::rethrow_exception(eptr);
+      }
     }
-  }
-  catch (const NotImplementedError& not_implemented_error) {
-    std::cerr << not_implemented_error.what() << '\n';
-  }
-  catch (const UnexpectedError& unexpected_error) {
-    std::cerr << unexpected_error.what() << '\n';
-  }
-  catch (const AssertError& assert_error) {
-    std::cerr << assert_error << '\n';
-  }
-  catch (...) {
-    std::cerr << "Unknown exception!\n";
-  }
+    catch (const NotImplementedError& not_implemented_error) {
+      std::cerr << not_implemented_error.what() << '\n';
+    }
+    catch (const UnexpectedError& unexpected_error) {
+      std::cerr << unexpected_error.what() << '\n';
+    }
+    catch (const AssertError& assert_error) {
+      std::cerr << assert_error << '\n';
+    }
+    catch (...) {
+      std::cerr << "Unknown exception!\n";
+    }
+
+    std::cerr << "\n *** " << rang::style::reset << rang::fg::reset << rang::style::bold << "Signal " << rang::fgB::red
+              << signalName(signal) << rang::fg::reset << " caught" << rang::style::reset << " ***\n";
 
-  std::cerr << "\n *** " << rang::style::reset << rang::fg::reset << rang::style::bold << "Signal " << rang::fgB::red
-            << signalName(signal) << rang::fg::reset << " caught" << rang::style::reset << " ***\n";
+    std::cerr << '\n' << ASTBacktrace::getInstance().stackInfo() << '\n';
 
-  SignalManager::pauseForDebug(signal);
+    SignalManager::pauseForDebug(signal);
+
+    mutex.unlock();
+  }
 }
 
 void
diff --git a/tests/test_ASTModulesImporter.cpp b/tests/test_ASTModulesImporter.cpp
index 4be8e087d..f70fa9b2b 100644
--- a/tests/test_ASTModulesImporter.cpp
+++ b/tests/test_ASTModulesImporter.cpp
@@ -1,6 +1,7 @@
 #include <catch2/catch_test_macros.hpp>
 #include <catch2/matchers/catch_matchers_all.hpp>
 
+#include <language/ast/ASTBacktrace.hpp>
 #include <language/ast/ASTBuilder.hpp>
 #include <language/ast/ASTModulesImporter.hpp>
 #include <language/ast/ASTNodeExpressionBuilder.hpp>
@@ -37,7 +38,9 @@ test_ASTExecutionInfo(const ASTNode& root_node, const ModuleRepository& module_r
     test_ASTExecutionInfo(*ast, module_repository);                                                 \
                                                                                                     \
     ExecutionPolicy exec_policy;                                                                    \
+    ASTBacktrace::create();                                                                         \
     ast->execute(exec_policy);                                                                      \
+    ASTBacktrace::destroy();                                                                        \
                                                                                                     \
     std::stringstream ast_output;                                                                   \
     ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::data_type}}; \
diff --git a/tests/test_ASTNode.cpp b/tests/test_ASTNode.cpp
index bb4b07f9b..468a27a89 100644
--- a/tests/test_ASTNode.cpp
+++ b/tests/test_ASTNode.cpp
@@ -2,6 +2,7 @@
 #include <catch2/matchers/catch_matchers_all.hpp>
 
 #include <language/PEGGrammar.hpp>
+#include <language/ast/ASTBacktrace.hpp>
 #include <language/ast/ASTNode.hpp>
 #include <language/node_processor/FakeProcessor.hpp>
 #include <utils/Demangle.hpp>
@@ -17,12 +18,16 @@ TEST_CASE("ASTNode", "[language]")
     ExecutionPolicy exec_policy;
 
 #ifndef NDEBUG
+    ASTBacktrace::create();
     REQUIRE_THROWS(ast_node.execute(exec_policy));
+    ASTBacktrace::destroy();
 #endif   // NDEBUG
 
     ast_node.m_node_processor = std::make_unique<FakeProcessor>();
 
+    ASTBacktrace::create();
     REQUIRE_NOTHROW(ast_node.execute(exec_policy));
+    ASTBacktrace::destroy();
   }
 
   SECTION("name")
diff --git a/tests/test_ASTNodeListProcessor.cpp b/tests/test_ASTNodeListProcessor.cpp
index 934eb5891..d858b313a 100644
--- a/tests/test_ASTNodeListProcessor.cpp
+++ b/tests/test_ASTNodeListProcessor.cpp
@@ -1,6 +1,7 @@
 #include <catch2/catch_test_macros.hpp>
 #include <catch2/matchers/catch_matchers_all.hpp>
 
+#include <language/ast/ASTBacktrace.hpp>
 #include <language/ast/ASTBuilder.hpp>
 #include <language/ast/ASTNodeDataTypeBuilder.hpp>
 #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp>
@@ -35,7 +36,9 @@ true;
 
   ASTNodeExpressionBuilder{*ast};
   ExecutionPolicy exec_policy;
+  ASTBacktrace::create();
   ast->execute(exec_policy);
+  ASTBacktrace::destroy();
 
   REQUIRE(ast->children[0]->is_type<language::integer>());
   REQUIRE(ast->children[1]->is_type<language::true_kw>());
diff --git a/tests/test_AffectationProcessor.cpp b/tests/test_AffectationProcessor.cpp
index 71670fd5d..03781088a 100644
--- a/tests/test_AffectationProcessor.cpp
+++ b/tests/test_AffectationProcessor.cpp
@@ -16,6 +16,7 @@
 #include <utils/Stringify.hpp>
 
 #include <FixturesForBuiltinT.hpp>
+#include <language/ast/ASTBacktrace.hpp>
 #include <language/utils/BasicAffectationRegistrerFor.hpp>
 
 #include <pegtl/string_input.hpp>
@@ -37,7 +38,9 @@
                                                                               \
     ASTNodeExpressionBuilder{*ast};                                           \
     ExecutionPolicy exec_policy;                                              \
+    ASTBacktrace::create();                                                   \
     ast->execute(exec_policy);                                                \
+    ASTBacktrace::destroy();                                                  \
                                                                               \
     auto symbol_table = ast->m_symbol_table;                                  \
                                                                               \
@@ -98,7 +101,9 @@
                                                                                                                 \
     ASTNodeExpressionBuilder{*ast};                                                                             \
     ExecutionPolicy exec_policy;                                                                                \
+    ASTBacktrace::create();                                                                                     \
     ast->execute(exec_policy);                                                                                  \
+    ASTBacktrace::destroy();                                                                                    \
                                                                                                                 \
     using namespace TAO_PEGTL_NAMESPACE;                                                                        \
     position use_position{internal::iterator{"fixture"}, "fixture"};                                            \
@@ -150,7 +155,9 @@
     ASTNodeExpressionBuilder{*ast};                                \
     ExecutionPolicy exec_policy;                                   \
                                                                    \
+    ASTBacktrace::create();                                        \
     REQUIRE_THROWS_WITH(ast->execute(exec_policy), error_message); \
+    ASTBacktrace::destroy();                                       \
   }
 
 // clazy:excludeall=non-pod-global-static
diff --git a/tests/test_AffectationToStringProcessor.cpp b/tests/test_AffectationToStringProcessor.cpp
index 6b20e7ca8..8e15ddc66 100644
--- a/tests/test_AffectationToStringProcessor.cpp
+++ b/tests/test_AffectationToStringProcessor.cpp
@@ -1,6 +1,7 @@
 #include <catch2/catch_test_macros.hpp>
 #include <catch2/matchers/catch_matchers_all.hpp>
 
+#include <language/ast/ASTBacktrace.hpp>
 #include <language/ast/ASTBuilder.hpp>
 #include <language/ast/ASTModulesImporter.hpp>
 #include <language/ast/ASTNodeAffectationExpressionBuilder.hpp>
@@ -32,7 +33,9 @@
                                                                               \
     ASTNodeExpressionBuilder{*ast};                                           \
     ExecutionPolicy exec_policy;                                              \
+    ASTBacktrace::create();                                                   \
     ast->execute(exec_policy);                                                \
+    ASTBacktrace::destroy();                                                  \
                                                                               \
     auto symbol_table = ast->m_symbol_table;                                  \
                                                                               \
diff --git a/tests/test_AffectationToTupleProcessor.cpp b/tests/test_AffectationToTupleProcessor.cpp
index 84d1a1639..ca6a6294b 100644
--- a/tests/test_AffectationToTupleProcessor.cpp
+++ b/tests/test_AffectationToTupleProcessor.cpp
@@ -1,6 +1,7 @@
 #include <catch2/catch_test_macros.hpp>
 #include <catch2/matchers/catch_matchers_all.hpp>
 
+#include <language/ast/ASTBacktrace.hpp>
 #include <language/ast/ASTBuilder.hpp>
 #include <language/ast/ASTModulesImporter.hpp>
 #include <language/ast/ASTNodeAffectationExpressionBuilder.hpp>
@@ -32,7 +33,9 @@
                                                                               \
     ASTNodeExpressionBuilder{*ast};                                           \
     ExecutionPolicy exec_policy;                                              \
+    ASTBacktrace::create();                                                   \
     ast->execute(exec_policy);                                                \
+    ASTBacktrace::destroy();                                                  \
                                                                               \
     auto symbol_table = ast->m_symbol_table;                                  \
                                                                               \
@@ -63,7 +66,9 @@
     ASTNodeExpressionBuilder{*ast};                                \
     ExecutionPolicy exec_policy;                                   \
                                                                    \
+    ASTBacktrace::create();                                        \
     REQUIRE_THROWS_WITH(ast->execute(exec_policy), error_message); \
+    ASTBacktrace::destroy();                                       \
   }
 
 // clazy:excludeall=non-pod-global-static
diff --git a/tests/test_ArraySubscriptProcessor.cpp b/tests/test_ArraySubscriptProcessor.cpp
index 5b1ac6c1c..949951c22 100644
--- a/tests/test_ArraySubscriptProcessor.cpp
+++ b/tests/test_ArraySubscriptProcessor.cpp
@@ -1,6 +1,7 @@
 #include <catch2/catch_test_macros.hpp>
 #include <catch2/matchers/catch_matchers_all.hpp>
 
+#include <language/ast/ASTBacktrace.hpp>
 #include <language/ast/ASTBuilder.hpp>
 #include <language/ast/ASTModulesImporter.hpp>
 #include <language/ast/ASTNodeAffectationExpressionBuilder.hpp>
@@ -33,7 +34,9 @@
                                                                               \
     ASTNodeExpressionBuilder{*ast};                                           \
     ExecutionPolicy exec_policy;                                              \
+    ASTBacktrace::create();                                                   \
     ast->execute(exec_policy);                                                \
+    ASTBacktrace::destroy();                                                  \
                                                                               \
     auto symbol_table = ast->m_symbol_table;                                  \
                                                                               \
@@ -66,7 +69,9 @@
                                                                  \
       ASTNodeExpressionBuilder{*ast};                            \
       ExecutionPolicy exec_policy;                               \
+      ASTBacktrace::create();                                    \
       ast->execute(exec_policy);                                 \
+      ASTBacktrace::destroy();                                   \
     };                                                           \
                                                                  \
     REQUIRE_THROWS_WITH(eval(), error_message);                  \
diff --git a/tests/test_BinaryExpressionProcessor_arithmetic.cpp b/tests/test_BinaryExpressionProcessor_arithmetic.cpp
index 83869150f..c93face34 100644
--- a/tests/test_BinaryExpressionProcessor_arithmetic.cpp
+++ b/tests/test_BinaryExpressionProcessor_arithmetic.cpp
@@ -76,7 +76,9 @@
                                                                                                                 \
     ASTNodeExpressionBuilder{*ast};                                                                             \
     ExecutionPolicy exec_policy;                                                                                \
+    ASTBacktrace::create();                                                                                     \
     ast->execute(exec_policy);                                                                                  \
+    ASTBacktrace::destroy();                                                                                    \
                                                                                                                 \
     using namespace TAO_PEGTL_NAMESPACE;                                                                        \
     position use_position{internal::iterator{"fixture"}, "fixture"};                                            \
@@ -153,7 +155,9 @@
                                                                                                                   \
     ASTNodeExpressionBuilder{*ast};                                                                               \
     ExecutionPolicy exec_policy;                                                                                  \
+    ASTBacktrace::create();                                                                                       \
     REQUIRE_THROWS_WITH(ast->execute(exec_policy), error_msg);                                                    \
+    ASTBacktrace::destroy();                                                                                      \
   }
 
 TEST_CASE("BinaryExpressionProcessor arithmetic", "[language]")
diff --git a/tests/test_BinaryExpressionProcessor_shift.cpp b/tests/test_BinaryExpressionProcessor_shift.cpp
index 71addbac7..190b9f2b2 100644
--- a/tests/test_BinaryExpressionProcessor_shift.cpp
+++ b/tests/test_BinaryExpressionProcessor_shift.cpp
@@ -64,7 +64,9 @@ fout << createSocketServer(0) << "\n";)";
 
       ASTNodeExpressionBuilder{*ast};
       ExecutionPolicy exec_policy;
+      ASTBacktrace::create();
       ast->execute(exec_policy);
+      ASTBacktrace::destroy();
     }
 
     REQUIRE(std::filesystem::exists(filename));
diff --git a/tests/test_BinaryExpressionProcessor_utils.hpp b/tests/test_BinaryExpressionProcessor_utils.hpp
index c8e3440cf..5983cda35 100644
--- a/tests/test_BinaryExpressionProcessor_utils.hpp
+++ b/tests/test_BinaryExpressionProcessor_utils.hpp
@@ -1,6 +1,7 @@
 #ifndef TEST_BINARY_EXPRESSION_PROCESSOR_UTILS_HPP
 #define TEST_BINARY_EXPRESSION_PROCESSOR_UTILS_HPP
 
+#include <language/ast/ASTBacktrace.hpp>
 #include <language/ast/ASTBuilder.hpp>
 #include <language/ast/ASTModulesImporter.hpp>
 #include <language/ast/ASTNodeDataTypeBuilder.hpp>
@@ -30,7 +31,9 @@
                                                                               \
     ASTNodeExpressionBuilder{*ast};                                           \
     ExecutionPolicy exec_policy;                                              \
+    ASTBacktrace::create();                                                   \
     ast->execute(exec_policy);                                                \
+    ASTBacktrace::destroy();                                                  \
                                                                               \
     auto symbol_table = ast->m_symbol_table;                                  \
                                                                               \
diff --git a/tests/test_BuiltinFunctionProcessor.cpp b/tests/test_BuiltinFunctionProcessor.cpp
index 8de9ec2c2..67812b0a4 100644
--- a/tests/test_BuiltinFunctionProcessor.cpp
+++ b/tests/test_BuiltinFunctionProcessor.cpp
@@ -1,6 +1,7 @@
 #include <catch2/catch_test_macros.hpp>
 #include <catch2/matchers/catch_matchers_predicate.hpp>
 
+#include <language/ast/ASTBacktrace.hpp>
 #include <language/ast/ASTBuilder.hpp>
 #include <language/ast/ASTModulesImporter.hpp>
 #include <language/ast/ASTNodeDataTypeBuilder.hpp>
@@ -31,7 +32,9 @@
                                                                                                                       \
     ASTNodeExpressionBuilder{*ast};                                                                                   \
     ExecutionPolicy exec_policy;                                                                                      \
+    ASTBacktrace::create();                                                                                           \
     ast->execute(exec_policy);                                                                                        \
+    ASTBacktrace::destroy();                                                                                          \
                                                                                                                       \
     auto symbol_table = ast->m_symbol_table;                                                                          \
                                                                                                                       \
@@ -69,7 +72,9 @@
     ASTNodeExpressionBuilder{*ast};                                                             \
     ExecutionPolicy exec_policy;                                                                \
     using namespace Catch::Matchers;                                                            \
+    ASTBacktrace::create();                                                                     \
     REQUIRE_THROWS_WITH(ast->execute(exec_policy), expected_error);                             \
+    ASTBacktrace::destroy();                                                                    \
   }
 
 // clazy:excludeall=non-pod-global-static
diff --git a/tests/test_DiscreteFunctionIntegrator.cpp b/tests/test_DiscreteFunctionIntegrator.cpp
index b3ba2efba..26a14385f 100644
--- a/tests/test_DiscreteFunctionIntegrator.cpp
+++ b/tests/test_DiscreteFunctionIntegrator.cpp
@@ -31,6 +31,9 @@
 
 TEST_CASE("DiscreteFunctionIntegrator", "[scheme]")
 {
+  const bool stack_details = ASTNode::getStackDetails();
+  ASTNode::setStackDetails(false);
+
   auto same_cell_value = [](auto f, auto g) -> bool {
     using ItemIdType = typename decltype(f)::index_type;
     for (ItemIdType item_id = 0; item_id < f.numberOfItems(); ++item_id) {
@@ -749,4 +752,6 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin(
       }
     }
   }
+
+  ASTNode::setStackDetails(stack_details);
 }
diff --git a/tests/test_DiscreteFunctionIntegratorByZone.cpp b/tests/test_DiscreteFunctionIntegratorByZone.cpp
index 217c15b38..0b550b063 100644
--- a/tests/test_DiscreteFunctionIntegratorByZone.cpp
+++ b/tests/test_DiscreteFunctionIntegratorByZone.cpp
@@ -33,6 +33,9 @@
 
 TEST_CASE("DiscreteFunctionIntegratorByZone", "[scheme]")
 {
+  const bool stack_details = ASTNode::getStackDetails();
+  ASTNode::setStackDetails(false);
+
   auto same_cell_value = [](auto f, auto g) -> bool {
     using ItemIdType = typename decltype(f)::index_type;
     for (ItemIdType item_id = 0; item_id < f.numberOfItems(); ++item_id) {
@@ -1030,4 +1033,6 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin(
       REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>()));
     }
   }
+
+  ASTNode::setStackDetails(stack_details);
 }
diff --git a/tests/test_DiscreteFunctionInterpoler.cpp b/tests/test_DiscreteFunctionInterpoler.cpp
index 0287d97c8..fd3f3b672 100644
--- a/tests/test_DiscreteFunctionInterpoler.cpp
+++ b/tests/test_DiscreteFunctionInterpoler.cpp
@@ -29,6 +29,9 @@
 
 TEST_CASE("DiscreteFunctionInterpoler", "[scheme]")
 {
+  const bool stack_details = ASTNode::getStackDetails();
+  ASTNode::setStackDetails(false);
+
   auto same_cell_value = [](auto f, auto g) -> bool {
     using ItemIdType = typename decltype(f)::index_type;
     for (ItemIdType item_id = 0; item_id < f.numberOfItems(); ++item_id) {
@@ -908,4 +911,6 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin(
       }
     }
   }
+
+  ASTNode::setStackDetails(stack_details);
 }
diff --git a/tests/test_DiscreteFunctionInterpolerByZone.cpp b/tests/test_DiscreteFunctionInterpolerByZone.cpp
index c4e6f0a00..8a0297d3e 100644
--- a/tests/test_DiscreteFunctionInterpolerByZone.cpp
+++ b/tests/test_DiscreteFunctionInterpolerByZone.cpp
@@ -31,6 +31,9 @@
 
 TEST_CASE("DiscreteFunctionInterpolerByZone", "[scheme]")
 {
+  const bool stack_details = ASTNode::getStackDetails();
+  ASTNode::setStackDetails(false);
+
   auto same_cell_value = [](auto f, auto g) -> bool {
     using ItemIdType = typename decltype(f)::index_type;
     for (ItemIdType item_id = 0; item_id < f.numberOfItems(); ++item_id) {
@@ -1042,4 +1045,6 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin(
       REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>()));
     }
   }
+
+  ASTNode::setStackDetails(stack_details);
 }
diff --git a/tests/test_DiscreteFunctionVectorIntegrator.cpp b/tests/test_DiscreteFunctionVectorIntegrator.cpp
index 4c510542b..60afd2dbc 100644
--- a/tests/test_DiscreteFunctionVectorIntegrator.cpp
+++ b/tests/test_DiscreteFunctionVectorIntegrator.cpp
@@ -32,6 +32,9 @@
 
 TEST_CASE("DiscreteFunctionVectorIntegrator", "[scheme]")
 {
+  const bool stack_details = ASTNode::getStackDetails();
+  ASTNode::setStackDetails(false);
+
   auto same_cell_value = [](const CellValue<const double>& fi, const size_t i, const auto& f) -> bool {
     for (CellId cell_id = 0; cell_id < fi.numberOfItems(); ++cell_id) {
       if (fi[cell_id] != f[cell_id][i]) {
@@ -396,4 +399,6 @@ Invalid value type: R^2)";
       }
     }
   }
+
+  ASTNode::setStackDetails(stack_details);
 }
diff --git a/tests/test_DiscreteFunctionVectorIntegratorByZone.cpp b/tests/test_DiscreteFunctionVectorIntegratorByZone.cpp
index ac516d3ff..01297d03d 100644
--- a/tests/test_DiscreteFunctionVectorIntegratorByZone.cpp
+++ b/tests/test_DiscreteFunctionVectorIntegratorByZone.cpp
@@ -34,6 +34,9 @@
 
 TEST_CASE("DiscreteFunctionVectorIntegratorByZone", "[scheme]")
 {
+  const bool stack_details = ASTNode::getStackDetails();
+  ASTNode::setStackDetails(false);
+
   auto same_cell_value = [](const CellValue<const double>& fi, const size_t i, const auto& f) -> bool {
     for (CellId cell_id = 0; cell_id < fi.numberOfItems(); ++cell_id) {
       if (fi[cell_id] != f[cell_id][i]) {
@@ -438,4 +441,6 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2];
 
     REQUIRE(i == function_id_list.size());
   }
+
+  ASTNode::setStackDetails(stack_details);
 }
diff --git a/tests/test_DiscreteFunctionVectorInterpoler.cpp b/tests/test_DiscreteFunctionVectorInterpoler.cpp
index e47b8754d..3a4871076 100644
--- a/tests/test_DiscreteFunctionVectorInterpoler.cpp
+++ b/tests/test_DiscreteFunctionVectorInterpoler.cpp
@@ -29,6 +29,9 @@
 
 TEST_CASE("DiscreteFunctionVectorInterpoler", "[scheme]")
 {
+  const bool stack_details = ASTNode::getStackDetails();
+  ASTNode::setStackDetails(false);
+
   auto same_cell_value = [](const CellValue<const double>& fi, const size_t i, const auto& f) -> bool {
     for (CellId cell_id = 0; cell_id < fi.numberOfItems(); ++cell_id) {
       if (fi[cell_id] != f[cell_id][i]) {
@@ -444,4 +447,6 @@ Invalid interpolation value type: R^2)";
       }
     }
   }
+
+  ASTNode::setStackDetails(stack_details);
 }
diff --git a/tests/test_DiscreteFunctionVectorInterpolerByZone.cpp b/tests/test_DiscreteFunctionVectorInterpolerByZone.cpp
index 2fe984934..0547aa3cf 100644
--- a/tests/test_DiscreteFunctionVectorInterpolerByZone.cpp
+++ b/tests/test_DiscreteFunctionVectorInterpolerByZone.cpp
@@ -31,6 +31,9 @@
 
 TEST_CASE("DiscreteFunctionVectorInterpolerByZone", "[scheme]")
 {
+  const bool stack_details = ASTNode::getStackDetails();
+  ASTNode::setStackDetails(false);
+
   auto same_cell_value = [](const CellValue<const double>& fi, const size_t i, const auto& f) -> bool {
     for (CellId cell_id = 0; cell_id < fi.numberOfItems(); ++cell_id) {
       if (fi[cell_id] != f[cell_id][i]) {
@@ -509,4 +512,6 @@ Invalid interpolation value type: R^2)";
       }
     }
   }
+
+  ASTNode::setStackDetails(stack_details);
 }
diff --git a/tests/test_InterpolateItemArray.cpp b/tests/test_InterpolateItemArray.cpp
index 6d020282a..61674ce2d 100644
--- a/tests/test_InterpolateItemArray.cpp
+++ b/tests/test_InterpolateItemArray.cpp
@@ -26,6 +26,9 @@
 
 TEST_CASE("InterpolateItemArray", "[language]")
 {
+  const bool stack_details = ASTNode::getStackDetails();
+  ASTNode::setStackDetails(false);
+
   SECTION("interpolate on all items")
   {
     auto same_cell_array = [](auto f, auto g) -> bool {
@@ -1106,4 +1109,6 @@ let f_3d: R^3 -> (R^3), x -> (2*x, [2*x[0]-x[1], 3*x[2]-x[0], x[1]+x[2]], 0);
       }
     }
   }
+
+  ASTNode::setStackDetails(stack_details);
 }
diff --git a/tests/test_InterpolateItemValue.cpp b/tests/test_InterpolateItemValue.cpp
index f53921ed1..9ee0a324f 100644
--- a/tests/test_InterpolateItemValue.cpp
+++ b/tests/test_InterpolateItemValue.cpp
@@ -26,6 +26,9 @@
 
 TEST_CASE("InterpolateItemValue", "[language]")
 {
+  const bool stack_details = ASTNode::getStackDetails();
+  ASTNode::setStackDetails(false);
+
   SECTION("interpolate on all items")
   {
     auto same_item_value = [](auto f, auto g) -> bool {
@@ -1085,4 +1088,6 @@ let R2x2_non_linear_3d: R^3 -> R^2x2, x -> [[2 * exp(x[0]) * sin(x[1]) + 3 * cos
       }
     }
   }
+
+  ASTNode::setStackDetails(stack_details);
 }
diff --git a/tests/test_ItemArrayVariantFunctionInterpoler.cpp b/tests/test_ItemArrayVariantFunctionInterpoler.cpp
index 7ceaf2207..3a2c4aada 100644
--- a/tests/test_ItemArrayVariantFunctionInterpoler.cpp
+++ b/tests/test_ItemArrayVariantFunctionInterpoler.cpp
@@ -26,6 +26,9 @@
 
 TEST_CASE("ItemArrayVariantFunctionInterpoler", "[scheme]")
 {
+  const bool stack_details = ASTNode::getStackDetails();
+  ASTNode::setStackDetails(false);
+
   auto same_item_array = [](auto f, auto g) -> bool {
     using ItemIdType = typename decltype(f)::index_type;
     if (f.sizeOfArrays() != g.sizeOfArrays()) {
@@ -672,4 +675,6 @@ let R2x2_non_linear_3d: R^3 -> R^2x2,
       }
     }
   }
+
+  ASTNode::setStackDetails(stack_details);
 }
diff --git a/tests/test_ItemValueVariantFunctionInterpoler.cpp b/tests/test_ItemValueVariantFunctionInterpoler.cpp
index 19f53e108..be1d4272b 100644
--- a/tests/test_ItemValueVariantFunctionInterpoler.cpp
+++ b/tests/test_ItemValueVariantFunctionInterpoler.cpp
@@ -26,6 +26,9 @@
 
 TEST_CASE("ItemValueVariantFunctionInterpoler", "[scheme]")
 {
+  const bool stack_details = ASTNode::getStackDetails();
+  ASTNode::setStackDetails(false);
+
   auto same_item_value = [](auto f, auto g) -> bool {
     using ItemIdType = typename decltype(f)::index_type;
     for (ItemIdType item_id = 0; item_id < f.numberOfItems(); ++item_id) {
@@ -544,4 +547,6 @@ let R2x2_non_linear_3d: R^3 -> R^2x2, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin(
       }
     }
   }
+
+  ASTNode::setStackDetails(stack_details);
 }
-- 
GitLab