ArkScript
A small, lisp-inspired, functional scripting language
Debugger.hpp
Go to the documentation of this file.
1/**
2 * @file Debugger.hpp
3 * @author Lexy Plateau (lexplt.dev@gmail.com)
4 * @brief Debugger used by the VM when an error or a breakpoint is reached
5 * @date 2026-01-12
6 *
7 * @copyright Copyright (c) 2026-01-12
8 *
9 */
10
11#ifndef ARK_VM_DEBUGGER_HPP
12#define ARK_VM_DEBUGGER_HPP
13
14#include <vector>
15#include <memory>
16#include <string>
17#include <optional>
18#include <filesystem>
19
23
24namespace Ark
25{
26 class VM;
27}
28
29namespace Ark::internal
30{
32 {
33 std::size_t ip;
34 std::size_t pp;
35 uint16_t sp;
36 uint16_t fc;
37 std::vector<ScopeView> locals;
38 std::vector<std::shared_ptr<ClosureScope>> closure_scopes;
39 };
40
42 {
43 std::vector<bytecode_t> pages;
44 std::vector<std::string> symbols;
45 std::vector<Value> constants;
46 };
47
49 {
50 public:
51 /**
52 * @brief Create a new Debugger object
53 *
54 * @param context context from the VM before displaying a backtrace
55 * @param libenv
56 * @param symbols symbols table of the VM
57 * @param constants constants table of the VM
58 */
59 Debugger(const ExecutionContext& context, const std::vector<std::filesystem::path>& libenv, const std::vector<std::string>& symbols, const std::vector<Value>& constants);
60
61 /**
62 * @brief Create a new Debugger object that will use lines from a file as prompts, instead of waiting for user inputs
63 *
64 * @param libenv
65 * @param path_to_prompt_file
66 * @param os output stream
67 * @param symbols symbols table of the VM
68 * @param constants constants table of the VM
69 */
70 Debugger(const std::vector<std::filesystem::path>& libenv, const std::string& path_to_prompt_file, std::ostream& os, const std::vector<std::string>& symbols, const std::vector<Value>& constants);
71
72 /**
73 * @brief Save the current VM state, to get back to it once the debugger is done running
74 *
75 * @param context
76 */
77 void saveState(const ExecutionContext& context);
78
79 /**
80 * @brief Reset a VM context to the last state saved by the debugger
81 *
82 * @param context context to reset
83 */
85
86 /**
87 * @brief Start the debugger shell
88 *
89 * @param vm
90 * @param context
91 * @param from_breakpoint true if the debugger is being invoked from a breakpoint
92 */
93 void run(VM& vm, ExecutionContext& context, bool from_breakpoint);
94
95 [[nodiscard]] inline bool isRunning() const noexcept
96 {
97 return m_running;
98 }
99
100 [[nodiscard]] inline bool shouldQuitVM() const noexcept
101 {
102 return m_quit_vm;
103 }
104
105 private:
106 std::vector<std::unique_ptr<SavedState>> m_states;
107 std::vector<std::filesystem::path> m_libenv;
108 std::vector<std::string> m_symbols;
109 std::vector<Value> m_constants;
110 bool m_running { false };
111 bool m_quit_vm { false };
112
113 std::ostream& m_os;
115 std::unique_ptr<std::istream> m_prompt_stream;
116 std::string m_code; ///< Code added while inside the debugger
117 std::size_t m_line_count { 0 };
118
119 void showContext(const VM& vm, const ExecutionContext& context) const;
120 void showStack(VM& vm, const ExecutionContext& context, std::size_t count) const;
121 void showLocals(VM& vm, ExecutionContext& context, std::size_t count) const;
122
123 static std::optional<std::string> getCommandArg(const std::string& command, const std::string& line);
124 static std::optional<std::size_t> parseStringAsInt(const std::string& str);
125 [[nodiscard]] std::optional<std::size_t> getArgAndParseOrError(const std::string& command, const std::string& line, std::size_t default_value) const;
126
127 std::optional<std::string> prompt(std::size_t ip, std::size_t pp, VM& vm, ExecutionContext& context);
128
129 /**
130 * @brief Take care of compiling new code using the existing data tables
131 *
132 * @param code
133 * @param start_page_at_offset offset to start the new pages at
134 * @return std::optional<CompiledPrompt> optional set of bytecode pages, symbols and constants if compilation succeeded
135 */
136 [[nodiscard]] std::optional<CompiledPrompt> compile(const std::string& code, std::size_t start_page_at_offset) const;
137 };
138}
139
140#endif // ARK_VM_DEBUGGER_HPP
Common code for the compiler.
Keeping track of the internal data needed by the VM.
Default value type handled by the virtual machine.
The ArkScript virtual machine, executing ArkScript bytecode.
Definition VM.hpp:48
void run(VM &vm, ExecutionContext &context, bool from_breakpoint)
Start the debugger shell.
Definition Debugger.cpp:63
std::string m_code
Code added while inside the debugger.
Definition Debugger.hpp:116
std::vector< std::unique_ptr< SavedState > > m_states
Definition Debugger.hpp:106
static std::optional< std::size_t > parseStringAsInt(const std::string &str)
Definition Debugger.cpp:223
void showStack(VM &vm, const ExecutionContext &context, std::size_t count) const
Definition Debugger.cpp:156
void showLocals(VM &vm, ExecutionContext &context, std::size_t count) const
Definition Debugger.cpp:179
bool shouldQuitVM() const noexcept
Definition Debugger.hpp:100
std::optional< std::string > prompt(std::size_t ip, std::size_t pp, VM &vm, ExecutionContext &context)
Definition Debugger.cpp:251
void resetContextToSavedState(ExecutionContext &context)
Reset a VM context to the last state saved by the debugger.
Definition Debugger.cpp:50
Debugger(const ExecutionContext &context, const std::vector< std::filesystem::path > &libenv, const std::vector< std::string > &symbols, const std::vector< Value > &constants)
Create a new Debugger object.
Definition Debugger.cpp:19
std::optional< std::size_t > getArgAndParseOrError(const std::string &command, const std::string &line, std::size_t default_value) const
Definition Debugger.cpp:233
bool isRunning() const noexcept
Definition Debugger.hpp:95
std::unique_ptr< std::istream > m_prompt_stream
Definition Debugger.hpp:115
std::ostream & m_os
Definition Debugger.hpp:113
std::vector< std::string > m_symbols
Definition Debugger.hpp:108
static std::optional< std::string > getCommandArg(const std::string &command, const std::string &line)
Definition Debugger.cpp:213
void showContext(const VM &vm, const ExecutionContext &context) const
Definition Debugger.cpp:131
void saveState(const ExecutionContext &context)
Save the current VM state, to get back to it once the debugger is done running.
Definition Debugger.cpp:38
std::vector< std::filesystem::path > m_libenv
Definition Debugger.hpp:107
std::vector< Value > m_constants
Definition Debugger.hpp:109
std::optional< CompiledPrompt > compile(const std::string &code, std::size_t start_page_at_offset) const
Take care of compiling new code using the existing data tables.
Definition Debugger.cpp:329
std::vector< Value > constants
Definition Debugger.hpp:45
std::vector< std::string > symbols
Definition Debugger.hpp:44
std::vector< bytecode_t > pages
Definition Debugger.hpp:43
std::vector< ScopeView > locals
Definition Debugger.hpp:37
std::vector< std::shared_ptr< ClosureScope > > closure_scopes
Definition Debugger.hpp:38