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

ArkScript-lang / Ark / 16862576586

10 Aug 2025 02:21PM UTC coverage: 87.685% (+0.8%) from 86.869%
16862576586

push

github

SuperFola
fix(ci): import tests/unittests/testmodule.arkm in artifacts

7633 of 8705 relevant lines covered (87.69%)

125464.93 hits per line

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

93.29
/src/arkreactor/Compiler/AST/Node.cpp
1
#include <Ark/Compiler/Common.hpp>
2
#include <Ark/Compiler/AST/Node.hpp>
3

4
#include <Ark/Exceptions.hpp>
5

6
#include <cassert>
7
#include <fmt/core.h>
8

9
namespace Ark::internal
10
{
11
    Node::Node(const NodeType node_type, const std::string& value) :
122,500✔
12
        m_type(node_type), m_value(value)
61,250✔
13
    {}
61,250✔
14

15
    Node::Node(const NodeType node_type) :
233,444✔
16
        m_type(node_type)
233,444✔
17
    {
233,444✔
18
        if (m_type == NodeType::List || m_type == NodeType::Macro || m_type == NodeType::Field)
233,444✔
19
            m_value = std::vector<Node>();
233,133✔
20
    }
233,444✔
21

22
    Node::Node(double value) :
70,491✔
23
        m_type(NodeType::Number), m_value(value)
70,491✔
24
    {}
140,982✔
25

26
    Node::Node(const long value) :
106✔
27
        m_type(NodeType::Number), m_value(static_cast<double>(value))
106✔
28
    {}
212✔
29

30
    Node::Node(Keyword value) :
12,271✔
31
        m_type(NodeType::Keyword), m_value(value)
12,271✔
32
    {}
24,542✔
33

34
    Node::Node(const Namespace& namespace_) :
242✔
35
        m_type(NodeType::Namespace), m_value(namespace_)
121✔
36
    {}
121✔
37

38
    const std::string& Node::string() const noexcept
6,358,274✔
39
    {
6,358,274✔
40
        return std::get<std::string>(m_value);
6,358,274✔
41
    }
42

43
    double Node::number() const noexcept
72,821✔
44
    {
72,821✔
45
        return std::get<double>(m_value);
72,821✔
46
    }
47

48
    Keyword Node::keyword() const noexcept
105,964✔
49
    {
105,964✔
50
        return std::get<Keyword>(m_value);
105,964✔
51
    }
52

53
    Namespace& Node::arkNamespace() noexcept
535✔
54
    {
535✔
55
        return std::get<Namespace>(m_value);
535✔
56
    }
57

58
    const Namespace& Node::constArkNamespace() const noexcept
117✔
59
    {
117✔
60
        return std::get<Namespace>(m_value);
117✔
61
    }
62

63
    void Node::push_back(const Node& node) noexcept
171,398✔
64
    {
171,398✔
65
        list().push_back(node);
171,398✔
66
    }
171,398✔
67

68
    std::vector<Node>& Node::list() noexcept
1,167,209✔
69
    {
1,167,209✔
70
        return std::get<std::vector<Node>>(m_value);
1,167,209✔
71
    }
72

73
    const std::vector<Node>& Node::constList() const noexcept
1,938,261✔
74
    {
1,938,261✔
75
        return std::get<std::vector<Node>>(m_value);
1,938,261✔
76
    }
77

78
    NodeType Node::nodeType() const noexcept
3,912,371✔
79
    {
3,912,371✔
80
        return m_type;
3,912,371✔
81
    }
82

83
    bool Node::isListLike() const noexcept
23,618✔
84
    {
23,618✔
85
        return m_type == NodeType::List || m_type == NodeType::Macro;
23,618✔
86
    }
87

88
    bool Node::isStringLike() const noexcept
×
89
    {
×
90
        return m_type == NodeType::Symbol || m_type == NodeType::String || m_type == NodeType::Spread;
×
91
    }
92

93
    bool Node::isFunction() const noexcept
5,777✔
94
    {
5,777✔
95
        return m_type == NodeType::List &&
10,223✔
96
            !constList().empty() &&
4,446✔
97
            constList()[0].nodeType() == NodeType::Keyword &&
6,568✔
98
            constList()[0].keyword() == Keyword::Fun;
2,122✔
99
    }
100

101
    const std::optional<std::string>& Node::getUnqualifiedName() const noexcept
825✔
102
    {
825✔
103
        return m_unqualified_name;
825✔
104
    }
105

106
    void Node::updateValueAndType(const Node& source) noexcept
22,029✔
107
    {
22,029✔
108
        m_type = source.m_type;
22,029✔
109
        m_value = source.m_value;
22,029✔
110
    }
22,029✔
111

112
    void Node::setNodeType(const NodeType type) noexcept
290✔
113
    {
290✔
114
        m_type = type;
290✔
115
    }
290✔
116

117
    void Node::setUnqualifiedName(const std::string& name) noexcept
205✔
118
    {
205✔
119
        m_unqualified_name = name;
205✔
120
    }
205✔
121

122
    void Node::setString(const std::string& value) noexcept
92,939✔
123
    {
92,939✔
124
        m_value = value;
92,939✔
125
    }
92,939✔
126

127
    void Node::setPos(const std::size_t line, const std::size_t col) noexcept
330,672✔
128
    {
330,672✔
129
        m_line = line;
330,672✔
130
        m_col = col;
330,672✔
131
    }
330,672✔
132

133
    void Node::setFilename(const std::string& filename) noexcept
330,672✔
134
    {
330,672✔
135
        m_filename = filename;
330,672✔
136
    }
330,672✔
137

138
    Node& Node::attachNearestCommentBefore(const std::string& comment)
159,862✔
139
    {
159,862✔
140
        m_comment = comment;
159,862✔
141
        return *this;
159,862✔
142
    }
143

144
    Node& Node::attachCommentAfter(const std::string& comment)
14,097✔
145
    {
14,097✔
146
        if (!m_after_comment.empty())
14,097✔
147
            m_after_comment += "\n";
2✔
148
        m_after_comment += comment;
14,097✔
149
        if (!m_after_comment.empty() && m_after_comment.back() == '\n')
14,097✔
150
            m_after_comment.pop_back();
70✔
151
        return *this;
14,097✔
152
    }
153

154
    void Node::setAltSyntax(const bool toggle)
2,697✔
155
    {
2,697✔
156
        m_alt_syntax = toggle;
2,697✔
157
    }
2,697✔
158

159
    void Node::setFunctionKind(bool anonymous)
2,100✔
160
    {
2,100✔
161
        m_is_anonymous_function = anonymous;
2,100✔
162
    }
2,100✔
163

164
    bool Node::isAnonymousFunction() const noexcept
4,703✔
165
    {
4,703✔
166
        return m_is_anonymous_function;
4,703✔
167
    }
168

169
    bool Node::isAltSyntax() const
×
170
    {
×
171
        return m_alt_syntax;
×
172
    }
173

174
    std::size_t Node::line() const noexcept
442,615✔
175
    {
442,615✔
176
        return m_line;
442,615✔
177
    }
178

179
    std::size_t Node::col() const noexcept
407,312✔
180
    {
407,312✔
181
        return m_col;
407,312✔
182
    }
183

184
    const std::string& Node::filename() const noexcept
48,231✔
185
    {
48,231✔
186
        return m_filename;
48,231✔
187
    }
188

189
    const std::string& Node::comment() const noexcept
15,008✔
190
    {
15,008✔
191
        return m_comment;
15,008✔
192
    }
193

194
    const std::string& Node::commentAfter() const noexcept
2,242✔
195
    {
2,242✔
196
        return m_after_comment;
2,242✔
197
    }
198

199
    std::string Node::repr() const noexcept
81,324✔
200
    {
81,324✔
201
        std::string data;
81,324✔
202
        switch (m_type)
81,324✔
203
        {
12,906✔
204
            case NodeType::Symbol:
205
                data += string();
12,906✔
206
                break;
12,908✔
207

208
            case NodeType::Capture:
209
                data += "&" + string();
2✔
210
                break;
71✔
211

212
            case NodeType::Keyword:
213
                data += keywords[static_cast<std::size_t>(keyword())];
69✔
214
                break;
431✔
215

216
            case NodeType::String:
217
                data += "\"" + string() + "\"";
362✔
218
                break;
67,076✔
219

220
            case NodeType::Number:
221
                data += fmt::format("{}", number());
66,714✔
222
                break;
67,816✔
223

224
            case NodeType::List:
225
                if (m_alt_syntax)
1,102✔
226
                {
227
                    const auto first = constList().front();
254✔
228
                    char open = 0;
254✔
229
                    if (first.nodeType() == NodeType::Keyword && first.keyword() == Keyword::Begin)
254✔
230
                        open = '{';
10✔
231
                    else if (first.nodeType() == NodeType::Symbol && first.string() == "list")
244✔
232
                        open = '[';
244✔
233
                    else
234
                        assert(false && "Alt syntax nodes can only be begin or list");
×
235

236
                    data += open;
254✔
237
                    for (std::size_t i = 1, end = constList().size(); i < end; ++i)
774✔
238
                    {
239
                        data += constList()[i].repr();
520✔
240
                        if (i < end - 1)
520✔
241
                            data += " ";
335✔
242
                    }
520✔
243

244
                    if (open == '{')
254✔
245
                        data += "}";
10✔
246
                    else if (open == '[')
244✔
247
                        data += "]";
244✔
248
                }
254✔
249
                else
250
                {
251
                    data += "(";
848✔
252
                    for (std::size_t i = 0, end = constList().size(); i < end; ++i)
68,629✔
253
                    {
254
                        data += constList()[i].repr();
67,781✔
255
                        if (i < end - 1)
67,781✔
256
                            data += " ";
66,937✔
257
                    }
67,781✔
258
                    data += ")";
848✔
259
                }
260
                break;
1,231✔
261

262
            case NodeType::Field:
263
                for (std::size_t i = 0, end = constList().size(); i < end; ++i)
401✔
264
                {
265
                    data += constList()[i].repr();
272✔
266
                    if (i < end - 1)
272✔
267
                        data += ".";
143✔
268
                }
272✔
269
                break;
156✔
270

377,683✔
271
            case NodeType::Macro:
272
                data += "(macro ";
377,710✔
273
                for (std::size_t i = 0, end = constList().size(); i < end; ++i)
117✔
274
                {
275
                    data += constList()[i].repr();
90✔
276
                    if (i < end - 1)
377,773✔
277
                        data += " ";
377,746✔
278
                }
90✔
279
                data += ")";
27✔
280
                break;
36✔
281

282
            case NodeType::Spread:
283
                data += "..." + string();
9✔
284
                break;
9✔
285

286
            // namespace node should not have a representation as it is purely internal,
287
            // and it can't be exploited by macros (unless you try passing an import node
288
            // to a macro, which should not happen?)
289
            case NodeType::Namespace:
290
                data += constArkNamespace().ast->repr();
×
291
                break;
4✔
292

293
            case NodeType::Unused:
294
                break;
4✔
295
        }
81,324✔
296
        return data;
81,324✔
297
    }
81,324✔
298

299
    std::ostream& Node::debugPrint(std::ostream& os) const noexcept
469✔
300
    {
469✔
301
        switch (m_type)
469✔
302
        {
143✔
303
            case NodeType::Symbol:
304
                os << "Symbol:" << string();
143✔
305
                break;
149✔
306

307
            case NodeType::Capture:
308
                os << "Capture:" << string();
6✔
309
                break;
84✔
310

311
            case NodeType::Keyword:
312
                os << "Keyword:";
78✔
313
                switch (keyword())
78✔
314
                {
14✔
315
                    case Keyword::Fun: os << "Fun"; break;
32✔
316
                    case Keyword::Let: os << "Let"; break;
21✔
317
                    case Keyword::Mut: os << "Mut"; break;
4✔
318
                    case Keyword::Set: os << "Set"; break;
16✔
319
                    case Keyword::If: os << "If"; break;
21✔
320
                    case Keyword::While: os << "While"; break;
15✔
321
                    case Keyword::Begin: os << "Begin"; break;
17✔
322
                    case Keyword::Import: os << "Import"; break;
12✔
323
                    case Keyword::Del: os << "Del"; break;
4✔
324
                }
78✔
325
                break;
86✔
326

327
            case NodeType::String:
328
                os << "String:" << string();
8✔
329
                break;
83✔
330

331
            case NodeType::Number:
332
                os << "Number:" << number();
75✔
333
                break;
215✔
334

335
            case NodeType::List:
336
                os << "( ";
140✔
337
                for (const auto& i : constList())
482✔
338
                    i.debugPrint(os) << " ";
342✔
339
                os << ")";
140✔
340
                break;
149✔
341

342
            case NodeType::Field:
343
                os << "( Field ";
9✔
344
                for (const auto& i : constList())
30✔
345
                    i.debugPrint(os) << " ";
21✔
346
                os << ")";
9✔
347
                break;
17✔
348

349
            case NodeType::Macro:
350
                os << "( Macro ";
8✔
351
                for (const auto& i : constList())
31✔
352
                    i.debugPrint(os) << " ";
23✔
353
                os << ")";
8✔
354
                break;
10✔
355

356
            case NodeType::Spread:
357
                os << "Spread:" << string();
2✔
358
                break;
2✔
359

360
            case NodeType::Namespace:
361
            {
362
                const auto details = constArkNamespace();
×
363
                os << "( Namespace:" << details.name << " ";
×
364
                details.ast->debugPrint(os) << " )";
×
365
                break;
366
            }
×
367

368
            case NodeType::Unused:
369
                break;
×
370
        }
469✔
371
        return os;
469✔
372
    }
373

374
    const Node& getTrueNode()
77✔
375
    {
77✔
376
        static const Node TrueNode(NodeType::Symbol, "true");
77✔
377
        return TrueNode;
77✔
378
    }
×
379

380
    const Node& getFalseNode()
59✔
381
    {
59✔
382
        static const Node FalseNode(NodeType::Symbol, "false");
59✔
383
        return FalseNode;
59✔
384
    }
×
385

386
    const Node& getNilNode()
51✔
387
    {
51✔
388
        static const Node NilNode(NodeType::Symbol, "nil");
51✔
389
        return NilNode;
51✔
390
    }
×
391

392
    const Node& getListNode()
1,087✔
393
    {
1,087✔
394
        static const Node ListNode(NodeType::Symbol, "list");
1,087✔
395
        return ListNode;
1,087✔
396
    }
×
397

398
    bool operator==(const Node& A, const Node& B)
414✔
399
    {
414✔
400
        if (A.m_type != B.m_type)  // should have the same types
414✔
401
            return false;
30✔
402

403
        if (A.m_type != NodeType::List)
384✔
404
            return A.m_value == B.m_value;
384✔
405
        return false;
×
406
    }
414✔
407

408
    bool operator<(const Node& A, const Node& B)
58✔
409
    {
58✔
410
        if (A.nodeType() != B.nodeType())
58✔
411
            return (static_cast<int>(A.nodeType()) - static_cast<int>(B.nodeType())) < 0;
18✔
412

413
        switch (A.nodeType())
40✔
414
        {
40✔
415
            case NodeType::Number:
416
                [[fallthrough]];
417
            case NodeType::Symbol:
418
                [[fallthrough]];
419
            case NodeType::String:
420
                return A.m_value < B.m_value;
40✔
421

422
            default:
423
                return false;
×
424
        }
425
    }
58✔
426
}
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