#pragma once #include "Expression.h" #include "Statement.h" #include "helperFunctions/ShortHands.h" #include "TypeWrapper.h" #include "Environment.h" #include "Value.h" #include "BobStdLib.h" #include "ErrorReporter.h" #include #include #include #include #include #include // Forward declaration class Interpreter; // RAII helper for thunk execution flag struct ScopedThunkFlag { bool& flag; bool prev; ScopedThunkFlag(bool& f) : flag(f), prev(f) { flag = true; } ~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 struct Thunk { public: using ThunkFunction = std::function; explicit Thunk(ThunkFunction func) : func(std::move(func)) {} Value execute() const { return func(); } bool isThunk() const { return true; } private: ThunkFunction func; }; class Interpreter : public ExprVisitor, public StmtVisitor { public: Value visitBinaryExpr(const std::shared_ptr& expression) override; Value visitCallExpr(const std::shared_ptr& expression) override; Value visitFunctionExpr(const std::shared_ptr& expression) override; Value visitGroupingExpr(const std::shared_ptr& expression) override; Value visitLiteralExpr(const std::shared_ptr& expression) override; Value visitUnaryExpr(const std::shared_ptr& expression) override; Value visitVarExpr(const std::shared_ptr& expression) override; Value visitIncrementExpr(const std::shared_ptr& expression) override; Value visitAssignExpr(const std::shared_ptr& expression) override; Value visitTernaryExpr(const std::shared_ptr& expression) override; Value visitArrayLiteralExpr(const std::shared_ptr& expression) override; Value visitArrayIndexExpr(const std::shared_ptr& expression) override; Value visitArrayAssignExpr(const std::shared_ptr& expression) override; Value visitDictLiteralExpr(const std::shared_ptr& expression) override; void visitBlockStmt(const std::shared_ptr& statement, ExecutionContext* context = nullptr) override; void visitExpressionStmt(const std::shared_ptr& statement, ExecutionContext* context = nullptr) override; void visitVarStmt(const std::shared_ptr& statement, ExecutionContext* context = nullptr) override; void visitFunctionStmt(const std::shared_ptr& statement, ExecutionContext* context = nullptr) override; void visitReturnStmt(const std::shared_ptr& statement, ExecutionContext* context = nullptr) override; void visitIfStmt(const std::shared_ptr& statement, ExecutionContext* context = nullptr) override; void visitWhileStmt(const std::shared_ptr& statement, ExecutionContext* context = nullptr) override; void visitDoWhileStmt(const std::shared_ptr& statement, ExecutionContext* context = nullptr) override; void visitForStmt(const std::shared_ptr& statement, ExecutionContext* context = nullptr) override; void visitBreakStmt(const std::shared_ptr& statement, ExecutionContext* context = nullptr) override; void visitContinueStmt(const std::shared_ptr& statement, ExecutionContext* context = nullptr) override; void visitAssignStmt(const std::shared_ptr& statement, ExecutionContext* context = nullptr) override; void interpret(std::vector> statements); explicit Interpreter(bool IsInteractive) : IsInteractive(IsInteractive), errorReporter(nullptr){ environment = std::make_shared(); } virtual ~Interpreter() = default; private: std::shared_ptr environment; bool IsInteractive; std::vector> builtinFunctions; std::vector> functions; std::vector> thunks; // Store thunks to prevent memory leaks ErrorReporter* errorReporter; bool inThunkExecution = false; // Automatic cleanup tracking int functionCreationCount = 0; int thunkCreationCount = 0; static const int CLEANUP_THRESHOLD = 1000000; // Cleanup every 1M creations (effectively disabled for performance) Value evaluate(const std::shared_ptr& expr); Value evaluateWithoutTrampoline(const std::shared_ptr& expr); bool isEqual(Value a, Value b); void execute(const std::shared_ptr& statement, ExecutionContext* context = nullptr); void executeBlock(std::vector> statements, std::shared_ptr env, ExecutionContext* context = nullptr); void addStdLibFunctions(); // Trampoline execution Value runTrampoline(Value initialResult); public: bool isTruthy(Value object); std::string stringify(Value object); void addBuiltinFunction(std::shared_ptr func); // Memory management void cleanupUnusedFunctions(); void cleanupUnusedThunks(); void forceCleanup(); // Error reporting void setErrorReporter(ErrorReporter* reporter) { errorReporter = reporter; if (environment) { environment->setErrorReporter(reporter); } // Add standard library functions after error reporter is set addStdLibFunctions(); } };