diff --git a/include/ast/BlockNode.h b/include/ast/BlockNode.h
index 1fb8bbb77d6f0bcb2e2143302b7ba2b6728f36cd..90d26e7bdbb24834dd30da102da61b336fccb230 100644
--- a/include/ast/BlockNode.h
+++ b/include/ast/BlockNode.h
@@ -2,6 +2,8 @@
 
 #include "ast/Node.h"
 #include "ast/control/ReturnNode.h"
+#include "ast/declaration/DeclarationNode.h"
+#include "ast/declaration/FunctionNode.h"
 #include "parser/Scope.h"
 
 namespace funk
diff --git a/include/ast/declaration/FunctionNode.h b/include/ast/declaration/FunctionNode.h
index 9711e82e59784c2517b361b6b32484ce5b589750..51a40687403bc4f492a0c61b47c350cd180a53e4 100644
--- a/include/ast/declaration/FunctionNode.h
+++ b/include/ast/declaration/FunctionNode.h
@@ -11,6 +11,8 @@
 namespace funk
 {
 
+class BlockNode;
+
 class FunctionNode : public Node
 {
 public:
diff --git a/include/parser/Scope.h b/include/parser/Scope.h
index b02738e9ad58fc32e932ca48911e88de97953c1e..b025cc36ce263494e9dbee10f0a6f5e9a57eb7b2 100644
--- a/include/parser/Scope.h
+++ b/include/parser/Scope.h
@@ -3,6 +3,7 @@
 #include "ast/Node.h"
 #include "logging/LogMacros.h"
 #include "utils/Common.h"
+#include "utils/Exception.h"
 
 namespace funk
 {
@@ -11,6 +12,7 @@ class Scope
 {
 public:
     static Scope& instance();
+    static const int MAX_DEPTH = 1000;
 
     void push();
     void pop();
diff --git a/source/ast/BlockNode.cc b/source/ast/BlockNode.cc
index e945c01af71bdd5de88f1ff7cd7734ae42c971cd..6a3a4a9cb64bc48f9062a8db21c97309280ed4a0 100644
--- a/source/ast/BlockNode.cc
+++ b/source/ast/BlockNode.cc
@@ -28,15 +28,28 @@ Vector<Node*> BlockNode::get_statements() const
 
 Node* BlockNode::evaluate() const
 {
-    Scope::instance().push();
+    bool push_scope{false};
+
+    for (Node* statement : statements)
+    {
+        if (dynamic_cast<DeclarationNode*>(statement) || dynamic_cast<FunctionNode*>(statement))
+        {
+            push_scope = true;
+            break;
+        }
+    }
+
+    if (push_scope) { Scope::instance().push(); }
     Node* result{};
+
     for (Node* statement : statements)
     {
         result = statement->evaluate();
         if (dynamic_cast<ReturnNode*>(statement)) { break; }
         result = nullptr;
     }
-    Scope::instance().pop();
+
+    if (push_scope) { Scope::instance().pop(); }
     return result;
 }
 
diff --git a/source/logging/Logger.cc b/source/logging/Logger.cc
index 90f923f96e34653eb0128d9b41e2b44632b4104a..a19a2c677448fc813545c9ca5960e18bdeb65313 100644
--- a/source/logging/Logger.cc
+++ b/source/logging/Logger.cc
@@ -21,7 +21,6 @@ Logger& Logger::instance()
 
 void Logger::log(LogLevel level, const std::string& message)
 {
-    file_open();
     if (level < log_level) return;
 
     auto now = std::chrono::system_clock::now();
diff --git a/source/parser/Scope.cc b/source/parser/Scope.cc
index d771d5c74fcfd0c9663cb19a2698e4f7e2805a5a..c964ba35d01075d579872db788b2a076c68a4b76 100644
--- a/source/parser/Scope.cc
+++ b/source/parser/Scope.cc
@@ -21,15 +21,15 @@ Scope& Scope::instance()
 void Scope::push()
 {
     LOG_DEBUG("Pushing scope at depth " + to_str(depth) + " -> " + to_str(depth + 1));
+    if (depth++ >= MAX_DEPTH) { throw RuntimeError("Scope stack overflow, max depth is " + to_str(MAX_DEPTH)); }
     scopes.push_back({});
-    depth++;
 }
 
 void Scope::pop()
 {
     LOG_DEBUG("Popping scope at depth " + to_str(depth) + " -> " + to_str(depth - 1));
+    if (depth-- <= 0) { throw RuntimeError("Scope stack underflow, can't go below 0"); }
     scopes.pop_back();
-    depth--;
 }
 
 void Scope::add(const String& name, Node* node)