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

ArkScript-lang / Ark / 14823373998

04 May 2025 05:03PM UTC coverage: 86.442% (+0.03%) from 86.409%
14823373998

push

github

SuperFola
fix: change the color of the function name inside runtime typechecking errors from blue to cyan to be easier to read inside dark terminals

0 of 1 new or added line in 1 file covered. (0.0%)

195 existing lines in 22 files now uncovered.

6835 of 7907 relevant lines covered (86.44%)

79668.53 hits per line

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

93.41
/src/arkscript/JsonCompiler.cpp
1
#include <CLI/JsonCompiler.hpp>
2

3
#include <string>
4
#include <vector>
5
#include <ranges>
6
#include <Ark/Exceptions.hpp>
7

8
#include <fmt/ranges.h>
9
#include <fmt/format.h>
10

11
using namespace Ark::internal;
12

13
JsonCompiler::JsonCompiler(const unsigned debug, const std::vector<std::filesystem::path>& lib_env, const uint16_t features) :
11 ✔
14
    m_welder(debug, lib_env, features)
11 ✔
15
{}
11 ✔
16

17
void JsonCompiler::feed(const std::string& filename)
11 ✔
18
{
11 ✔
19
    m_welder.computeASTFromFile(filename);
11 ✔
20
}
11 ✔
21

22
std::string JsonCompiler::compile()
11 ✔
23
{
11 ✔
24
    return _compile(m_welder.ast());
11 ✔
25
}
26

27
std::string JsonCompiler::_compile(const Node& node)
667 ✔
28
{
667 ✔
29
    std::string json;
667 ✔
30

31
    switch (node.nodeType())
667 ✔
32
    {
292 ✔
33
        case NodeType::Symbol:
34
        {
35
            json += fmt::format(
292 ✔
36
                R"({{"type": "Symbol", "name": "{}"}})",
292 ✔
37
                node.string());
292 ✔
38
            break;
292 ✔
39
        }
6 ✔
40

41
        case NodeType::Spread:
42
        {
43
            json += fmt::format(
6 ✔
44
                R"({{"type": "Spread", "name": "{}"}})",
6 ✔
45
                node.string());
6 ✔
46
            break;
6 ✔
47
        }
5 ✔
48

49
        case NodeType::Capture:
50
        {
51
            json += fmt::format(
5 ✔
52
                R"({{"type": "Capture", "name": "{}"}})",
5 ✔
53
                node.string());
5 ✔
54
            break;
5 ✔
55
        }
4 ✔
56

57
        case NodeType::Field:
58
        {
59
            json += R"({"type": "Field", "children": )";
4 ✔
60
            json += toJsonList(node, 0) + "}";
4 ✔
61
            break;
4 ✔
62
        }
52 ✔
63

64
        case NodeType::String:
65
        {
66
            json += fmt::format(
52 ✔
67
                R"({{"type": "String", "value": "{}"}})",
52 ✔
68
                node.string());
52 ✔
69
            break;
52 ✔
70
        }
76 ✔
71

72
        case NodeType::Number:
73
        {
74
            json += fmt::format(
76 ✔
75
                R"({{"type": "Number", "value": {}}})",
76 ✔
76
                node.number());
76 ✔
77
            break;
76 ✔
78
        }
214 ✔
79

80
        case NodeType::List:
81
        {
82
            if (!node.constList().empty() && node.constList()[0].nodeType() == NodeType::Keyword)
214 ✔
83
            {
84
                Node keyword = node.constList()[0];
89 ✔
85
                switch (keyword.keyword())
89 ✔
86
                {
18 ✔
87
                    case Keyword::Fun:
88
                    {
89
                        // (fun (args) (body))
90
                        std::string args;
18 ✔
91
                        Node args_node = node.constList()[1];
18 ✔
92
                        if (args_node.nodeType() == NodeType::List)
18 ✔
93
                        {
94
                            args = "[";
17 ✔
95
                            for (std::size_t i = 0, end = args_node.constList().size(); i < end; ++i)
41 ✔
96
                            {
97
                                args += _compile(args_node.constList()[i]);
24 ✔
98
                                if (end > 1 && i != end - 1)
24 ✔
99
                                    args += ", ";
8 ✔
100
                            }
24 ✔
101
                            args += "]";
17 ✔
102
                        }
17 ✔
103
                        else
104
                            args = _compile(args_node);
1 ✔
105

106
                        json += fmt::format(
36 ✔
107
                            R"({{"type": "Fun", "args": {}, "body": {}}})",
18 ✔
108
                            args, _compile(node.constList()[2]));
18 ✔
109
                        break;
110
                    }
39 ✔
111

112
                    case Keyword::Let:
113
                    {
114
                        // (let name value)
115
                        json += fmt::format(
42 ✔
116
                            R"({{"type": "Let", "name": {}, "value": {}}})",
21 ✔
117
                            _compile(node.constList()[1]), _compile(node.constList()[2]));
21 ✔
118
                        break;
21 ✔
119
                    }
3 ✔
120

121
                    case Keyword::Mut:
122
                    {
123
                        // (mut name value)
124
                        json += fmt::format(
6 ✔
125
                            R"({{"type": "Mut", "name": {}, "value": {}}})",
3 ✔
126
                            _compile(node.constList()[1]), _compile(node.constList()[2]));
3 ✔
127
                        break;
3 ✔
128
                    }
5 ✔
129

130
                    case Keyword::Set:
131
                    {
132
                        // (set name value)
133
                        json += fmt::format(
10 ✔
134
                            R"({{"type": "Set", "name": {}, "value": {}}})",
5 ✔
135
                            _compile(node.constList()[1]), _compile(node.constList()[2]));
5 ✔
136
                        break;
5 ✔
137
                    }
5 ✔
138

139
                    case Keyword::If:
140
                    {
141
                        // (if condition then else)
142
                        if (node.constList().size() == 4)
5 ✔
143
                            json += fmt::format(
10 ✔
144
                                R"({{"type": "If", "condition": {}, "then": {}, "else": {}}})",
5 ✔
145
                                _compile(node.constList()[1]), _compile(node.constList()[2]), _compile(node.constList()[3]));
5 ✔
146
                        else
147
                            json += fmt::format(
×
148
                                R"({{"type": "If", "condition": {}, "then": {}}})",
×
149
                                _compile(node.constList()[1]), _compile(node.constList()[2]));
×
150
                        break;
5 ✔
151
                    }
2 ✔
152

153
                    case Keyword::While:
154
                    {
155
                        // (while condition body)
156
                        json += fmt::format(
4 ✔
157
                            R"({{"type": "While", "condition": {}, "body": {}}})",
2 ✔
158
                            _compile(node.constList()[1]), _compile(node.constList()[2]));
2 ✔
159
                        break;
2 ✔
160
                    }
30 ✔
161

162
                    case Keyword::Begin:
163
                    {
164
                        // (begin body)
165
                        json += R"({"type": "Begin", "children": )";
30 ✔
166
                        json += toJsonList(node, 1) + "}";
30 ✔
167
                        break;
30 ✔
168
                    }
4 ✔
169

170
                    case Keyword::Import:
171
                    {
172
                        // (import pkg.value)
173
                        // (import pkg.value :sym)
174
                        // (import pkg.value:*)
175
                        std::string package = node.constList()[1].constList().front().string();
4 ✔
176
                        for (const auto& sym : node.constList()[1].constList() | std::views::drop(1))
8 ✔
177
                            package += "." + sym.string();
4 ✔
178

179
                        bool is_glob = node.constList()[2].nodeType() == NodeType::Symbol && node.constList()[2].string() == "*";
4 ✔
180
                        std::vector<std::string> syms;
4 ✔
181
                        if (node.constList()[2].nodeType() == NodeType::List)
4 ✔
182
                            std::ranges::transform(
6 ✔
183
                                node.constList()[2].constList(),
3 ✔
184
                                std::back_inserter(syms),
3 ✔
185
                                [](const auto& sym) {
2 ✔
186
                                    return fmt::format("{:?}", sym.string());
2 ✔
187
                                });
188

189
                        json += fmt::format(
8 ✔
190
                            R"({{"type": "Import", "package": "{}", "glob": {}, "symbols": [{}]}})",
4 ✔
191
                            package,
192
                            is_glob,
193
                            fmt::join(syms, ", "));
4 ✔
194
                        break;
195
                    }
5 ✔
196

197
                    case Keyword::Del:
198
                    {
199
                        // (del value)
200
                        json += fmt::format(
2 ✔
201
                            R"({{"type": "Del", "value": {}}})",
1 ✔
202
                            _compile(node.constList()[1]));
1 ✔
203
                        break;
1 ✔
204
                    }
205
                }
89 ✔
206
            }
89 ✔
207
            else if (node.constList().size() > 1 && node.constList()[0].nodeType() == NodeType::Symbol)
125 ✔
208
            {
209
                // (foo bar 1)
210
                json += fmt::format(
240 ✔
211
                    R"({{"type": "FunctionCall", "name": {}, "args": {}}})",
120 ✔
212
                    _compile(node.constList()[0]),
120 ✔
213
                    toJsonList(node, 1));
120 ✔
214
            }
120 ✔
215
            else
216
                json += toJsonList(node, 0);
5 ✔
217

218
            break;
214 ✔
219
        }
18 ✔
220

221
        case NodeType::Macro:
222
        {
223
            if (const auto& first = node.constList()[0]; first.nodeType() == NodeType::Symbol)
36 ✔
224
            {
225
                json += fmt::format(
28 ✔
226
                    R"({{"type": "Macro", "name": {}, )",
14 ✔
227
                    _compile(node.constList()[0]));
14 ✔
228
                if (node.constList().size() == 2)
14 ✔
229
                    json += fmt::format(R"("value": {}}})", _compile(node.constList()[1]));
7 ✔
230
                else
231
                    json += fmt::format(
14 ✔
232
                        R"("args": {}, "body": {}}})",
7 ✔
233
                        toJsonList(node.constList()[1], 0),
7 ✔
234
                        _compile(node.constList()[2]));
7 ✔
235
            }
14 ✔
236
            else if (first.nodeType() == NodeType::Keyword)
4 ✔
237
            {
238
                if (first.keyword() == Keyword::If)
4 ✔
239
                    json += fmt::format(
8 ✔
240
                        R"({{"type": "MacroCondition", "condition": {}, "then": {}, "else": {}}})",
4 ✔
241
                        _compile(node.constList()[1]),
4 ✔
242
                        _compile(node.constList()[2]),
4 ✔
243
                        node.constList().size() == 4 ? _compile(node.constList()[3]) : R"({"type": "Symbol", "name": "nil"})");
4 ✔
244
            }
4 ✔
245
            break;
18 ✔
246
        }
×
247

248
        case NodeType::Unused:
249
            break;
×
250

251
        default:
252
            throw Ark::Error(fmt::format(
×
253
                "Not handled NodeType::{} ({} at {}:{}), please report this error on GitHub",
×
254
                nodeTypes[static_cast<std::size_t>(node.nodeType())].data(),
×
UNCOV
255
                node.filename(),
×
UNCOV
256
                node.line(),
×
UNCOV
257
                node.col()));
×
258
    }
667 ✔
259
    return json;
667 ✔
260
}
667 ✔
261

262
std::string JsonCompiler::toJsonList(const Node& node, const std::size_t start)
166 ✔
263
{
166 ✔
264
    std::vector<std::string> json;
166 ✔
265
    for (std::size_t i = start, end = node.constList().size(); i < end; ++i)
546 ✔
266
    {
267
        if (node.constList()[i].nodeType() != NodeType::Unused)
380 ✔
268
            json.push_back(_compile(node.constList()[i]));
376 ✔
269
    }
380 ✔
270
    return fmt::format("[{}]", fmt::join(json, ", "));
166 ✔
271
}
166 ✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc