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

ArkScript-lang / Ark / 21488144923

29 Jan 2026 05:26PM UTC coverage: 93.408% (-0.009%) from 93.417%
21488144923

push

github

SuperFola
chore: update credits

8828 of 9451 relevant lines covered (93.41%)

274416.0 hits per line

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

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

33
    void Welder::registerSymbol(const std::string& name)
675✔
34
    {
675✔
35
        m_name_resolver.addDefinedSymbol(name, /* is_mutable= */ false);
675✔
36
    }
675✔
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)
16✔
47
    {
16✔
48
        m_root_file = std::filesystem::current_path();  // No filename given, take the current working directory
16✔
49

50
        return computeAST(ARK_NO_NAME_FILE, code);
16✔
51
    }
1✔
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✔
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)
×
79
                dumpIRToFile();
×
80

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

88
            Diagnostics::generate(e);
×
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:
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✔
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

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)
608✔
169
    {
608✔
170
        try
171
        {
172
            m_parser.process(filename, code);
608✔
173
            m_computed_ast = m_parser.ast();
×
174

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

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

188
            if ((m_features & FeatureNameResolver) != 0)
600✔
189
            {
190
                m_name_resolver.process(m_computed_ast);
316✔
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
        }
150✔
202
        catch (const CodeError& e)
203
        {
204
            if ((m_features & FeatureTestFailOnException) > 0)
75✔
205
                throw;
75✔
206

207
            if (filename != ARK_NO_NAME_FILE)
×
208
                Diagnostics::generate(e);
×
209
            else
210
                Diagnostics::generateWithCode(e, code);
×
211
            return false;
×
212
        }
75✔
213
    }
1,377✔
214
}
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