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

ArkScript-lang / Ark / 20065764942

09 Dec 2025 01:49PM UTC coverage: 90.564% (+0.008%) from 90.556%
20065764942

push

github

SuperFola
chore(tests): adding IR generation tests for arg attributes

8043 of 8881 relevant lines covered (90.56%)

180911.91 hits per line

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

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

3
#include <string>
4
#include <vector>
5
#include <ranges>
6
#include <Ark/Error/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) :
13✔
14
    m_welder(debug, lib_env, features)
13✔
15
{}
13✔
16

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

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

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

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

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

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

57
        case NodeType::Spread:
58
        {
59
            json += fmt::format(
6✔
60
                R"({{"type": "Spread", "name": "{}"}})",
6✔
61
                node.string());
6✔
62
            break;
6✔
63
        }
5✔
64

65
        case NodeType::Capture:
66
        {
67
            json += fmt::format(
5✔
68
                R"({{"type": "Capture", "name": "{}"}})",
5✔
69
                node.string());
5✔
70
            break;
5✔
71
        }
4✔
72

73
        case NodeType::Field:
74
        {
75
            json += R"({"type": "Field", "children": )";
4✔
76
            json += toJsonList(node, 0) + "}";
4✔
77
            break;
4✔
78
        }
52✔
79

80
        case NodeType::String:
81
        {
82
            json += fmt::format(
52✔
83
                R"({{"type": "String", "value": "{}"}})",
52✔
84
                node.string());
52✔
85
            break;
52✔
86
        }
79✔
87

88
        case NodeType::Number:
89
        {
90
            json += fmt::format(
79✔
91
                R"({{"type": "Number", "value": {}}})",
79✔
92
                node.number());
79✔
93
            break;
79✔
94
        }
221✔
95

96
        case NodeType::List:
97
        {
98
            if (!node.constList().empty() && node.constList()[0].nodeType() == NodeType::Keyword)
221✔
99
            {
100
                Node keyword = node.constList()[0];
95✔
101
                switch (keyword.keyword())
95✔
102
                {
19✔
103
                    case Keyword::Fun:
104
                    {
105
                        // (fun (args) (body))
106
                        std::string args;
19✔
107
                        Node args_node = node.constList()[1];
19✔
108
                        if (args_node.nodeType() == NodeType::List)
19✔
109
                        {
110
                            args = "[";
18✔
111
                            for (std::size_t i = 0, end = args_node.constList().size(); i < end; ++i)
45✔
112
                            {
113
                                args += _compile(args_node.constList()[i]);
27✔
114
                                if (end > 1 && i != end - 1)
27✔
115
                                    args += ", ";
10✔
116
                            }
27✔
117
                            args += "]";
18✔
118
                        }
18✔
119
                        else
120
                            args = _compile(args_node);
1✔
121

122
                        json += fmt::format(
38✔
123
                            R"({{"type": "Fun", "args": {}, "body": {}}})",
19✔
124
                            args, _compile(node.constList()[2]));
19✔
125
                        break;
126
                    }
40✔
127

128
                    case Keyword::Let:
129
                    {
130
                        // (let name value)
131
                        json += fmt::format(
42✔
132
                            R"({{"type": "Let", "name": {}, "value": {}}})",
21✔
133
                            _compile(node.constList()[1]), _compile(node.constList()[2]));
21✔
134
                        break;
21✔
135
                    }
3✔
136

137
                    case Keyword::Mut:
138
                    {
139
                        // (mut name value)
140
                        json += fmt::format(
6✔
141
                            R"({{"type": "Mut", "name": {}, "value": {}}})",
3✔
142
                            _compile(node.constList()[1]), _compile(node.constList()[2]));
3✔
143
                        break;
3✔
144
                    }
5✔
145

146
                    case Keyword::Set:
147
                    {
148
                        // (set name value)
149
                        json += fmt::format(
10✔
150
                            R"({{"type": "Set", "name": {}, "value": {}}})",
5✔
151
                            _compile(node.constList()[1]), _compile(node.constList()[2]));
5✔
152
                        break;
5✔
153
                    }
7✔
154

155
                    case Keyword::If:
156
                    {
157
                        // (if condition then else)
158
                        if (node.constList().size() == 4)
7✔
159
                            json += fmt::format(
12✔
160
                                R"({{"type": "If", "condition": {}, "then": {}, "else": {}}})",
6✔
161
                                _compile(node.constList()[1]), _compile(node.constList()[2]), _compile(node.constList()[3]));
6✔
162
                        else
163
                            json += fmt::format(
2✔
164
                                R"({{"type": "If", "condition": {}, "then": {}}})",
1✔
165
                                _compile(node.constList()[1]), _compile(node.constList()[2]));
1✔
166
                        break;
7✔
167
                    }
2✔
168

169
                    case Keyword::While:
170
                    {
171
                        // (while condition body)
172
                        json += fmt::format(
4✔
173
                            R"({{"type": "While", "condition": {}, "body": {}}})",
2✔
174
                            _compile(node.constList()[1]), _compile(node.constList()[2]));
2✔
175
                        break;
2✔
176
                    }
32✔
177

178
                    case Keyword::Begin:
179
                    {
180
                        // (begin body)
181
                        json += R"({"type": "Begin", "children": )";
32✔
182
                        json += toJsonList(node, 1) + "}";
32✔
183
                        break;
32✔
184
                    }
5✔
185

186
                    case Keyword::Import:
187
                    {
188
                        // (import pkg.value)
189
                        // (import pkg.value :sym)
190
                        // (import pkg.value:*)
191
                        std::string package = node.constList()[1].constList().front().string();
5✔
192
                        for (const auto& sym : node.constList()[1].constList() | std::views::drop(1))
10✔
193
                            package += "." + sym.string();
5✔
194

195
                        bool is_glob = node.constList()[2].nodeType() == NodeType::Symbol && node.constList()[2].string() == "*";
5✔
196
                        std::vector<std::string> syms;
5✔
197
                        if (node.constList()[2].nodeType() == NodeType::List)
5✔
198
                            std::ranges::transform(
8✔
199
                                node.constList()[2].constList(),
4✔
200
                                std::back_inserter(syms),
4✔
201
                                [](const auto& sym) {
2✔
202
                                    return fmt::format("{:?}", sym.string());
2✔
203
                                });
204

205
                        json += fmt::format(
10✔
206
                            R"({{"type": "Import", "package": "{}", "glob": {}, "symbols": [{}]}})",
5✔
207
                            package,
208
                            is_glob,
209
                            fmt::join(syms, ", "));
5✔
210
                        break;
211
                    }
6✔
212

213
                    case Keyword::Del:
214
                    {
215
                        // (del value)
216
                        json += fmt::format(
2✔
217
                            R"({{"type": "Del", "value": {}}})",
1✔
218
                            _compile(node.constList()[1]));
1✔
219
                        break;
1✔
220
                    }
221
                }
95✔
222
            }
95✔
223
            else if (node.constList().size() > 1 && node.constList()[0].nodeType() == NodeType::Symbol)
126✔
224
            {
225
                // (foo bar 1)
226
                json += fmt::format(
242✔
227
                    R"({{"type": "FunctionCall", "name": {}, "args": {}}})",
121✔
228
                    _compile(node.constList()[0]),
121✔
229
                    toJsonList(node, 1));
121✔
230
            }
121✔
231
            else
232
                json += toJsonList(node, 0);
5✔
233

234
            break;
221✔
235
        }
18✔
236

237
        case NodeType::Macro:
238
        {
239
            if (const auto& first = node.constList()[0]; first.nodeType() == NodeType::Symbol)
36✔
240
            {
241
                json += fmt::format(
28✔
242
                    R"({{"type": "Macro", "name": {}, )",
14✔
243
                    _compile(node.constList()[0]));
14✔
244
                if (node.constList().size() == 2)
14✔
245
                    json += fmt::format(R"("value": {}}})", _compile(node.constList()[1]));
7✔
246
                else
247
                    json += fmt::format(
14✔
248
                        R"("args": {}, "body": {}}})",
7✔
249
                        toJsonList(node.constList()[1], 0),
7✔
250
                        _compile(node.constList()[2]));
7✔
251
            }
14✔
252
            else if (first.nodeType() == NodeType::Keyword)
4✔
253
            {
254
                if (first.keyword() == Keyword::If)
4✔
255
                    json += fmt::format(
8✔
256
                        R"({{"type": "MacroCondition", "condition": {}, "then": {}, "else": {}}})",
4✔
257
                        _compile(node.constList()[1]),
4✔
258
                        _compile(node.constList()[2]),
4✔
259
                        node.constList().size() == 4 ? _compile(node.constList()[3]) : R"({"type": "Symbol", "name": "nil"})");
4✔
260
            }
4✔
261
            break;
18✔
262
        }
×
263

264
        case NodeType::Unused:
265
            break;
×
266

267
        default:
268
            throw Ark::Error(fmt::format(
×
269
                "Not handled NodeType::{} ({} at {}:{}), please report this error on GitHub",
×
270
                nodeTypes[static_cast<std::size_t>(node.nodeType())].data(),
×
271
                node.filename(),
×
272
                node.position().start.line,
×
273
                node.position().start.column));
×
274
    }
686✔
275
    return json;
686✔
276
}
686✔
277

278
std::string JsonCompiler::toJsonList(const Node& node, const std::size_t start)
169✔
279
{
169✔
280
    std::vector<std::string> json;
169✔
281
    for (std::size_t i = start, end = node.constList().size(); i < end; ++i)
556✔
282
    {
283
        if (node.constList()[i].nodeType() != NodeType::Unused)
387✔
284
            json.push_back(_compile(node.constList()[i]));
383✔
285
    }
387✔
286
    return fmt::format("[{}]", fmt::join(json, ", "));
169✔
287
}
169✔
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