From dccc97c3bf76cb02854cdf03b21d952fefdbc606 Mon Sep 17 00:00:00 2001
From: Mattias Ajander <mattias@ajander.se>
Date: Sat, 12 Apr 2025 00:49:30 +0200
Subject: [PATCH] Improved scope and block management. Implement a max depth
 for scope aswell as a check if a new scope is needed in block calls.

---
 include/ast/BlockNode.h                |  2 ++
 include/ast/declaration/FunctionNode.h |  2 ++
 include/parser/Scope.h                 |  2 ++
 source/ast/BlockNode.cc                | 17 +++++++++++++++--
 source/logging/Logger.cc               |  1 -
 source/parser/Scope.cc                 |  4 ++--
 6 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/include/ast/BlockNode.h b/include/ast/BlockNode.h
index 1fb8bbb..90d26e7 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 9711e82..51a4068 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 b02738e..b025cc3 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 e945c01..6a3a4a9 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 90f923f..a19a2c6 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 d771d5c..c964ba3 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)
-- 
GitLab