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

ArkScript-lang / Ark / 21146409233

19 Jan 2026 05:26PM UTC coverage: 93.417% (+0.7%) from 92.743%
21146409233

push

github

SuperFola
feat(tests, debugger): testing the debugger triggering on errors

5 of 5 new or added lines in 2 files covered. (100.0%)

125 existing lines in 4 files now uncovered.

8813 of 9434 relevant lines covered (93.42%)

273848.42 hits per line

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

83.21
/src/arkreactor/Compiler/Welder.cpp
1
#include <Ark/Constants.hpp>
2
#include <Ark/Compiler/Welder.hpp>
3

4
#include <Ark/Compiler/Package/ImportSolver.hpp>
5
#include <Ark/Compiler/AST/Optimizer.hpp>
6
#include <Ark/Compiler/Macros/Processor.hpp>
7
#include <Ark/Compiler/NameResolution/NameResolutionPass.hpp>
8
#include <Ark/Utils/Files.hpp>
9
#include <Ark/Error/Exceptions.hpp>
10
#include <Ark/Error/Diagnostics.hpp>
11
#include <Ark/VM/Value/Value.hpp>
12

13
#include <cassert>
14
#include <sstream>
15
#include <fmt/ostream.h>
16

17
namespace Ark
18
{
19
    Welder::Welder(const unsigned debug, const std::vector<std::filesystem::path>& lib_env, const uint16_t features) :
764✔
20
        m_lib_env(lib_env), m_features(features),
382✔
21
        m_computed_ast(internal::NodeType::Unused),
382✔
22
        m_parser(debug),
382✔
23
        m_import_solver(debug, lib_env),
382✔
24
        m_macro_processor(debug),
382✔
25
        m_ast_optimizer(debug),
382✔
26
        m_name_resolver(debug),
382✔
27
        m_logger("Welder", debug),
382✔
28
        m_lowerer(debug),
382✔
29
        m_ir_optimizer(debug),
382✔
30
        m_ir_compiler(debug)
382✔
31
    {}
764✔
32

33
    void Welder::registerSymbol(const std::string& name)
673✔
34
    {
673✔
35
        m_name_resolver.addDefinedSymbol(name, /* is_mutable= */ false);
673✔
36
    }
673✔
37

38
    bool Welder::computeASTFromFile(const std::string& filename)
352✔
39
    {
352✔
40
        m_root_file = std::filesystem::path(filename);
352✔
41
        const std::string code = Utils::readFile(filename);
352✔
42

43
        return computeAST(filename, code);
352✔
44
    }
352✔
45

46
    bool Welder::computeASTFromString(const std::string& code)
15✔
47
    {
15✔
48
        m_root_file = std::filesystem::current_path();  // No filename given, take the current working directory
15✔
49

50
        return computeAST(ARK_NO_NAME_FILE, code);
15✔
UNCOV
51
    }
×
52

53
    bool Welder::computeASTFromStringWithKnownSymbols(const std::string& code, const std::vector<std::string>& symbols)
15✔
54
    {
15✔
55
        m_root_file = std::filesystem::current_path();  // No filename given, take the current working directory
15✔
56

57
        for (const std::string& sym : symbols)
76✔
58
            m_name_resolver.addDefinedSymbol(sym, /* is_mutable= */ true);
61✔
59
        return computeAST(ARK_NO_NAME_FILE, code);
15✔
UNCOV
60
    }
×
61

62
    bool Welder::generateBytecode()
476✔
63
    {
476✔
64
        try
65
        {
66
            m_lowerer.process(m_computed_ast);
476✔
67
            m_ir = m_lowerer.intermediateRepresentation();
×
68

69
            if ((m_features & FeatureIROptimizer) != 0)
248✔
70
            {
71
                m_ir_optimizer.process(m_ir, m_lowerer.symbols(), m_lowerer.values());
248✔
72
                m_ir = m_ir_optimizer.intermediateRepresentation();
248✔
73
            }
248✔
74

75
            m_ir_compiler.process(m_ir, m_lowerer.symbols(), m_lowerer.values());
248✔
76
            m_bytecode = m_ir_compiler.bytecode();
257✔
77

78
            if ((m_features & FeatureDumpIR) != 0)
×
UNCOV
79
                dumpIRToFile();
×
80

UNCOV
81
            return true;
×
82
        }
76✔
83
        catch (const CodeError& e)
84
        {
85
            if ((m_features & FeatureTestFailOnException) > 0)
38✔
86
                throw;
38✔
87

UNCOV
88
            Diagnostics::generate(e);
×
UNCOV
89
            return false;
×
90
        }
38✔
91
    }
1,028✔
92

93
    bool Welder::generateBytecodeUsingTables(const std::vector<std::string>& symbols, const std::vector<Value>& constants, const std::size_t start_page_at_offset)
15✔
94
    {
15✔
95
        std::vector<internal::ValTableElem> values;
15✔
96
        for (const Value& constant : constants)
94✔
97
        {
98
            switch (constant.valueType())
79✔
99
            {
44✔
100
                case ValueType::Number:
101
                    values.emplace_back(constant.number());
44✔
102
                    break;
73✔
103

104
                case ValueType::String:
105
                    values.emplace_back(constant.string());
29✔
106
                    break;
35✔
107

108
                case ValueType::PageAddr:
109
                    values.emplace_back(static_cast<std::size_t>(constant.pageAddr()));
6✔
110
                    break;
6✔
111

112
                default:
UNCOV
113
                    assert(false && "This should not be possible to have a constant that isn't a Number, a String or a PageAddr");
×
114
                    break;
115
            }
79✔
116
        }
79✔
117

118
        m_lowerer.addToTables(symbols, values);
15✔
119
        m_lowerer.offsetPagesBy(start_page_at_offset);
15✔
120
        return generateBytecode();
15✔
121
    }
15✔
122

123
    bool Welder::saveBytecodeToFile(const std::string& filename)
206✔
124
    {
206✔
125
        m_logger.info("Final bytecode size: {}B", m_bytecode.size() * sizeof(uint8_t));
206✔
126

127
        if (m_bytecode.empty())
206✔
UNCOV
128
            return false;
×
129

130
        std::ofstream output(filename, std::ofstream::binary);
206✔
131
        output.write(
412✔
132
            reinterpret_cast<char*>(&m_bytecode[0]),
206✔
133
            static_cast<std::streamsize>(m_bytecode.size() * sizeof(uint8_t)));
206✔
134
        output.close();
206✔
135
        return true;
206✔
136
    }
206✔
137

138
    const internal::Node& Welder::ast() const noexcept
13✔
139
    {
13✔
140
        return m_computed_ast;
13✔
141
    }
142

143
    std::string Welder::textualIR() const noexcept
20✔
144
    {
20✔
145
        std::stringstream stream;
20✔
146
        m_ir_compiler.dumpToStream(stream);
20✔
147
        return stream.str();
20✔
148
    }
20✔
149

150
    const bytecode_t& Welder::bytecode() const noexcept
31✔
151
    {
31✔
152
        return m_bytecode;
31✔
153
    }
154

UNCOV
155
    void Welder::dumpIRToFile() const
×
UNCOV
156
    {
×
UNCOV
157
        std::filesystem::path path = m_root_file;
×
UNCOV
158
        if (is_directory(m_root_file))
×
UNCOV
159
            path /= "output.ark.ir";
×
160
        else
UNCOV
161
            path.replace_extension(".ark.ir");
×
162

UNCOV
163
        std::ofstream output(path);
×
UNCOV
164
        m_ir_compiler.dumpToStream(output);
×
UNCOV
165
        output.close();
×
166
    }
×
167

168
    bool Welder::computeAST(const std::string& filename, const std::string& code)
607✔
169
    {
607✔
170
        try
171
        {
172
            m_parser.process(filename, code);
607✔
UNCOV
173
            m_computed_ast = m_parser.ast();
×
174

175
            if ((m_features & FeatureImportSolver) != 0)
630✔
176
            {
177
                m_import_solver.setup(m_root_file, m_parser.imports());
346✔
178
                m_import_solver.process(m_computed_ast);
346✔
179
                m_computed_ast = m_import_solver.ast();
345✔
180
            }
345✔
181

182
            if ((m_features & FeatureMacroProcessor) != 0)
629✔
183
            {
184
                m_macro_processor.process(m_computed_ast);
345✔
185
                m_computed_ast = m_macro_processor.ast();
315✔
186
            }
315✔
187

188
            if ((m_features & FeatureNameResolver) != 0)
599✔
189
            {
190
                m_name_resolver.process(m_computed_ast);
315✔
191
                m_computed_ast = m_name_resolver.ast();
295✔
192
            }
295✔
193

194
            if ((m_features & FeatureASTOptimizer) != 0)
579✔
195
            {
196
                m_ast_optimizer.process(m_computed_ast);
11✔
197
                m_computed_ast = m_ast_optimizer.ast();
11✔
198
            }
11✔
199

200
            return true;
11✔
201
        }
148✔
202
        catch (const CodeError& e)
203
        {
204
            if ((m_features & FeatureTestFailOnException) > 0)
74✔
205
                throw;
74✔
206

UNCOV
207
            Diagnostics::generate(e);
×
UNCOV
208
            return false;
×
209
        }
74✔
210
    }
1,373✔
211
}
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