• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ArkScript-lang / Ark / 21043080682

15 Jan 2026 07:07PM UTC coverage: 91.835% (-0.9%) from 92.743%
21043080682

Pull #628

github

web-flow
Merge 453e86f68 into ada0e0686
Pull Request #628: Feat/debugger

131 of 242 new or added lines in 10 files covered. (54.13%)

2 existing lines in 1 file now uncovered.

8571 of 9333 relevant lines covered (91.84%)

276580.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/arkreactor/VM/Debugger.cpp
1
#include <Ark/VM/Debugger.hpp>
2

3
#include <fmt/core.h>
4
#include <fmt/color.h>
5

6
#include <Ark/State.hpp>
7
#include <Ark/VM/VM.hpp>
8
#include <Ark/Compiler/Welder.hpp>
9
#include <Ark/Compiler/BytecodeReader.hpp>
10

11
namespace Ark::internal
12
{
NEW
13
    Debugger::Debugger(const ExecutionContext& context, const std::vector<std::filesystem::path>& libenv, const std::vector<std::string>& symbols, const std::vector<Value>& constants) :
×
NEW
14
        m_libenv(libenv), m_symbols(symbols), m_constants(constants), m_running(false)
×
NEW
15
    {
×
NEW
16
        saveState(context);
×
NEW
17
    }
×
18

NEW
19
    void Debugger::saveState(const ExecutionContext& context)
×
NEW
20
    {
×
NEW
21
        m_states.emplace_back(
×
NEW
22
            std::make_unique<SavedState>(
×
NEW
23
                context.ip,
×
NEW
24
                context.pp,
×
NEW
25
                context.sp,
×
NEW
26
                context.fc,
×
NEW
27
                context.locals,
×
NEW
28
                context.stacked_closure_scopes));
×
NEW
29
    }
×
30

NEW
31
    void Debugger::resetContextToErrorState(ExecutionContext& context)
×
NEW
32
    {
×
NEW
33
        const auto& [ip, pp, sp, fc, locals, closure_scopes] = *m_states.back();
×
NEW
34
        context.locals = locals;
×
NEW
35
        context.stacked_closure_scopes = closure_scopes;
×
NEW
36
        context.ip = ip;
×
NEW
37
        context.pp = pp;
×
NEW
38
        context.sp = sp;
×
NEW
39
        context.fc = fc;
×
40

NEW
41
        m_states.pop_back();
×
NEW
42
    }
×
43

NEW
44
    void Debugger::run(VM& vm, ExecutionContext& context)
×
NEW
45
    {
×
NEW
46
        m_running = true;
×
NEW
47
        const bool is_vm_running = vm.m_running;
×
48

49
        // TODO: create a shell
NEW
50
        fmt::print("> ");
×
NEW
51
        std::string line;
×
NEW
52
        std::getline(std::cin, line);
×
53

54
        // todo: start writing the article, god damn it!
55

NEW
56
        if (const auto pages = compile(m_code + line, vm.m_state.m_pages.size()); pages.has_value())
×
57
        {
NEW
58
            context.ip = 0;
×
NEW
59
            context.pp = vm.m_state.m_pages.size();
×
60
            // create dedicated scope, so that we won't be overwriting existing variables
NEW
61
            context.locals.emplace_back(context.scopes_storage.data(), context.locals.back().storageEnd());
×
62

NEW
63
            vm.m_state.extendBytecode(pages.value(), m_symbols, m_constants);
×
64

NEW
65
            if (vm.safeRun(context) == 0)
×
66
            {
67
                // executing code worked
NEW
68
                m_code += line;
×
69

NEW
70
                const Value* maybe_value = vm.peekAndResolveAsPtr(context);
×
NEW
71
                if (maybe_value != nullptr && maybe_value->valueType() != ValueType::Undefined && maybe_value->valueType() != ValueType::InstPtr)
×
NEW
72
                    fmt::println("{}", fmt::styled(maybe_value->toString(vm), fmt::fg(fmt::color::chocolate)));
×
NEW
73
            }
×
74

NEW
75
            context.locals.pop_back();
×
NEW
76
        }
×
77

NEW
78
        m_running = false;
×
79
        // we do not want to retain code from the past executions
NEW
80
        m_code.clear();
×
81
        // we hit a HALT instruction that set 'running' to false, ignore that if we were still running!
NEW
82
        vm.m_running = is_vm_running;
×
NEW
83
    }
×
84

NEW
85
    std::optional<std::vector<bytecode_t>> Debugger::compile(const std::string& code, const std::size_t start_page_at_offset)
×
NEW
86
    {
×
NEW
87
        Welder welder(0, m_libenv, DefaultFeatures);
×
NEW
88
        if (!welder.computeASTFromStringWithKnownSymbols(code, m_symbols))
×
NEW
89
            return std::nullopt;
×
NEW
90
        if (!welder.generateBytecodeUsingTables(m_symbols, m_constants, start_page_at_offset))
×
NEW
91
            return std::nullopt;
×
92

NEW
93
        BytecodeReader bcr;
×
NEW
94
        bcr.feed(welder.bytecode());
×
NEW
95
        const auto syms = bcr.symbols();
×
NEW
96
        const auto vals = bcr.values(syms);
×
NEW
97
        const auto files = bcr.filenames(vals);
×
NEW
98
        const auto inst_locs = bcr.instLocations(files);
×
NEW
99
        const auto [pages, _] = bcr.code(inst_locs);
×
100

NEW
101
        m_symbols = syms.symbols;
×
NEW
102
        m_constants = vals.values;
×
103

NEW
104
        return pages;
×
NEW
105
    }
×
106
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc