• 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

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) :
726✔
20
        m_lib_env(lib_env), m_features(features),
363✔
21
        m_computed_ast(internal::NodeType::Unused),
363✔
22
        m_parser(debug),
363✔
23
        m_import_solver(debug, lib_env),
363✔
24
        m_macro_processor(debug),
363✔
25
        m_ast_optimizer(debug),
363✔
26
        m_name_resolver(debug),
363✔
27
        m_logger("Welder", debug),
363✔
28
        m_lowerer(debug),
363✔
29
        m_ir_optimizer(debug),
363✔
30
        m_ir_compiler(debug)
363✔
31
    {}
726✔
32

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

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

43
        return computeAST(filename, code);
346✔
44
    }
346✔
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✔
51
    }
×
52

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

57
        for (const std::string& sym : symbols)
12✔
58
            m_name_resolver.addDefinedSymbol(sym, /* is_mutable= */ false);
10✔
59
        return computeAST(ARK_NO_NAME_FILE, code);
2✔
NEW
60
    }
×
61

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

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

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

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

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

88
            Diagnostics::generate(e);
×
89
            return false;
×
90
        }
37✔
91
    }
956✔
92

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

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

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

112
                default:
NEW
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
            }
4✔
116
        }
4✔
117

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

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

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

130
        std::ofstream output(filename, std::ofstream::binary);
201✔
131
        output.write(
402✔
132
            reinterpret_cast<char*>(&m_bytecode[0]),
201✔
133
            static_cast<std::streamsize>(m_bytecode.size() * sizeof(uint8_t)));
201✔
134
        output.close();
201✔
135
        return true;
201✔
136
    }
201✔
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
18✔
151
    {
18✔
152
        return m_bytecode;
18✔
153
    }
154

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

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

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

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

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

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

194
            if ((m_features & FeatureASTOptimizer) != 0)
541✔
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

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