Clear Project (#40)

This commit is contained in:
ykiko
2025-01-16 22:48:35 +08:00
committed by GitHub
parent 2476020c71
commit 2f44874cbf
56 changed files with 1500 additions and 1696 deletions

View File

@@ -4,6 +4,7 @@
#include "Support/Error.h"
#include "Support/JSON.h"
#include "Support/Ranges.h"
namespace clice {
@@ -12,30 +13,11 @@ void print(std::format_string<Args...> fmt, Args&&... args) {
llvm::outs() << std::vformat(fmt.get(), std::make_format_args(args...));
}
template <typename... Ts>
constexpr inline bool is_formattable_v = false;
template <typename T, typename... Args>
constexpr inline bool is_formattable_v<T, Args...> =
std::is_convertible_v<T, std::format_string<Args...>>;
template <typename... Args>
requires (!is_formattable_v<Args...>)
void print(Args&&... args) {
((llvm::outs() << std::format("{}", std::make_format_args(args)) << " "), ...);
}
template <typename... Args>
void println(std::format_string<Args...> fmt, Args&&... args) {
llvm::outs() << std::vformat(fmt.get(), std::make_format_args(args...)) << '\n';
}
template <typename... Args>
requires (!is_formattable_v<Args...>)
void println(Args&&... args) {
((llvm::outs() << std::format("{}", std::make_format_args(args)) << " "), ...) << '\n';
}
} // namespace clice
template <>
@@ -53,6 +35,21 @@ struct std::formatter<llvm::StringRef> : std::formatter<std::string_view> {
}
};
template <std::size_t N>
struct std::formatter<llvm::SmallString<N>> : std::formatter<llvm::StringRef> {
using Base = std::formatter<llvm::StringRef>;
template <typename ParseContext>
constexpr auto parse(ParseContext& ctx) {
return Base::parse(ctx);
}
template <typename FormatContext>
auto format(const llvm::SmallString<N>& s, FormatContext& ctx) const {
return Base::format(llvm::StringRef(s), ctx);
}
};
template <>
struct std::formatter<llvm::Error> : std::formatter<llvm::StringRef> {
using Base = std::formatter<llvm::StringRef>;
@@ -71,21 +68,6 @@ struct std::formatter<llvm::Error> : std::formatter<llvm::StringRef> {
}
};
template <std::size_t N>
struct std::formatter<llvm::SmallString<N>> : std::formatter<llvm::StringRef> {
using Base = std::formatter<llvm::StringRef>;
template <typename ParseContext>
constexpr auto parse(ParseContext& ctx) {
return Base::parse(ctx);
}
template <typename FormatContext>
auto format(const llvm::SmallString<N>& s, FormatContext& ctx) const {
return Base::format(llvm::StringRef(s), ctx);
}
};
template <>
struct std::formatter<clice::json::Value> : std::formatter<llvm::StringRef> {
using Base = std::formatter<llvm::StringRef>;
@@ -104,8 +86,7 @@ struct std::formatter<clice::json::Value> : std::formatter<llvm::StringRef> {
}
};
template <typename E>
requires clice::refl::special_enum<E>
template <clice::refl::reflectable_enum E>
struct std::formatter<E> : std::formatter<std::string_view> {
using Base = std::formatter<std::string_view>;
@@ -119,3 +100,66 @@ struct std::formatter<E> : std::formatter<std::string_view> {
return Base::format(e.name(), ctx);
}
};
namespace clice {
/// Dump object to string for debugging. Note that it is not efficient
/// and should not be used except for debugging.
template <typename Object>
std::string dump(const Object& object) {
if constexpr(std::is_fundamental_v<Object>) {
return std::format("{}", object);
} else if constexpr(std::is_same_v<Object, std::string> ||
std::is_same_v<Object, std::string_view> ||
std::is_same_v<Object, llvm::StringRef>) {
return std::format("\"{}\"", object);
} else if constexpr(ranges::range<Object>) {
constexpr bool is_sequence = sequence_range<Object>;
std::string result = is_sequence ? "[" : "{";
if constexpr(map_range<Object>) {
for(auto&& [key, value]: object) {
result += std::format("\"{}\": {}, ", dump(key), dump(value));
}
} else {
for(auto&& value: object) {
result += std::format("{}, ", dump(value));
}
}
if(!object.empty()) {
result.pop_back();
result.pop_back();
}
result += is_sequence ? "]" : "}";
return result;
} else if constexpr(std::is_enum_v<Object>) {
return std::format("{}", refl::enum_name(object));
} else if constexpr(refl::reflectable_enum<Object>) {
return std::format("\"{}\"", object);
} else if constexpr(refl::reflectable_struct<Object>) {
std::string result = "{";
refl::foreach(object, [&](auto name, auto value) {
result += std::format("\"{}\": {}, ", name, dump(value));
});
if(refl::member_count<Object>() != 0) {
result.pop_back();
result.pop_back();
}
result += "}";
return result;
} else {
static_assert(dependent_false<Object>, "Cannot dump object");
}
}
template <typename Object>
std::string pretty_dump(const Object& object, std::size_t indent = 2) {
auto repr = dump(object);
auto json = json::parse(repr);
if(!json) {
std::terminate();
}
llvm::SmallString<128> buffer = {std::format("{{0:{}}}", indent)};
return llvm::formatv(buffer.c_str(), *json);
}
} // namespace clice