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

ArkScript-lang / Ark / 22520480876

28 Feb 2026 12:10PM UTC coverage: 93.472% (-0.03%) from 93.5%
22520480876

push

github

web-flow
fix: replace `std::cout` with `std::cerr` in the error diagnostics handler (#644)

* Replace `std::cout` with `std::cerr` in the error diagnostics handler

This is half of the solution for #643 and is more than workable in
principle, but still without color. Regarding color, I noticed that
"termcolor" is one of the additional project modules, so I'll see what
that leads to. Finally, I'll review the current tests to see if any
already exist that test the output flow and any coloration. If not, I'll
try to implement such test(s).

* Save benchmark test results

* Delete benchmark test results

9250 of 9896 relevant lines covered (93.47%)

276809.88 hits per line

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

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

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

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

43
        return computeAST(filename, code);
409✔
44
    }
409✔
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()
565✔
63
    {
565✔
64
        try
65
        {
66
            m_lowerer.process(m_computed_ast);
565✔
67
            m_ir = m_lowerer.intermediateRepresentation();
×
68

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

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

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

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

88
            Diagnostics::generate(e);
×
89
            return false;
×
90
        }
43✔
91
    }
1,216✔
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)
250✔
124
    {
250✔
125
        m_logger.info("Final bytecode size: {}B", m_bytecode.size() * sizeof(uint8_t));
250✔
126

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

130
        std::ofstream output(filename, std::ofstream::binary);
250✔
131
        output.write(
500✔
132
            reinterpret_cast<char*>(&m_bytecode[0]),
250✔
133
            static_cast<std::streamsize>(m_bytecode.size() * sizeof(uint8_t)));
250✔
134
        output.close();
250✔
135
        return true;
250✔
136
    }
250✔
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
23✔
144
    {
23✔
145
        std::stringstream stream;
23✔
146
        m_ir_compiler.dumpToStream(stream);
23✔
147
        return stream.str();
23✔
148
    }
23✔
149

150
    const bytecode_t& Welder::bytecode() const noexcept
281✔
151
    {
281✔
152
        return m_bytecode;
281✔
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 = path / ARK_CACHE_DIRNAME / "output.ark.ir";
×
160
        else
161
        {
162
            const auto filename = path.filename().replace_extension(".ark.ir");
×
163
            path.remove_filename();
×
164
            path = path / ARK_CACHE_DIRNAME / filename;
×
165
        }
×
166

167
        std::ofstream output(path);
×
168
        m_ir_compiler.dumpToStream(output);
×
169
        output.close();
×
170
    }
×
171

172
    bool Welder::computeAST(const std::string& filename, const std::string& code)
715✔
173
    {
715✔
174
        try
175
        {
176
            m_parser.process(filename, code);
715✔
177
            m_computed_ast = m_parser.ast();
×
178

179
            if ((m_features & FeatureImportSolver) != 0)
738✔
180
            {
181
                m_import_solver.setup(m_root_file, m_parser.imports());
404✔
182
                m_import_solver.process(m_computed_ast);
404✔
183
                m_computed_ast = m_import_solver.ast();
403✔
184
            }
403✔
185

186
            if ((m_features & FeatureMacroProcessor) != 0)
737✔
187
            {
188
                m_macro_processor.process(m_computed_ast);
403✔
189
                m_computed_ast = m_macro_processor.ast();
368✔
190
            }
368✔
191

192
            if ((m_features & FeatureNameResolver) != 0)
702✔
193
            {
194
                m_name_resolver.process(m_computed_ast);
368✔
195
                m_computed_ast = m_name_resolver.ast();
347✔
196
            }
347✔
197

198
            if ((m_features & FeatureASTOptimizer) != 0)
681✔
199
            {
200
                m_ast_optimizer.process(m_computed_ast);
13✔
201
                m_computed_ast = m_ast_optimizer.ast();
13✔
202
            }
13✔
203

204
            return true;
13✔
205
        }
160✔
206
        catch (const CodeError& e)
207
        {
208
            if ((m_features & FeatureTestFailOnException) > 0)
80✔
209
                throw;
80✔
210

211
            if (filename != ARK_NO_NAME_FILE)
×
212
                Diagnostics::generate(e);
×
213
            else
214
                Diagnostics::generateWithCode(e, code);
×
215
            return false;
×
216
        }
80✔
217
    }
1,603✔
218
}
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