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

ArkScript-lang / Ark / 20074477466

09 Dec 2025 06:35PM UTC coverage: 90.587% (+0.02%) from 90.564%
20074477466

push

github

SuperFola
fix: use const string instead of constexpr string, otherwise compilers go bonkers about address of constexpr changing

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

16 existing lines in 2 files now uncovered.

8074 of 8913 relevant lines covered (90.59%)

360683.37 hits per line

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

90.51
/src/arkreactor/TypeChecker.cpp
1
#include <Ark/TypeChecker.hpp>
2

3
#include <limits>
4
#include <algorithm>
5
#include <fmt/core.h>
6
#include <fmt/args.h>
7
#include <fmt/color.h>
8
#include <fmt/ostream.h>
9

10
#include <Ark/VM/VM.hpp>
11

12
namespace Ark::types
13
{
14
    std::string typeListToString(const std::vector<ValueType>& types)
352 ✔
15
    {
352 ✔
16
        if (types.size() == 1 && types[0] == ValueType::Any)
352 ✔
17
            return "any";
36 ✔
18

19
        std::string acc;
316 ✔
20

21
        for (std::size_t i = 0, end = types.size(); i < end; ++i)
642 ✔
22
        {
23
            if (i > 0)
326 ✔
24
                acc += ", ";
10 ✔
25
            if (i + 1 == end && types.size() > 1)
326 ✔
26
                acc += "or ";
6 ✔
27
            acc += std::to_string(types[i]);
326 ✔
28
        }
326 ✔
29
        return acc;
316 ✔
30
    }
668 ✔
31

32
    void displayContract(const std::string_view& funcname, const Contract& contract, const std::vector<Value>& args, VM& vm, std::ostream& os, const bool colorize)
212 ✔
33
    {
212 ✔
34
        const std::string checkmark = "✓";
212 ✔
35
        const std::string crossmark = "×";
212 ✔
36

37
        auto displayArg = [colorize, &os](const Typedef& td, const bool correct) {
564 ✔
38
            const std::string arg_str = typeListToString(td.types);
352 ✔
39

40
            fmt::dynamic_format_arg_store<fmt::format_context> store;
352 ✔
41
            store.push_back(td.variadic ? "variadic " : "");
352 ✔
42
            if (colorize)
352 ✔
UNCOV
43
                store.push_back(
×
UNCOV
44
                    fmt::styled(
×
UNCOV
45
                        td.name,
×
UNCOV
46
                        correct
×
UNCOV
47
                            ? fmt::fg(fmt::color::green)
×
UNCOV
48
                            : fmt::fg(fmt::color::magenta)));
×
49
            else
50
                store.push_back(td.name);
352 ✔
51
            store.push_back(arg_str);
352 ✔
52

53
            fmt::vprint(os, "  → {}`{}' (expected {})", store);
352 ✔
54
        };
352 ✔
55

56
        fmt::print(os, "Signature\n  ↳ ({}", funcname);
212 ✔
57
        for (const Typedef& td : contract.arguments)
564 ✔
58
            fmt::print(os, " {}", td.name);
352 ✔
59
        fmt::print(os, ")\nArguments\n");
212 ✔
60

61
        for (std::size_t i = 0, end = contract.arguments.size(); i < end; ++i)
564 ✔
62
        {
63
            const Typedef& td = contract.arguments[i];
352 ✔
64

65
            if (td.variadic && i < args.size())
352 ✔
66
            {
67
                // variadic argument in contract and enough provided arguments
68
                std::size_t bad_type_count = 0;
6 ✔
69
                std::string formatted_varargs;
6 ✔
70
                for (std::size_t j = i, args_end = args.size(); j < args_end; ++j)
14 ✔
71
                {
72
                    bool type_ok = true;
8 ✔
73
                    if (td.types[0] != ValueType::Any && std::ranges::find(td.types, args[j].valueType()) == td.types.end())
8 ✔
74
                    {
75
                        bad_type_count++;
2 ✔
76
                        type_ok = false;
2 ✔
77
                    }
2 ✔
78
                    formatted_varargs += fmt::format(
16 ✔
79
                        "\n    {} ({}) {}",
8 ✔
80
                        args[j].toString(vm),
8 ✔
81
                        std::to_string(args[j].valueType()),
8 ✔
82
                        type_ok ? checkmark : crossmark);
8 ✔
83
                }
8 ✔
84

85
                if (bad_type_count)
6 ✔
86
                {
87
                    displayArg(td, /* correct= */ false);
2 ✔
88

89
                    fmt::dynamic_format_arg_store<fmt::format_context> store;
2 ✔
90
                    if (colorize)
2 ✔
UNCOV
91
                        store.push_back(fmt::styled(bad_type_count, fmt::fg(fmt::color::red)));
×
92
                    else
93
                        store.push_back(bad_type_count);
2 ✔
94
                    store.push_back(bad_type_count > 1 ? "s" : "");
2 ✔
95
                    store.push_back(formatted_varargs);
2 ✔
96

97
                    fmt::vprint(os, ": {} argument{} do not match:{}", store);
2 ✔
98
                }
2 ✔
99
                else
100
                    displayArg(td, /* correct= */ true);
4 ✔
101
            }
6 ✔
102
            else
103
            {
104
                // provided argument but wrong type
105
                if (i < args.size() && td.types[0] != ValueType::Any && std::ranges::find(td.types, args[i].valueType()) == td.types.end())
346 ✔
106
                {
107
                    displayArg(td, /* correct= */ false);
226 ✔
108
                    const auto type = std::to_string(args[i].valueType());
226 ✔
109

110
                    fmt::dynamic_format_arg_store<fmt::format_context> store;
226 ✔
111
                    store.push_back(args[i].toString(vm));
226 ✔
112
                    if (colorize)
226 ✔
UNCOV
113
                        store.push_back(fmt::styled(type, fmt::fg(fmt::color::red)));
×
114
                    else
115
                        store.push_back(type);
226 ✔
116
                    fmt::vprint(os, ", got {} ({})", store);
226 ✔
117
                }
226 ✔
118
                // non-provided argument
119
                else if (i >= args.size())
120 ✔
120
                {
121
                    displayArg(td, /* correct= */ false);
44 ✔
122
                    if (colorize)
44 ✔
UNCOV
123
                        fmt::print(os, "{}", fmt::styled(" was not provided", fmt::fg(fmt::color::red)));
×
124
                    else
125
                        fmt::print(os, " was not provided");
44 ✔
126
                }
44 ✔
127
                else
128
                {
129
                    displayArg(td, /* correct= */ true);
76 ✔
130
                    fmt::print(os, " {}", checkmark);
76 ✔
131
                }
132
            }
133
            fmt::print(os, "\n");
352 ✔
134
        }
352 ✔
135

136
        if (contract.arguments.size() < args.size())
212 ✔
137
        {
138
            fmt::print(os, "  → unexpected additional args: ");
4 ✔
139
            for (std::size_t i = contract.arguments.size(), end = args.size(); i < end; ++i)
8 ✔
140
            {
141
                fmt::print(os, "{} ({})", args[i].toString(vm), std::to_string(args[i].valueType()));
4 ✔
142
                if (i + 1 != end)
4 ✔
UNCOV
143
                    fmt::print(os, ", ");
×
144
            }
4 ✔
145
            fmt::print(os, "\n");
4 ✔
146
        }
4 ✔
147
    }
212 ✔
148

149
    void generateError(const std::string_view& funcname, const std::vector<Contract>& contracts, const std::vector<Value>& args, VM& vm, std::ostream& os, bool colorize)
182 ✔
150
    {
182 ✔
151
        {
152
            fmt::dynamic_format_arg_store<fmt::format_context> store;
182 ✔
153
            if (colorize)
182 ✔
UNCOV
154
                store.push_back(fmt::styled(funcname, fmt::fg(fmt::color::cyan)));
×
155
            else
156
                store.push_back(funcname);
182 ✔
157
            fmt::vprint(os, "Function {} expected ", store);
182 ✔
158
        }
182 ✔
159

160
        std::vector<Value> sanitizedArgs;
182 ✔
161
        std::ranges::copy_if(args, std::back_inserter(sanitizedArgs), [](const Value& value) -> bool {
448 ✔
162
            return value.valueType() != ValueType::Undefined;
266 ✔
163
        });
164

165
        // get expected arguments count
166
        std::size_t min_argc = std::numeric_limits<std::size_t>::max(), max_argc = 0;
182 ✔
167
        bool variadic = false;
182 ✔
168
        for (const auto& [arguments] : contracts)
1,400 ✔
169
        {
170
            if (arguments.size() < min_argc)
212 ✔
171
                min_argc = arguments.size();
184 ✔
172
            if (arguments.size() > max_argc)
212 ✔
173
                max_argc = arguments.size();
186 ✔
174

175
            if (!arguments.empty() && arguments.back().variadic)
212 ✔
176
                variadic = true;
10 ✔
177
        }
212 ✔
178

179
        bool correct_argcount = true;
182 ✔
180

181
        if (min_argc != max_argc)
182 ✔
182
        {
183
            fmt::dynamic_format_arg_store<fmt::format_context> store;
6 ✔
184
            if (colorize)
6 ✔
UNCOV
185
                store.push_back(fmt::styled(min_argc, fmt::fg(fmt::color::yellow)));
×
186
            else
187
                store.push_back(min_argc);
6 ✔
188
            store.push_back(min_argc > 1 ? "s" : "");
6 ✔
189
            if (colorize)
6 ✔
UNCOV
190
                store.push_back(fmt::styled(max_argc, fmt::fg(fmt::color::yellow)));
×
191
            else
192
                store.push_back(max_argc);
6 ✔
193
            store.push_back(max_argc > 1 ? "s" : "");
6 ✔
194

195
            fmt::vprint(os, "between {} argument{} and {} argument{}", store);
6 ✔
196

197
            if (sanitizedArgs.size() < min_argc || sanitizedArgs.size() > max_argc)
6 ✔
198
                correct_argcount = false;
4 ✔
199
        }
6 ✔
200
        else
201
        {
202
            fmt::dynamic_format_arg_store<fmt::format_context> store;
176 ✔
203
            store.push_back(variadic ? "at least " : "");
176 ✔
204
            if (colorize)
176 ✔
UNCOV
205
                store.push_back(fmt::styled(min_argc, fmt::fg(fmt::color::yellow)));
×
206
            else
207
                store.push_back(min_argc);
176 ✔
208
            store.push_back(min_argc > 1 ? "s" : "");
176 ✔
209

210
            fmt::vprint(os, "{}{} argument{}", store);
176 ✔
211

212
            if (sanitizedArgs.size() != min_argc)
176 ✔
213
                correct_argcount = false;
26 ✔
214
        }
176 ✔
215

216
        if (!correct_argcount || variadic)
182 ✔
217
        {
218
            std::string preposition = (variadic && args.size() >= min_argc) ? "and" : "but";
36 ✔
219
            if (colorize)
36 ✔
UNCOV
220
                fmt::print(os, " {} got {}", preposition, fmt::styled(sanitizedArgs.size(), fmt::fg(fmt::color::red)));
×
221
            else
222
                fmt::print(os, " {} got {}", preposition, sanitizedArgs.size());
36 ✔
223
        }
36 ✔
224

225
        fmt::print(os, "\nCall\n  ↳ ({}", funcname);
182 ✔
226
        for (const Value& arg : args)
448 ✔
227
            fmt::print(os, " {}", arg.toString(vm));
266 ✔
228
        fmt::print(os, ")\n");
182 ✔
229

230
        displayContract(funcname, contracts[0], sanitizedArgs, vm, os, colorize);
182 ✔
231
        for (std::size_t i = 1, end = contracts.size(); i < end; ++i)
212 ✔
232
        {
233
            fmt::print(os, "\nAlternative {}:\n", i + 1);
30 ✔
234
            displayContract(funcname, contracts[i], sanitizedArgs, vm, os, colorize);
30 ✔
235
        }
30 ✔
236
    }
182 ✔
237
}
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