• 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 · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc