• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

ArkScript-lang / Ark / 17100280902

20 Aug 2025 01:45PM UTC coverage: 87.348% (-0.08%) from 87.426%
17100280902

push

github

SuperFola
feat(tests): adding parser tests to improve coverage

4 of 4 new or added lines in 1 file covered. (100.0%)

171 existing lines in 10 files now uncovered.

7553 of 8647 relevant lines covered (87.35%)

129750.62 hits per line

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

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

4
#include <Ark/Error/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) :
125,942✔
12
        m_type(node_type), m_value(value), m_pos()
62,971✔
13
    {}
62,971✔
14

15
    Node::Node(const NodeType node_type) :
238,942✔
16
        m_type(node_type), m_pos()
477,884✔
17
    {
238,942✔
18
        if (m_type == NodeType::List || m_type == NodeType::Macro || m_type == NodeType::Field)
238,942✔
19
            m_value = std::vector<Node>();
238,628✔
20
    }
238,942✔
21

22
    Node::Node(double value) :
70,573✔
23
        m_type(NodeType::Number), m_value(value), m_pos()
141,146✔
24
    {}
141,146✔
25

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

30
    Node::Node(Keyword value) :
12,625✔
31
        m_type(NodeType::Keyword), m_value(value), m_pos()
25,250✔
32
    {}
25,250✔
33

34
    Node::Node(const Namespace& namespace_) :
250✔
35
        m_type(NodeType::Namespace), m_value(namespace_), m_pos()
125✔
36
    {}
125✔
37

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

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

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

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

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

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

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

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

78
    NodeType Node::nodeType() const noexcept
4,023,800✔
79
    {
4,023,800✔
80
        return m_type;
4,023,800✔
81
    }
82

83
    bool Node::isListLike() const noexcept
14,463✔
84
    {
14,463✔
85
        return m_type == NodeType::List || m_type == NodeType::Macro;
14,463✔
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,979✔
94
    {
5,979✔
95
        return m_type == NodeType::List &&
10,506✔
96
            !constList().empty() &&
4,527✔
97
            constList()[0].nodeType() == NodeType::Keyword &&
6,677✔
98
            constList()[0].keyword() == Keyword::Fun;
2,150✔
99
    }
100

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

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

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

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

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

127
    void Node::setPositionFrom(const Node& source) noexcept
161✔
128
    {
161✔
129
        m_filename = source.m_filename;
161✔
130
        m_pos = source.m_pos;
161✔
131
    }
161✔
132

133
    Node& Node::attachNearestCommentBefore(const std::string& comment)
158,450✔
134
    {
158,450✔
135
        m_comment = comment;
158,450✔
136
        return *this;
158,450✔
137
    }
138

139
    Node& Node::attachCommentAfter(const std::string& comment)
38,541✔
140
    {
38,541✔
141
        if (!m_after_comment.empty())
38,541✔
142
            m_after_comment += "\n";
37✔
143
        m_after_comment += comment;
38,541✔
144
        if (!m_after_comment.empty() && m_after_comment.back() == '\n')
38,541✔
145
            m_after_comment.pop_back();
107✔
146
        return *this;
38,541✔
147
    }
148

149
    void Node::setAltSyntax(const bool toggle)
2,760✔
150
    {
2,760✔
151
        m_alt_syntax = toggle;
2,760✔
152
    }
2,760✔
153

154
    void Node::setFunctionKind(const bool anonymous)
2,127✔
155
    {
2,127✔
156
        m_is_anonymous_function = anonymous;
2,127✔
157
    }
2,127✔
158

159
    bool Node::isAnonymousFunction() const noexcept
4,779✔
160
    {
4,779✔
161
        return m_is_anonymous_function;
4,779✔
162
    }
163

UNCOV
164
    bool Node::isAltSyntax() const
×
UNCOV
165
    {
×
UNCOV
166
        return m_alt_syntax;
×
167
    }
168

169
    FileSpan Node::position() const noexcept
107,247✔
170
    {
107,247✔
171
        return m_pos;
107,247✔
172
    }
173

174
    const std::string& Node::filename() const noexcept
49,813✔
175
    {
49,813✔
176
        return m_filename;
49,813✔
177
    }
178

179
    const std::string& Node::comment() const noexcept
15,419✔
180
    {
15,419✔
181
        return m_comment;
15,419✔
182
    }
183

184
    const std::string& Node::commentAfter() const noexcept
2,266✔
185
    {
2,266✔
186
        return m_after_comment;
2,266✔
187
    }
188

189
    std::string Node::repr() const noexcept
15,966✔
190
    {
15,966✔
191
        std::string data;
15,966✔
192
        switch (m_type)
15,966✔
193
        {
13,123✔
194
            case NodeType::Symbol:
195
                data += string();
13,123✔
196
                break;
13,123✔
197

198
            case NodeType::Capture:
UNCOV
199
                data += "&" + string();
×
200
                break;
60✔
201

202
            case NodeType::Keyword:
203
                data += keywords[static_cast<std::size_t>(keyword())];
60✔
204
                break;
480✔
205

206
            case NodeType::String:
207
                data += "\"" + string() + "\"";
420✔
208
                break;
1,562✔
209

210
            case NodeType::Number:
211
                data += fmt::format("{}", number());
1,142✔
212
                break;
2,217✔
213

214
            case NodeType::List:
215
                if (m_alt_syntax)
1,075✔
216
                {
217
                    const auto first = constList().front();
256✔
218
                    char open = 0;
256✔
219
                    if (first.nodeType() == NodeType::Keyword && first.keyword() == Keyword::Begin)
256✔
220
                        open = '{';
3✔
221
                    else if (first.nodeType() == NodeType::Symbol && first.string() == "list")
253✔
222
                        open = '[';
253✔
223
                    else
UNCOV
224
                        assert(false && "Alt syntax nodes can only be begin or list");
×
225

226
                    data += open;
256✔
227
                    for (std::size_t i = 1, end = constList().size(); i < end; ++i)
795✔
228
                    {
229
                        data += constList()[i].repr();
539✔
230
                        if (i < end - 1)
539✔
231
                            data += " ";
347✔
232
                    }
539✔
233

234
                    if (open == '{')
256✔
235
                        data += "}";
3✔
236
                    else if (open == '[')
253✔
237
                        data += "]";
253✔
238
                }
256✔
239
                else
240
                {
241
                    data += "(";
819✔
242
                    for (std::size_t i = 0, end = constList().size(); i < end; ++i)
2,984✔
243
                    {
244
                        data += constList()[i].repr();
2,165✔
245
                        if (i < end - 1)
2,165✔
246
                            data += " ";
1,350✔
247
                    }
2,165✔
248
                    data += ")";
819✔
249
                }
250
                break;
1,204✔
251

252
            case NodeType::Field:
253
                for (std::size_t i = 0, end = constList().size(); i < end; ++i)
401✔
254
                {
255
                    data += constList()[i].repr();
272✔
256
                    if (i < end - 1)
272✔
257
                        data += ".";
385,485✔
258
                }
272✔
259
                break;
145✔
260

261
            case NodeType::Macro:
262
                data += "(macro ";
16✔
263
                for (std::size_t i = 0, end = constList().size(); i < end; ++i)
385,418✔
264
                {
385,342✔
265
                    data += constList()[i].repr();
60✔
266
                    if (i < end - 1)
60✔
267
                        data += " ";
44✔
268
                }
60✔
269
                data += ")";
16✔
270
                break;
17✔
271

272
            case NodeType::Spread:
273
                data += "..." + string();
1✔
274
                break;
1✔
275

276
            // namespace node should not have a representation as it is purely internal,
277
            // and it can't be exploited by macros (unless you try passing an import node
278
            // to a macro, which should not happen?)
279
            case NodeType::Namespace:
UNCOV
280
                data += constArkNamespace().ast->repr();
×
UNCOV
281
                break;
×
282

283
            case NodeType::Unused:
UNCOV
284
                break;
×
285
        }
15,966✔
286
        return data;
15,966✔
287
    }
15,966✔
288

289
    std::ostream& Node::debugPrint(std::ostream& os) const noexcept
469✔
290
    {
469✔
291
        switch (m_type)
469✔
292
        {
143✔
293
            case NodeType::Symbol:
294
                os << "Symbol:" << string();
143✔
295
                break;
149✔
296

297
            case NodeType::Capture:
298
                os << "Capture:" << string();
6✔
299
                break;
84✔
300

301
            case NodeType::Keyword:
302
                os << "Keyword:";
78✔
303
                switch (keyword())
78✔
304
                {
14✔
305
                    case Keyword::Fun: os << "Fun"; break;
32✔
306
                    case Keyword::Let: os << "Let"; break;
21✔
307
                    case Keyword::Mut: os << "Mut"; break;
4✔
308
                    case Keyword::Set: os << "Set"; break;
16✔
309
                    case Keyword::If: os << "If"; break;
21✔
310
                    case Keyword::While: os << "While"; break;
15✔
311
                    case Keyword::Begin: os << "Begin"; break;
17✔
312
                    case Keyword::Import: os << "Import"; break;
12✔
313
                    case Keyword::Del: os << "Del"; break;
4✔
314
                }
78✔
315
                break;
86✔
316

317
            case NodeType::String:
318
                os << "String:" << string();
8✔
319
                break;
83✔
320

321
            case NodeType::Number:
322
                os << "Number:" << number();
75✔
323
                break;
215✔
324

325
            case NodeType::List:
326
                os << "( ";
140✔
327
                for (const auto& i : constList())
482✔
328
                    i.debugPrint(os) << " ";
342✔
329
                os << ")";
140✔
330
                break;
149✔
331

332
            case NodeType::Field:
333
                os << "( Field ";
9✔
334
                for (const auto& i : constList())
30✔
335
                    i.debugPrint(os) << " ";
21✔
336
                os << ")";
9✔
337
                break;
17✔
338

339
            case NodeType::Macro:
340
                os << "( Macro ";
8✔
341
                for (const auto& i : constList())
31✔
342
                    i.debugPrint(os) << " ";
23✔
343
                os << ")";
8✔
344
                break;
10✔
345

346
            case NodeType::Spread:
347
                os << "Spread:" << string();
2✔
348
                break;
2✔
349

350
            case NodeType::Namespace:
351
            {
UNCOV
352
                const auto details = constArkNamespace();
×
UNCOV
353
                os << "( Namespace:" << details.name << " ";
×
UNCOV
354
                details.ast->debugPrint(os) << " )";
×
355
                break;
UNCOV
356
            }
×
357

358
            case NodeType::Unused:
UNCOV
359
                break;
×
360
        }
469✔
361
        return os;
469✔
362
    }
363

364
    const Node& getTrueNode()
77✔
365
    {
77✔
366
        static const Node TrueNode(NodeType::Symbol, "true");
77✔
367
        return TrueNode;
77✔
UNCOV
368
    }
×
369

370
    const Node& getFalseNode()
59✔
371
    {
59✔
372
        static const Node FalseNode(NodeType::Symbol, "false");
59✔
373
        return FalseNode;
59✔
UNCOV
374
    }
×
375

376
    const Node& getNilNode()
51✔
377
    {
51✔
378
        static const Node NilNode(NodeType::Symbol, "nil");
51✔
379
        return NilNode;
51✔
UNCOV
380
    }
×
381

382
    const Node& getListNode()
1,120✔
383
    {
1,120✔
384
        static const Node ListNode(NodeType::Symbol, "list");
1,120✔
385
        return ListNode;
1,120✔
UNCOV
386
    }
×
387

388
    bool operator==(const Node& A, const Node& B)
414✔
389
    {
414✔
390
        if (A.m_type != B.m_type)  // should have the same types
414✔
391
            return false;
30✔
392

393
        if (A.m_type != NodeType::List)
384✔
394
            return A.m_value == B.m_value;
384✔
UNCOV
395
        return false;
×
396
    }
414✔
397

398
    bool operator<(const Node& A, const Node& B)
58✔
399
    {
58✔
400
        if (A.nodeType() != B.nodeType())
58✔
401
            return (static_cast<int>(A.nodeType()) - static_cast<int>(B.nodeType())) < 0;
18✔
402

403
        switch (A.nodeType())
40✔
404
        {
40✔
405
            case NodeType::Number:
406
                [[fallthrough]];
407
            case NodeType::Symbol:
408
                [[fallthrough]];
409
            case NodeType::String:
410
                return A.m_value < B.m_value;
40✔
411

412
            default:
UNCOV
413
                return false;
×
414
        }
415
    }
58✔
416
}
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