Skip to content

Commit 4918cc2

Browse files
committed
feat(tests, type checker): adding tests for the type checker error message generation (in isolation)
1 parent 8865cae commit 4918cc2

12 files changed

Lines changed: 306 additions & 39 deletions

File tree

include/Ark/TypeChecker.hpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <string>
1616
#include <vector>
17+
#include <ostream>
1718

1819
#include <Ark/VM/Value.hpp>
1920

@@ -62,15 +63,15 @@ namespace Ark::types
6263
*/
6364
struct ARK_API Typedef
6465
{
65-
std::string_view name;
66+
std::string name;
6667
std::vector<ValueType> types;
6768
bool variadic;
6869

69-
Typedef(const std::string_view& type_name, const ValueType type, const bool is_variadic = false) :
70+
Typedef(const std::string& type_name, const ValueType type, const bool is_variadic = false) :
7071
name(type_name), types { type }, variadic(is_variadic)
7172
{}
7273

73-
Typedef(const std::string_view& type_name, const std::vector<ValueType>& type_list, const bool is_variadic = false) :
74+
Typedef(const std::string& type_name, const std::vector<ValueType>& type_list, const bool is_variadic = false) :
7475
name(type_name), types(type_list), variadic(is_variadic)
7576
{}
7677
};
@@ -90,8 +91,15 @@ namespace Ark::types
9091
* @param funcname ArkScript name of the function
9192
* @param contracts types contracts the function can follow
9293
* @param args provided argument list
94+
* @param os output stream, default to cout
95+
* @param colorize enable output colorizing
9396
*/
94-
ARK_API void generateError [[noreturn]] (const std::string_view& funcname, const std::vector<Contract>& contracts, const std::vector<Value>& args);
97+
ARK_API void generateError [[noreturn]] (
98+
const std::string_view& funcname,
99+
const std::vector<Contract>& contracts,
100+
const std::vector<Value>& args,
101+
std::ostream& os = std::cout,
102+
bool colorize = true);
95103
}
96104

97105
#endif

src/arkreactor/TypeChecker.cpp

Lines changed: 85 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
#include <limits>
44
#include <algorithm>
55
#include <fmt/core.h>
6+
#include <fmt/args.h>
67
#include <fmt/color.h>
8+
#include <fmt/ostream.h>
79

810
#include <Ark/Exceptions.hpp>
911

@@ -25,20 +27,25 @@ namespace Ark::types
2527
return acc;
2628
}
2729

28-
void displayContract(const Contract& contract, const std::vector<Value>& args)
30+
void displayContract(const Contract& contract, const std::vector<Value>& args, std::ostream& os, const bool colorize)
2931
{
30-
auto displayArg = [](const Typedef& td, bool correct) {
32+
auto displayArg = [](const Typedef& td, const bool correct, std::ostream& os, const bool colorize) {
3133
const std::string arg_str = typeListToString(td.types);
3234

33-
fmt::print(
34-
" -> {}{} ({}) ",
35-
td.variadic ? "variadic " : "",
36-
fmt::styled(
37-
td.name,
38-
correct
39-
? fmt::fg(fmt::color::green)
40-
: fmt::fg(fmt::color::magenta)),
41-
arg_str);
35+
fmt::dynamic_format_arg_store<fmt::format_context> store;
36+
store.push_back(td.variadic ? "variadic " : "");
37+
if (colorize)
38+
store.push_back(
39+
fmt::styled(
40+
td.name,
41+
correct
42+
? fmt::fg(fmt::color::green)
43+
: fmt::fg(fmt::color::magenta)));
44+
else
45+
store.push_back(td.name);
46+
store.push_back(arg_str);
47+
48+
fmt::vprint(os, " -> {}{} ({})", store);
4249
};
4350

4451
for (std::size_t i = 0, end = contract.arguments.size(); i < end; ++i)
@@ -57,36 +64,61 @@ namespace Ark::types
5764

5865
if (bad_type)
5966
{
60-
displayArg(td, false);
61-
fmt::print("{} argument{} do not match", fmt::styled(bad_type, fmt::fg(fmt::color::red)), bad_type > 1 ? "s" : "");
67+
displayArg(td, false, os, colorize);
68+
69+
fmt::dynamic_format_arg_store<fmt::format_context> store;
70+
if (colorize)
71+
store.push_back(fmt::styled(bad_type, fmt::fg(fmt::color::red)));
72+
else
73+
store.push_back(bad_type);
74+
store.push_back(bad_type > 1 ? "s" : "");
75+
76+
fmt::vprint(os, " {} argument{} do not match", store);
6277
}
6378
else
64-
displayArg(td, true);
79+
displayArg(td, true, os, colorize);
6580
}
6681
else
6782
{
6883
// provided argument but wrong type
6984
if (i < args.size() && td.types[0] != ValueType::Any && std::ranges::find(td.types, args[i].valueType()) == td.types.end())
7085
{
71-
displayArg(td, false);
72-
fmt::print("was of type {}", fmt::styled(types_to_str[static_cast<std::size_t>(args[i].valueType())], fmt::fg(fmt::color::red)));
86+
displayArg(td, false, os, colorize);
87+
const auto type = types_to_str[static_cast<std::size_t>(args[i].valueType())];
88+
89+
fmt::dynamic_format_arg_store<fmt::format_context> store;
90+
if (colorize)
91+
store.push_back(fmt::styled(type, fmt::fg(fmt::color::red)));
92+
else
93+
store.push_back(type);
94+
fmt::vprint(os, " was of type {}", store);
7395
}
7496
// non-provided argument
7597
else if (i >= args.size())
7698
{
77-
displayArg(td, false);
78-
fmt::print(fmt::fg(fmt::color::red), "was not provided");
99+
displayArg(td, false, os, colorize);
100+
if (colorize)
101+
fmt::print(os, "{}", fmt::styled(" was not provided", fmt::fg(fmt::color::red)));
102+
else
103+
fmt::print(os, " was not provided");
79104
}
80105
else
81-
displayArg(td, true);
106+
displayArg(td, true, os, colorize);
82107
}
83-
fmt::print("\n");
108+
fmt::print(os, "\n");
84109
}
85110
}
86111

87-
[[noreturn]] void generateError(const std::string_view& funcname, const std::vector<Contract>& contracts, const std::vector<Value>& args)
112+
[[noreturn]] void generateError(const std::string_view& funcname, const std::vector<Contract>& contracts, const std::vector<Value>& args, std::ostream& os, bool colorize)
88113
{
89-
fmt::print("Function {} expected ", fmt::styled(funcname, fmt::fg(fmt::color::blue)));
114+
{
115+
fmt::dynamic_format_arg_store<fmt::format_context> store;
116+
if (colorize)
117+
store.push_back(fmt::styled(funcname, fmt::fg(fmt::color::blue)));
118+
else
119+
store.push_back(funcname);
120+
fmt::vprint(os, "Function {} expected ", store);
121+
}
90122

91123
std::vector<Value> sanitizedArgs;
92124
std::ranges::copy_if(args, std::back_inserter(sanitizedArgs), [](const Value& value) -> bool {
@@ -107,34 +139,53 @@ namespace Ark::types
107139

108140
if (min_argc != max_argc)
109141
{
110-
fmt::print(
111-
"between {} argument{} and {} argument{}",
112-
fmt::styled(min_argc, fmt::fg(fmt::color::yellow)),
113-
min_argc > 1 ? "s" : "",
114-
fmt::styled(max_argc, fmt::fg(fmt::color::yellow)),
115-
max_argc > 1 ? "s" : "");
142+
fmt::dynamic_format_arg_store<fmt::format_context> store;
143+
if (colorize)
144+
store.push_back(fmt::styled(min_argc, fmt::fg(fmt::color::yellow)));
145+
else
146+
store.push_back(min_argc);
147+
store.push_back(min_argc > 1 ? "s" : "");
148+
if (colorize)
149+
store.push_back(fmt::styled(max_argc, fmt::fg(fmt::color::yellow)));
150+
else
151+
store.push_back(max_argc);
152+
store.push_back(max_argc > 1 ? "s" : "");
153+
154+
fmt::vprint(os, "between {} argument{} and {} argument{}", store);
116155

117156
if (sanitizedArgs.size() < min_argc || sanitizedArgs.size() > max_argc)
118157
correct_argcount = false;
119158
}
120159
else
121160
{
122-
fmt::print("{} argument{}", fmt::styled(min_argc, fmt::fg(fmt::color::yellow)), min_argc > 1 ? "s" : "");
161+
fmt::dynamic_format_arg_store<fmt::format_context> store;
162+
if (colorize)
163+
store.push_back(fmt::styled(min_argc, fmt::fg(fmt::color::yellow)));
164+
else
165+
store.push_back(min_argc);
166+
store.push_back(min_argc > 1 ? "s" : "");
167+
168+
fmt::vprint(os, "{} argument{}", store);
123169

124170
if (sanitizedArgs.size() != min_argc)
125171
correct_argcount = false;
126172
}
127173

128174
if (!correct_argcount)
129-
fmt::print(" but got {}", fmt::styled(sanitizedArgs.size(), fmt::fg(fmt::color::red)));
175+
{
176+
if (colorize)
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());
180+
}
130181

131-
fmt::print("\n");
182+
fmt::print(os, "\n");
132183

133-
displayContract(contracts[0], sanitizedArgs);
184+
displayContract(contracts[0], sanitizedArgs, os, colorize);
134185
for (std::size_t i = 1, end = contracts.size(); i < end; ++i)
135186
{
136-
std::cout << "Alternative " << (i + 1) << ":\n";
137-
displayContract(contracts[i], sanitizedArgs);
187+
fmt::print(os, "Alternative {}:\n", i + 1);
188+
displayContract(contracts[i], sanitizedArgs, os, colorize);
138189
}
139190

140191
throw TypeError("");

0 commit comments

Comments
 (0)