diff --git a/headers/Interpreter.h b/headers/Interpreter.h index dbd207e..911f3f2 100644 --- a/headers/Interpreter.h +++ b/headers/Interpreter.h @@ -26,6 +26,14 @@ struct ScopedThunkFlag { ~ScopedThunkFlag() { flag = prev; } }; +// RAII helper for environment management +struct ScopedEnv { + std::shared_ptr& target; + std::shared_ptr prev; + ScopedEnv(std::shared_ptr& e) : target(e), prev(e) {} + ~ScopedEnv() { target = prev; } +}; + // Thunk class for trampoline-based tail call optimization class Thunk { public: diff --git a/source/Interpreter.cpp b/source/Interpreter.cpp index 423ffc9..3479ee3 100644 --- a/source/Interpreter.cpp +++ b/source/Interpreter.cpp @@ -604,8 +604,8 @@ Value Interpreter::visitCallExpr(const std::shared_ptr& expression) { if (expression->isTailCall) { // Create a thunk for tail call optimization auto thunk = new Thunk([this, function, arguments]() -> Value { - // Set up the environment for the tail call - auto previousEnv = environment; + // Use RAII to manage environment + ScopedEnv _env(environment); environment = std::make_shared(function->closure); environment->setErrorReporter(errorReporter); @@ -623,12 +623,10 @@ Value Interpreter::visitCallExpr(const std::shared_ptr& expression) { for (const auto& stmt : function->body) { execute(stmt, &context); if (context.hasReturn) { - environment = previousEnv; return context.returnValue; } } - environment = previousEnv; return context.returnValue; }); @@ -636,7 +634,7 @@ Value Interpreter::visitCallExpr(const std::shared_ptr& expression) { return Value(thunk); } else { // Normal function call - create new environment - auto previousEnv = environment; + ScopedEnv _env(environment); environment = std::make_shared(function->closure); environment->setErrorReporter(errorReporter); @@ -651,12 +649,10 @@ Value Interpreter::visitCallExpr(const std::shared_ptr& expression) { for (const auto& stmt : function->body) { execute(stmt, &context); if (context.hasReturn) { - environment = previousEnv; return context.returnValue; } } - environment = previousEnv; return context.returnValue; } } diff --git a/tco.bob b/tco.bob new file mode 100644 index 0000000..9a51ada --- /dev/null +++ b/tco.bob @@ -0,0 +1,13 @@ +func countdown(n) +{ + + if(n == 0) + return 0; + + print(n); + + return countdown(n - 1); + +} + +countdown(1000000);