Clear Project (#40)
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user