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

ArkScript-lang / Ark / 12320388836

13 Dec 2024 05:39PM UTC coverage: 79.237% (+1.9%) from 77.378%
12320388836

push

github

SuperFola
feat(ast optimizer): adding AST optimization tests and fixing the json compiler to accept (if cond then) and not just (if cond then else)

59 of 68 new or added lines in 3 files covered. (86.76%)

14 existing lines in 5 files now uncovered.

5667 of 7152 relevant lines covered (79.24%)

14746.86 hits per line

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

90.06
/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✔
UNCOV
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✔
UNCOV
40

×
41
        case NodeType::Spread:
UNCOV
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:
UNCOV
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

UNCOV
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

UNCOV
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
NEW
147
                            json += fmt::format(
×
NEW
148
                                R"({{"type": "If", "condition": {}, "then": {}}})",
×
NEW
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;
3✔
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
                        {
183
                            for (const auto& sym : node.constList()[2].constList())
5✔
184
                                syms.push_back('"' + sym.string() + '"');
2✔
185
                        }
3✔
186
                        json += fmt::format(
8✔
187
                            R"({{"type": "Import", "package": "{}", "glob": {}, "symbols": [{}]}})",
4✔
188
                            package,
189
                            is_glob,
190
                            fmt::join(syms, ", "));
4✔
191
                        break;
192
                    }
5✔
193

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

215
            break;
214✔
216
        }
18✔
217

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

245
        case NodeType::Unused:
NEW
246
            break;
×
247

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

259
std::string JsonCompiler::toJsonList(const Node& node, const std::size_t start)
166✔
260
{
166✔
261
    std::vector<std::string> json;
166✔
262
    for (std::size_t i = start, end = node.constList().size(); i < end; ++i)
546✔
263
    {
264
        if (node.constList()[i].nodeType() != NodeType::Unused)
380✔
265
            json.push_back(_compile(node.constList()[i]));
376✔
266
    }
380✔
267
    return fmt::format("[{}]", fmt::join(json, ", "));
166✔
268
}
166✔
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

© 2025 Coveralls, Inc