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

ArkScript-lang / Ark / 14316379818

07 Apr 2025 06:10PM UTC coverage: 80.073% (+0.7%) from 79.378%
14316379818

push

github

SuperFola
feat(tests, type checker): adding tests for the type checker error message generation (in isolation)

36 of 68 new or added lines in 2 files covered. (52.94%)

12 existing lines in 3 files now uncovered.

6128 of 7653 relevant lines covered (80.07%)

77599.75 hits per line

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

63.93
/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/Exceptions.hpp>
11

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

19
        std::string acc;
5✔
20

21
        for (std::size_t i = 0, end = types.size(); i < end; ++i)
11✔
22
        {
23
            if (i > 0)
6✔
24
                acc += ", ";
1✔
25
            acc += types_to_str[static_cast<std::size_t>(types[i])];
6✔
26
        }
6✔
27
        return acc;
5✔
28
    }
10✔
29

30
    void displayContract(const Contract& contract, const std::vector<Value>& args, std::ostream& os, const bool colorize)
4✔
31
    {
4✔
32
        auto displayArg = [colorize, &os](const Typedef& td, const bool correct) {
9✔
33
            const std::string arg_str = typeListToString(td.types);
5✔
34

35
            fmt::dynamic_format_arg_store<fmt::format_context> store;
5✔
36
            store.push_back(td.variadic ? "variadic " : "");
5✔
37
            if (colorize)
5✔
NEW
38
                store.push_back(
×
NEW
39
                    fmt::styled(
×
NEW
40
                        td.name,
×
NEW
41
                        correct
×
NEW
42
                            ? fmt::fg(fmt::color::green)
×
NEW
43
                            : fmt::fg(fmt::color::magenta)));
×
44
            else
45
                store.push_back(td.name);
5✔
46
            store.push_back(arg_str);
5✔
47

48
            fmt::vprint(os, "  -> {}{} ({})", store);
5✔
49
        };
5✔
50

51
        for (std::size_t i = 0, end = contract.arguments.size(); i < end; ++i)
9✔
52
        {
53
            const Typedef& td = contract.arguments[i];
5✔
54

55
            if (td.variadic && i < args.size())
5✔
56
            {
57
                // variadic argument in contract and enough provided arguments
58
                std::size_t bad_type = 0;
×
59
                for (std::size_t j = i, args_end = args.size(); j < args_end; ++j)
×
60
                {
61
                    if (td.types[0] != ValueType::Any && std::ranges::find(td.types, args[j].valueType()) == td.types.end())
×
62
                        bad_type++;
×
63
                }
×
64

65
                if (bad_type)
×
66
                {
NEW
67
                    displayArg(td, /* correct= */ false);
×
68

NEW
69
                    fmt::dynamic_format_arg_store<fmt::format_context> store;
×
NEW
70
                    if (colorize)
×
NEW
71
                        store.push_back(fmt::styled(bad_type, fmt::fg(fmt::color::red)));
×
72
                    else
NEW
73
                        store.push_back(bad_type);
×
NEW
74
                    store.push_back(bad_type > 1 ? "s" : "");
×
75

NEW
76
                    fmt::vprint(os, " {} argument{} do not match", store);
×
UNCOV
77
                }
×
78
                else
NEW
79
                    displayArg(td, /* correct= */ true);
×
80
            }
×
81
            else
82
            {
83
                // provided argument but wrong type
84
                if (i < args.size() && td.types[0] != ValueType::Any && std::ranges::find(td.types, args[i].valueType()) == td.types.end())
5✔
85
                {
86
                    displayArg(td, /* correct= */ false);
2✔
87
                    const auto type = types_to_str[static_cast<std::size_t>(args[i].valueType())];
2✔
88

89
                    fmt::dynamic_format_arg_store<fmt::format_context> store;
2✔
90
                    if (colorize)
2✔
NEW
91
                        store.push_back(fmt::styled(type, fmt::fg(fmt::color::red)));
×
92
                    else
93
                        store.push_back(type);
2✔
94
                    fmt::vprint(os, " was of type {}", store);
2✔
95
                }
2✔
96
                // non-provided argument
97
                else if (i >= args.size())
3✔
98
                {
99
                    displayArg(td, /* correct= */ false);
1✔
100
                    if (colorize)
1✔
NEW
101
                        fmt::print(os, "{}", fmt::styled(" was not provided", fmt::fg(fmt::color::red)));
×
102
                    else
103
                        fmt::print(os, " was not provided");
1✔
104
                }
1✔
105
                else
106
                    displayArg(td, /* correct= */ true);
2✔
107
            }
108
            fmt::print(os, "\n");
5✔
109
        }
5✔
110
    }
4✔
111

112
    [[noreturn]] void generateError(const std::string_view& funcname, const std::vector<Contract>& contracts, const std::vector<Value>& args, std::ostream& os, bool colorize)
4✔
113
    {
4✔
114
        {
115
            fmt::dynamic_format_arg_store<fmt::format_context> store;
4✔
116
            if (colorize)
4✔
NEW
117
                store.push_back(fmt::styled(funcname, fmt::fg(fmt::color::blue)));
×
118
            else
119
                store.push_back(funcname);
4✔
120
            fmt::vprint(os, "Function {} expected ", store);
4✔
121
        }
8✔
122

123
        std::vector<Value> sanitizedArgs;
4✔
124
        std::ranges::copy_if(args, std::back_inserter(sanitizedArgs), [](const Value& value) -> bool {
9✔
125
            return value.valueType() != ValueType::Undefined;
5✔
126
        });
127

128
        // get expected arguments count
129
        std::size_t min_argc = std::numeric_limits<std::size_t>::max(), max_argc = 0;
4✔
130
        for (const auto& [arguments] : contracts)
20✔
131
        {
132
            if (arguments.size() < min_argc)
4✔
133
                min_argc = arguments.size();
4✔
134
            if (arguments.size() > max_argc)
4✔
135
                max_argc = arguments.size();
4✔
136
        }
4✔
137

138
        bool correct_argcount = true;
4✔
139

140
        if (min_argc != max_argc)
4✔
141
        {
NEW
142
            fmt::dynamic_format_arg_store<fmt::format_context> store;
×
NEW
143
            if (colorize)
×
NEW
144
                store.push_back(fmt::styled(min_argc, fmt::fg(fmt::color::yellow)));
×
145
            else
NEW
146
                store.push_back(min_argc);
×
NEW
147
            store.push_back(min_argc > 1 ? "s" : "");
×
NEW
148
            if (colorize)
×
NEW
149
                store.push_back(fmt::styled(max_argc, fmt::fg(fmt::color::yellow)));
×
150
            else
NEW
151
                store.push_back(max_argc);
×
NEW
152
            store.push_back(max_argc > 1 ? "s" : "");
×
153

NEW
154
            fmt::vprint(os, "between {} argument{} and {} argument{}", store);
×
155

156
            if (sanitizedArgs.size() < min_argc || sanitizedArgs.size() > max_argc)
×
157
                correct_argcount = false;
×
158
        }
×
159
        else
160
        {
161
            fmt::dynamic_format_arg_store<fmt::format_context> store;
4✔
162
            if (colorize)
4✔
NEW
163
                store.push_back(fmt::styled(min_argc, fmt::fg(fmt::color::yellow)));
×
164
            else
165
                store.push_back(min_argc);
4✔
166
            store.push_back(min_argc > 1 ? "s" : "");
4✔
167

168
            fmt::vprint(os, "{} argument{}", store);
4✔
169

170
            if (sanitizedArgs.size() != min_argc)
4✔
171
                correct_argcount = false;
2✔
172
        }
4✔
173

174
        if (!correct_argcount)
4✔
175
        {
176
            if (colorize)
2✔
NEW
177
                fmt::print(os, " but got {}", fmt::styled(sanitizedArgs.size(), fmt::fg(fmt::color::red)));
×
178
            else
179
                fmt::print(os, " but got {}", sanitizedArgs.size());
2✔
180
        }
2✔
181

182
        fmt::print(os, "\n");
4✔
183

184
        displayContract(contracts[0], sanitizedArgs, os, colorize);
4✔
185
        for (std::size_t i = 1, end = contracts.size(); i < end; ++i)
4✔
186
        {
NEW
187
            fmt::print(os, "Alternative {}:\n", i + 1);
×
NEW
188
            displayContract(contracts[i], sanitizedArgs, os, colorize);
×
UNCOV
189
        }
×
190

191
        throw TypeError("");
4✔
192
    }
8✔
193
}
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