32template <
typename T, std::integral U,
typename... Extra>
33inline std::int64_t get_ulps(T
const& a, T
const& b, U ulps, Extra&&... extra)
35 return static_cast<std::int64_t
>(ulps);
38template <
typename T>
inline std::int64_t get_ulps(T
const& a, T
const& b) {
return 4; }
40template <
typename T,
typename... Extra>
inline std::int64_t get_ulps(T
const& a, T
const& b, Extra&&...) {
return 4; }
44struct FormattingOptions;
81 static constexpr const char*
StaticName =
"Color options (yes/no/auto)";
82 static constexpr std::array<const char*, 3>
Names = {
"yes",
"no",
"auto"};
110 static constexpr const char*
StaticName =
"Thread-id options (yes/no/auto)";
111 static constexpr std::array<const char*, 3>
Names = {
"yes",
"no",
"auto"};
124 using Sink = std::function<void(std::string)>;
128 std::fputs(s.c_str(), stderr);
144 mutable std::map<std::string, terminal::TerminalStyle>
Styles;
157 return CO::autocolor;
159 return CO::autocolor;
173 static constexpr std::pair<std::string_view, std::string_view> kDefaults[] = {{
"TRACE",
"Cyan"},
174 {
"DEBUG_TRACE",
"Green"},
175 {
"TRACE_EXPR",
"Blue"},
177 {
"TRACE_MODULE",
"Cyan;Bold"},
178 {
"TRACE_FILENAME",
"Red"},
179 {
"TRACE_LINE",
"Bold"},
180 {
"TRACE_STRING",
"Cyan"},
182 {
"DEBUG_CHECK",
"Red"},
183 {
"PRECONDITION",
"Red"},
184 {
"DEBUG_PRECONDITION",
"Red"},
187 {
"TIMESTAMP",
"LightGray"},
188 {
"THREAD_ID",
"LightMagenta"}};
190 for (
auto [kind, def] : kDefaults)
192 std::string env = std::string(
"UNI20_COLOR_") + kind;
193 Styles[std::string(kind)] = terminal::getenv_or_default<terminal::TerminalStyle>(env, def);
197 if (
auto* path = std::getenv(
"UNI20_TRACEFILE"))
201 if (std::strcmp(path,
"-") == 0 || std::strcmp(path,
"stdout") == 0)
205 else if (std::strcmp(path,
"stderr") == 0)
209 else if (std::strlen(path) > 0)
217 out = std::fopen(path, append ?
"a" :
"w");
232 timestamp = terminal::getenv_or_default<terminal::toggle>(
"UNI20_TRACE_TIMESTAMP",
true);
233 threadId = parse_thread_id_option_from_env(
"UNI20_TRACE_THREAD_ID",
threadId);
246 std::string mod{
module};
251 static constexpr std::string_view kDefaults[] = {
"TRACE",
"DEBUG_TRACE",
"TRACE_EXPR",
252 "TRACE_VALUE",
"TRACE_FILENAME",
"TRACE_LINE",
253 "TRACE_STRING",
"TIMESTAMP",
"THREAD_ID"};
255 for (
auto kind : kDefaults)
257 std::string env = fmt::format(
"UNI20_COLOR_{}_MODULE_{}", kind, module);
259 Styles[std::string(kind)] = terminal::getenv_or_default<terminal::TerminalStyle>(env, def);
263 if (
auto* path = std::getenv((
"UNI20_TRACEFILE_MODULE_" + mod).c_str()))
267 if (std::strcmp(path,
"-") == 0 || std::strcmp(path,
"stdout") == 0)
271 else if (std::strcmp(path,
"stderr") == 0)
275 else if (std::strlen(path) > 0)
283 out = std::fopen(path, append ?
"a" :
"w");
294 terminal::getenv_or_default<int>(
"UNI20_FP_PRECISION_FLOAT32_MODULE_" + mod,
fp_precision_float32);
296 terminal::getenv_or_default<int>(
"UNI20_FP_PRECISION_FLOAT64_MODULE_" + mod,
fp_precision_float64);
298 terminal::getenv_or_default<int>(
"UNI20_FP_PRECISION_FLOAT128_MODULE_" + mod,
fp_precision_float128);
301 timestamp = terminal::getenv_or_default<terminal::toggle>(
"UNI20_TRACE_TIMESTAMP_MODULE_" + mod,
timestamp);
302 threadId = parse_thread_id_option_from_env(
"UNI20_TRACE_THREAD_ID_MODULE_" + mod,
threadId);
321 sink = [f](std::string s) {
322 std::fputs(s.c_str(), f);
338 color = color_option_from_policy(
c);
402 std::string
format_style(
const std::string& str,
const std::string& kind)
const
407 fmt::print(stderr,
"UNEXPECTED: unknown format style: {}\n", kind);
413 return this->
render(text);
424 fmt::print(stderr,
"UNEXPECTED: unknown format style: {}\n", kind);
430 return this->
render(text);
439 auto const it =
Styles.find(kind);
442 fmt::print(stderr,
"UNEXPECTED: unknown format style: {}\n", kind);
454 std::string
const& kind)
const
456 auto const it =
Styles.find(kind);
459 fmt::print(stderr,
"UNEXPECTED: unknown format style: {}\n", kind);
471 auto const it =
Styles.find(std::string(kind));
501 if (
auto const* raw = std::getenv(var.c_str()))
503 return parse_thread_id_option_from_string(raw, fallback);
509 void updateShowColor()
513 if (
color == CO::yes)
515 else if (
color == CO::no)
530 static std::recursive_mutex mtx;
531 static std::unordered_map<std::string, FormattingOptions> table;
532 std::lock_guard lock(mtx);
534 auto it = table.find(module);
535 if (it != table.end())
return it->second;
548 auto [it, _] = table.try_emplace(module, module);
559template <
typename T,
typename CharT =
char>
560#if defined(__CUDACC__)
582 return fmt::format(
"{}",
value);
589 return std::format(
"{}",
value);
607template <uni20::Complex T>
615template <
typename Promise>
620 reinterpret_cast<const void*
>(h.address()));
626 return fmt::format(
"coroutine_handle<> @ {:p}",
reinterpret_cast<const void*
>(h.address()));
634template <Container ContainerType>
638 std::vector<
decltype(
formatValue(*std::begin(
c), opts))> result;
639 result.reserve(std::ranges::distance(
c));
640 for (
auto const& elem :
c)
653 if (s.empty())
return std::string(
"(null)");
654 return fmt::format(
"{}", s);
663 if (!s)
return std::string(
"(null)");
664 return fmt::format(
"{}", s);
673 return formatValue(
static_cast<const char*
>(s), opts);
684 requires(!std::is_same_v<U, char> && !std::is_same_v<U, const char>)
702inline bool trace_dump_enabled()
704 if (
auto const*
value = std::getenv(
"UNI20_TRACE_DUMP"))
706 std::string_view mode(
value);
716inline std::string sanitize_dump_label(std::string_view label)
719 out.reserve(std::min<std::size_t>(label.size(), 80));
720 for (
auto const ch : label)
722 auto const c =
static_cast<unsigned char>(ch);
723 if (std::isalnum(
c) || ch ==
'_' || ch ==
'-' || ch ==
'.')
727 else if (!
out.empty() &&
out.back() !=
'_')
731 if (
out.size() >= 80)
break;
733 if (
out.empty()) out =
"value";
737inline std::filesystem::path trace_dump_directory()
739 if (
auto const* dir = std::getenv(
"UNI20_TRACE_DUMP_DIR"); dir !=
nullptr && std::strlen(dir) > 0)
741 return std::filesystem::path(dir);
743 return std::filesystem::temp_directory_path() /
"uni20-trace";
746inline std::filesystem::path next_trace_dump_path(std::string_view label)
748 static std::atomic<std::uint64_t> counter = 0;
749 auto dir = trace_dump_directory();
750 std::filesystem::create_directories(dir);
751 auto const now = std::chrono::system_clock::now().time_since_epoch();
752 auto const stamp = std::chrono::duration_cast<std::chrono::microseconds>(now).count();
753 auto const id = counter.fetch_add(1, std::memory_order_relaxed);
754 return dir / fmt::format(
"uni20_trace_{}_{}_{}.txt", stamp,
id, sanitize_dump_label(label));
757template <
typename MDS, std::
size_t Rank>
758std::string dump_index_string(std::array<
typename std::remove_cvref_t<MDS>::index_type, Rank>
const& indices)
760 if constexpr (Rank == 0)
766 std::string
out =
"[";
767 for (std::size_t i = 0; i < Rank; ++i)
769 if (i > 0)
out +=
", ";
770 out += std::to_string(
static_cast<std::size_t
>(indices[i]));
777inline std::string dump_shape_string(std::vector<std::size_t>
const& extents)
779 std::string
out =
"shape=(";
780 for (std::size_t i = 0; i < extents.size(); ++i)
782 if (i > 0)
out +=
", ";
783 out += std::to_string(extents[i]);
789template <
typename MDS,
typename ElementFormatter, std::
size_t Rank>
790void write_mdspan_dump_recursive(std::ofstream& out, MDS
const& mds,
791 std::array<
typename std::remove_cvref_t<MDS>::index_type, Rank>& indices,
793 ElementFormatter& formatter)
797 out << dump_index_string<MDS>(indices) <<
'\t'
802 auto const extent =
static_cast<std::size_t
>(mds.extent(axis));
803 for (std::size_t i = 0; i < extent; ++i)
805 indices[axis] =
static_cast<typename std::remove_cvref_t<MDS>::index_type
>(i);
806 write_mdspan_dump_recursive(out, mds, indices, axis + 1, policy, formatter);
810template <uni20::presentation::mdspan_like MDS,
typename ElementFormatter>
811std::string write_mdspan_dump(MDS
const& mds, FormattingOptions
const& opts, std::string_view label,
812 std::vector<std::size_t>
const& extents, std::size_t element_count,
813 ElementFormatter&& formatter)
815 if (!trace_dump_enabled())
return "full data dump disabled by UNI20_TRACE_DUMP";
819 auto path = next_trace_dump_path(label);
820 std::ofstream
out(path);
821 if (!out)
return "full data dump failed: could not open " + path.string();
823 auto dump_policy = opts.presentation_policy();
826 dump_policy.wrap_width = std::nullopt;
828 out <<
"# Uni20 trace mdspan dump\n";
829 out <<
"# " << dump_shape_string(extents) <<
'\n';
830 out <<
"# elements=" << element_count <<
'\n';
831 out <<
"# index\tvalue\n";
833 constexpr std::size_t rank = std::remove_cvref_t<MDS>::rank();
834 using index_type =
typename std::remove_cvref_t<MDS>::index_type;
835 auto element_formatter = std::forward<ElementFormatter>(formatter);
836 std::array<index_type, rank> indices{};
837 if constexpr (rank == 0)
844 write_mdspan_dump_recursive(out, mds, indices, 0, dump_policy, element_formatter);
847 return "full data: " + path.string();
849 catch (std::exception
const& ex)
851 return std::string(
"full data dump failed: ") + ex.what();
856template <uni20::presentation::mdspan_like MDS>
867 policy.
wrap_width =
static_cast<std::size_t
>(value_width);
874 preview.text +=
"\n";
875 preview.text += detail::write_mdspan_dump(mds, opts, label, preview.extents, preview.element_count, formatter);
885template <uni20::presentation::mdspan_like MDS>
901template <uni20::presentation::mdspan_like MDS>
908template <HasPresentationMdspanView T>
923inline std::string
trim(
const std::string& s)
927 while (start < s.size() && std::isspace(
static_cast<unsigned char>(s[start])))
929 if (start == s.size())
934 size_t end = s.size() - 1;
935 while (end > start && std::isspace(
static_cast<unsigned char>(s[end])))
937 return s.substr(start, end - start + 1);
958inline std::vector<std::pair<std::string, bool>>
parseNames(std::string_view s)
960 std::vector<std::pair<std::string, bool>> tokens;
962 bool tokenHasTopLevelLiteral =
false;
965 int parenCount = 0, squareCount = 0, curlyCount = 0;
968 bool inDoubleQuote =
false, inSingleQuote =
false;
970 for (
size_t i = 0; i < s.size(); ++i)
977 current.push_back(
c);
981 if (i + 1 < s.size())
983 current.push_back(s[i + 1]);
989 inDoubleQuote =
false;
997 current.push_back(
c);
1000 if (i + 1 < s.size())
1002 current.push_back(s[i + 1]);
1008 inSingleQuote =
false;
1014 if ((
c ==
'"' ||
c ==
'\'') && parenCount == 0 && squareCount == 0 && curlyCount == 0)
1016 tokenHasTopLevelLiteral =
true;
1018 inDoubleQuote =
true;
1020 inSingleQuote =
true;
1021 current.push_back(
c);
1026 if (
c ==
',' && parenCount == 0 && squareCount == 0 && curlyCount == 0)
1028 tokens.push_back({
trim(current), tokenHasTopLevelLiteral});
1030 tokenHasTopLevelLiteral =
false;
1039 if (parenCount > 0) --parenCount;
1045 if (squareCount > 0) --squareCount;
1051 if (curlyCount > 0) --curlyCount;
1054 current.push_back(
c);
1058 if (!current.empty()) tokens.push_back({
trim(current), tokenHasTopLevelLiteral});
1064inline bool isMultiline(
const std::string& str) {
return std::find(str.begin(), str.end(),
'\n') != str.end(); }
1068 for (
const auto& s : str)
1089 std::size_t lineStart = 0;
1090 while (lineStart <= str.size())
1092 auto const lineEnd = str.find(
'\n', lineStart);
1093 auto const line = lineEnd == std::string::npos ? std::string_view(str).substr(lineStart)
1094 : std::string_view(str).substr(lineStart, lineEnd - lineStart);
1096 if (lineEnd == std::string::npos)
break;
1097 lineStart = lineEnd + 1;
1117 size_t max_width = 0;
1118 for (
const auto& e : elems)
1119 max_width = std::max(max_width,
maxWidth(e, policy));
1123template <
typename T>
size_t maxWidth(
const std::vector<T>& elems)
1130 if (elems.empty())
return false;
1132 auto const cols = elems.front().size();
1133 if (cols == 0)
return false;
1135 for (
auto const& row : elems)
1137 if (row.size() != cols)
return false;
1146 std::vector<std::string> flat;
1147 flat.reserve(elems.size() * elems.front().size());
1148 for (
auto const& row : elems)
1150 flat.insert(flat.end(), row.begin(), row.end());
1153 using extents_type = stdex::extents<std::size_t, stdex::dynamic_extent, stdex::dynamic_extent>;
1154 auto matrix = stdex::mdspan<std::string const, extents_type, stdex::layout_right>(flat.data(), elems.size(),
1155 elems.front().size());
1181 std::string inlineStr;
1187 for (
int i = 0; i < std::ssize(elems); ++i)
1189 if (i > 0) inlineStr +=
",\n ";
1197 max_width = std::max(max_width,
maxWidth(elems, policy));
1199 for (
int i = 0; i < std::ssize(elems); ++i)
1201 if (i > 0) inlineStr +=
", ";
1215 size_t max_width = 0)
1224 std::string inlineStr =
"[ ";
1227 for (
int i = 0; i < std::ssize(elems); ++i)
1229 if (i > 0) inlineStr +=
",\n ";
1237 max_width = std::max(max_width,
maxWidth(elems, policy));
1238 for (
size_t i = 0; i < elems.size(); ++i)
1240 if (i > 0) inlineStr +=
",\n ";
1266 int available_width)
1279 if (
isMultiline(
value) || (available_width > 0 && item_width >
static_cast<std::size_t
>(available_width)))
1281 auto const indent =
displayWidth(name.first, opts) + 3;
1302 detail::TraceNameValue
const&
value,
1309 if (
isMultiline(
value.value) || (available_width > 0 && item_width >
static_cast<std::size_t
>(available_width)))
1332template <
typename T>
1340template <
typename T>
1341std::string
formatItemString(
const std::pair<std::string, bool>& name,
const std::vector<T>& values,
1362inline std::string
formatParameters(std::vector<std::pair<std::string, bool>>::const_iterator b,
1368template <
typename T,
typename... Ts>
1375 if (value_width > 0 && !b->second)
1378 if (indent <
static_cast<std::size_t
>(value_width))
1380 value_width -=
static_cast<int>(indent);
1388 if constexpr (
sizeof...(rest) > 0)
1390 result.append(
", ");
1396template <
typename T,
typename... Ts>
1403template <
typename T,
typename... Ts>
1405 const T& first,
const Ts&... rest)
1410template <
typename... Args>
1412 const Args&... args)
1418template <
typename... Args>
1426template <
typename... Args>
1433template <
typename... Args>
void print(fmt::format_string<Args...> fmt_str, Args&&... args)
1437 text.
append(fmt::format(fmt_str, std::forward<Args>(args)...));
1438 opts.sink(opts.render(
text));
1443 auto const now = std::chrono::system_clock::now();
1444 auto const whole_seconds = std::chrono::floor<std::chrono::seconds>(now);
1445 auto const nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(now - whole_seconds);
1446 auto const local_time = fmt::localtime(std::chrono::system_clock::to_time_t(whole_seconds));
1447 return fmt::format(
"{:%F %T}.{:09}", local_time, nanos.count());
1452inline std::thread::id
const startup_thread_id = std::this_thread::get_id();
1459 if (opts.
threadId == Mode::yes)
return true;
1460 if (opts.
threadId == Mode::no)
return false;
1461 return std::this_thread::get_id() != detail::startup_thread_id;
1467 bool has_prefix =
false;
1477 if (has_prefix) prefix.append(
" ");
1478 auto id = std::hash<std::thread::id>{}(std::this_thread::get_id());
1479 std::string th = fmt::format(
"[TID {:>8x}]",
id);
1484 if (has_prefix) prefix.append(
" ");
1494 std::string_view label, std::string_view style_kind,
const char* file,
int line)
1503 std::string_view label, std::string_view style_kind,
const char* module,
1504 const char* file,
int line)
1515 std::string_view style_kind,
bool start_newline)
1531 bool start_newline =
false)
1533 if (parameters.
empty())
return;
1541template <
typename... Args>
void TraceCall(
const char* exprList,
const char* file,
int line,
const Args&... args)
1550 opts.sink(opts.render(
text));
1556template <
typename... Args>
void TraceOnceCall(
const char* exprList,
const char* file,
int line,
const Args&... args)
1565 opts.sink(opts.render(
text));
1571template <
typename... Args>
1572void TraceModuleCall(
const char* module,
const char* exprList,
const char* file,
int line,
const Args&... args)
1581 opts.sink(opts.render(
text));
1587template <
typename... Args>
void DebugTraceCall(
const char* exprList,
const char* file,
int line,
const Args&... args)
1596 opts.sink(opts.render(
text));
1602template <
typename... Args>
1612 opts.sink(opts.render(
text));
1618template <
typename... Args>
1619void DebugTraceModuleCall(
const char* module,
const char* exprList,
const char* file,
int line,
const Args&... args)
1628 opts.sink(opts.render(
text));
1635 auto policy = opts.presentation_policy();
1636 if (!policy.
wrap_width.has_value() && opts.terminal_width > 0)
1638 policy.
wrap_width =
static_cast<std::size_t
>(opts.terminal_width);
1643#if TRACE_HAS_STACKTRACE
1644inline uni20::presentation::stacktrace_format_options stacktrace_presentation_options(FormattingOptions
const& opts)
1646 return uni20::presentation::stacktrace_format_options{
1648 .tree_style = opts.presentation_style(
"TRACE_LINE"),
1649 .index_style = opts.presentation_style(
"TRACE_LINE"),
1650 .description_style = opts.presentation_style(
"TRACE"),
1651 .source_file_style = opts.presentation_style(
"TRACE_FILENAME"),
1652 .source_line_style = opts.presentation_style(
"TRACE_LINE"),
1657inline void emit_stacktrace(FormattingOptions& opts, std::string_view style_kind, std::size_t skip_frames)
1659#if TRACE_HAS_STACKTRACE
1661 opts.append_style(heading,
"Stacktrace:", std::string(style_kind));
1663 opts.sink(opts.render(heading));
1664 auto const policy = diagnostic_presentation_policy(opts);
1665 opts.sink(opts.render(uni20::presentation::format_stacktrace(std::stacktrace::current(skip_frames), policy,
1666 stacktrace_presentation_options(opts))));
1671 opts.append_style(warning,
"WARNING: std::stacktrace is unavailable in this build; stacktrace omitted.",
1672 std::string(style_kind));
1674 opts.sink(opts.render(warning));
1678[[noreturn]]
inline void abort_with_stacktrace(FormattingOptions& opts, std::string
const& message,
1679 std::string_view style_kind, std::size_t skip_frames)
1682 emit_stacktrace(opts, style_kind, skip_frames);
1683 std::fflush(
nullptr);
1688 std::string_view style_kind, std::size_t skip_frames)
1690 opts.sink(opts.render(message));
1691 emit_stacktrace(opts, style_kind, skip_frames);
1692 std::fflush(
nullptr);
1696[[noreturn]]
inline void abort_after_diagnostic(FormattingOptions& opts,
1699 opts.sink(opts.render(message));
1700 std::fflush(
nullptr);
1704template <
typename... Args>
1705inline void emit_trace_line(FormattingOptions& opts, std::string_view label, std::string_view style_kind,
1706 const char* exprList,
const char* file,
int line,
const Args&... args)
1713 opts.sink(opts.render(
text));
1716template <
typename... Args>
1717inline void emit_trace_line_module(FormattingOptions& opts, std::string_view label, std::string_view style_kind,
1718 const char* module,
const char* exprList,
const char* file,
int line,
1719 const Args&... args)
1726 opts.sink(opts.render(
text));
1730 std::string_view style_kind,
const char* file,
int line)
1733 auto const glyph = [&] {
1735 if (style_kind ==
"CHECK" || style_kind ==
"DEBUG_CHECK" || style_kind ==
"PRECONDITION" ||
1736 style_kind ==
"DEBUG_PRECONDITION" || style_kind ==
"PANIC")
1742 opts.append_glyph(
text,
glyph, std::string(style_kind));
1752 opts.append_style(
text, cond,
"TRACE_EXPR");
1754 opts.append_style(
text,
"false",
"TRACE_VALUE");
1762 opts.append_style(
text, a,
"TRACE_EXPR");
1764 opts.append_style(
text, b,
"TRACE_EXPR");
1769 const char* a,
const char* b, std::int64_t ulps)
1772 opts.append_style(
text, a,
"TRACE_EXPR");
1774 opts.append_style(
text, b,
"TRACE_EXPR");
1776 opts.append_style(
text, fmt::format(
"{}", ulps),
"TRACE_EXPR");
1782 std::string_view style_kind)
1789template <
typename... Args>
void TraceStackCall(
const char* exprList,
const char* file,
int line,
const Args&... args)
1792 detail::emit_trace_line(opts,
"TRACE_STACK",
"TRACE", exprList, file, line, args...);
1793 detail::emit_stacktrace(opts,
"TRACE", 2);
1796template <
typename... Args>
1800 detail::emit_trace_line(opts,
"TRACE_ONCE_STACK",
"TRACE", exprList, file, line, args...);
1801 detail::emit_stacktrace(opts,
"TRACE", 2);
1804template <
typename... Args>
1805void TraceModuleStackCall(
const char* module,
const char* exprList,
const char* file,
int line,
const Args&... args)
1808 detail::emit_trace_line_module(opts,
"TRACE_MODULE_STACK",
"TRACE", module, exprList, file, line, args...);
1809 detail::emit_stacktrace(opts,
"TRACE", 2);
1812template <
typename... Args>
1816 detail::emit_trace_line(opts,
"DEBUG_TRACE_STACK",
"DEBUG_TRACE", exprList, file, line, args...);
1817 detail::emit_stacktrace(opts,
"DEBUG_TRACE", 2);
1820template <
typename... Args>
1824 detail::emit_trace_line(opts,
"DEBUG_TRACE_ONCE_STACK",
"DEBUG_TRACE", exprList, file, line, args...);
1825 detail::emit_stacktrace(opts,
"DEBUG_TRACE", 2);
1828template <
typename... Args>
1830 const Args&... args)
1833 detail::emit_trace_line_module(opts,
"DEBUG_TRACE_MODULE_STACK",
"DEBUG_TRACE", module, exprList, file, line,
1835 detail::emit_stacktrace(opts,
"DEBUG_TRACE", 2);
1838template <
typename... Args>
1839[[noreturn]]
void CheckCall(
const char* cond,
const char* exprList,
const char* file,
int line,
const Args&... args)
1844 auto text = detail::make_diagnostic_header(opts,
"CHECK",
"CHECK", file, line);
1845 detail::append_condition_false(
text, opts, cond);
1846 detail::append_diagnostic_parameters(
text, opts, parameters,
"CHECK");
1847 detail::abort_with_stacktrace(opts,
text,
"CHECK", 2);
1853template <
typename... Args>
1854[[noreturn]]
void DebugCheckCall(
const char* cond,
const char* exprList,
const char* file,
int line,
1855 const Args&... args)
1860 auto text = detail::make_diagnostic_header(opts,
"DEBUG_CHECK",
"DEBUG_CHECK", file, line);
1861 detail::append_condition_false(
text, opts, cond);
1862 detail::append_diagnostic_parameters(
text, opts, parameters,
"DEBUG_CHECK");
1863 detail::abort_with_stacktrace(opts,
text,
"DEBUG_CHECK", 2);
1869template <
typename... Args>
1870[[noreturn]]
void CheckEqualCall(
const char* a,
const char* b,
const char* exprList,
const char* file,
int line,
1871 const Args&... args)
1876 auto text = detail::make_diagnostic_header(opts,
"CHECK_EQUAL",
"CHECK", file, line);
1877 detail::append_not_equal(
text, opts, a, b);
1878 detail::append_diagnostic_parameters(
text, opts, parameters,
"CHECK");
1879 detail::abort_with_stacktrace(opts,
text,
"CHECK", 2);
1885template <
typename... Args>
1886[[noreturn]]
void DebugCheckEqualCall(
const char* a,
const char* b,
const char* exprList,
const char* file,
int line,
1887 const Args&... args)
1892 auto text = detail::make_diagnostic_header(opts,
"DEBUG_CHECK_EQUAL",
"DEBUG_CHECK", file, line);
1893 detail::append_not_equal(
text, opts, a, b);
1894 detail::append_diagnostic_parameters(
text, opts, parameters,
"DEBUG_CHECK");
1895 detail::abort_with_stacktrace(opts,
text,
"DEBUG_CHECK", 2);
1901template <
typename... Args>
1903 const char* file,
int line,
const Args&... args)
1908 auto text = detail::make_diagnostic_header(opts,
"CHECK_FLOATING_EQ",
"CHECK", file, line);
1909 detail::append_not_approx_equal(
text, opts, a, b, ulps);
1910 detail::append_diagnostic_parameters(
text, opts, parameters,
"CHECK");
1911 detail::abort_with_stacktrace(opts,
text,
"CHECK", 2);
1917template <
typename... Args>
1919 const char* file,
int line,
const Args&... args)
1924 auto text = detail::make_diagnostic_header(opts,
"DEBUG_CHECK_FLOATING_EQ",
"DEBUG_CHECK", file, line);
1925 detail::append_not_approx_equal(
text, opts, a, b, ulps);
1926 detail::append_diagnostic_parameters(
text, opts, parameters,
"DEBUG_CHECK");
1927 detail::abort_with_stacktrace(opts,
text,
"DEBUG_CHECK", 2);
1933template <
typename... Args>
1934[[noreturn]]
void PreconditionCall(
const char* cond,
const char* exprList,
const char* file,
int line,
1935 const Args&... args)
1940 auto text = detail::make_diagnostic_header(opts,
"PRECONDITION",
"PRECONDITION", file, line);
1941 detail::append_condition_false(
text, opts, cond);
1942 detail::append_diagnostic_parameters(
text, opts, parameters,
"PRECONDITION");
1943 detail::abort_with_stacktrace(opts,
text,
"PRECONDITION", 2);
1949template <
typename... Args>
1951 const Args&... args)
1956 auto text = detail::make_diagnostic_header(opts,
"DEBUG_PRECONDITION",
"DEBUG_PRECONDITION", file, line);
1957 detail::append_condition_false(
text, opts, cond);
1958 detail::append_diagnostic_parameters(
text, opts, parameters,
"DEBUG_PRECONDITION");
1959 detail::abort_with_stacktrace(opts,
text,
"DEBUG_PRECONDITION", 2);
1965template <
typename... Args>
1967 const Args&... args)
1972 auto text = detail::make_diagnostic_header(opts,
"PRECONDITION_EQUAL",
"PRECONDITION", file, line);
1973 detail::append_not_equal(
text, opts, a, b);
1974 detail::append_diagnostic_parameters(
text, opts, parameters,
"PRECONDITION");
1975 detail::abort_with_stacktrace(opts,
text,
"PRECONDITION", 2);
1981template <
typename... Args>
1983 int line,
const Args&... args)
1988 auto text = detail::make_diagnostic_header(opts,
"DEBUG_PRECONDITION_EQUAL",
"DEBUG_PRECONDITION", file, line);
1989 detail::append_not_equal(
text, opts, a, b);
1990 detail::append_diagnostic_parameters(
text, opts, parameters,
"DEBUG_PRECONDITION");
1991 detail::abort_with_stacktrace(opts,
text,
"DEBUG_PRECONDITION", 2);
1997template <
typename... Args>
1999 const char* file,
int line,
const Args&... args)
2004 auto text = detail::make_diagnostic_header(opts,
"PRECONDITION_FLOATING_EQ",
"PRECONDITION", file, line);
2005 detail::append_not_approx_equal(
text, opts, a, b, ulps);
2006 detail::append_diagnostic_parameters(
text, opts, parameters,
"PRECONDITION");
2007 detail::abort_with_stacktrace(opts,
text,
"PRECONDITION", 2);
2013template <
typename... Args>
2015 const char* file,
int line,
const Args&... args)
2020 auto text = detail::make_diagnostic_header(opts,
"DEBUG_PRECONDITION_FLOATING_EQ",
"DEBUG_PRECONDITION", file, line);
2021 detail::append_not_approx_equal(
text, opts, a, b, ulps);
2022 detail::append_diagnostic_parameters(
text, opts, parameters,
"DEBUG_PRECONDITION");
2023 detail::abort_with_stacktrace(opts,
text,
"DEBUG_PRECONDITION", 2);
2029template <
typename... Args>
2030[[noreturn]]
void PanicCall(
const char* exprList,
const char* file,
int line,
const Args&... args)
2035 auto text = detail::make_diagnostic_header(opts,
"PANIC",
"PANIC", file, line);
2038 detail::abort_with_stacktrace(opts,
text,
"PANIC", 2);
2044template <
typename... Args>
2045[[noreturn]]
void ErrorCall(
const char* exprList,
const char* file,
int line,
const Args&... args)
2051 auto text = detail::make_diagnostic_header(opts,
"ERROR",
"ERROR", file, line);
2055 if (opts.errors_abort())
2057 detail::abort_with_stacktrace(opts,
text,
"ERROR", 2);
2059 throw std::runtime_error(opts.render(
text));
2065template <
typename... Args>
2066[[noreturn]]
void ErrorIfCall(
const char* cond,
const char* exprList,
const char* file,
int line,
const Args&... args)
2072 auto text = detail::make_diagnostic_header(opts,
"ERROR",
"ERROR", file, line);
2074 detail::append_condition_false(
text, opts, cond);
2077 if (opts.errors_abort())
2079 detail::abort_with_stacktrace(opts,
text,
"ERROR", 2);
2081 throw std::runtime_error(opts.render(
text));
2086template <
class Error>
2087concept HasDiagnosticReport =
requires(Error
const& error) {
2088 { diagnostic_report(error) } -> std::same_as<uni20::presentation::report_builder>;
2095 if (
error.source_location().has_value())
2097 auto const& location = *
error.source_location();
2098 opts.append_style(
text,
"Source location:",
"ERROR");
2100 opts.append_style(
text, location.file_name(),
"TRACE_FILENAME");
2101 opts.append_style(
text, fmt::format(
":{}", location.line()),
"TRACE_LINE");
2105#if TRACE_HAS_STACKTRACE
2106 if (
error.stacktrace().has_value())
2108 opts.append_style(
text,
"Stacktrace:",
"ERROR");
2111 uni20::presentation::format_stacktrace(*
error.stacktrace(), policy, stacktrace_presentation_options(opts)));
2116template <
class Error>
2122 append_diagnostic_context(
text, opts, error, policy);
2126template <
class Error>
2128 std::source_location where)
2130 if constexpr (HasDiagnosticReport<Error>)
2134 return format_diagnostic_text(opts, error, diagnostic_presentation_policy(opts));
2143 auto text = make_diagnostic_header(opts,
"ERROR",
"ERROR", where.file_name(),
static_cast<int>(where.line()));
2145 opts.append_style(
text,
error.what(),
"TRACE_VALUE");
2157template <
class Error>
2158 requires std::derived_from<std::remove_cvref_t<Error>,
uni20::diagnostic_error> && detail::HasDiagnosticReport<Error>
2168template <
class Error>
2169 requires std::derived_from<std::remove_cvref_t<Error>,
uni20::diagnostic_error> && detail::HasDiagnosticReport<Error>
2173 return detail::format_diagnostic_text(opts, error, detail::diagnostic_presentation_policy(opts));
2182template <
class Exception>
2183 requires std::derived_from<std::remove_cvref_t<Exception>, std::exception>
2184[[noreturn]]
void raise(Exception&& exception, std::source_location where = std::source_location::current())
2186 using error_type = std::remove_cvref_t<Exception>;
2187 error_type error(std::forward<Exception>(exception));
2189 if constexpr (std::derived_from<error_type, uni20::diagnostic_error>)
2191 error.set_source_location(where);
2192#if TRACE_HAS_STACKTRACE
2193 error.set_stacktrace(std::stacktrace::current(1));
2198 if (opts.errors_abort())
2200 auto text = detail::raised_error_text(opts, error, where);
2201#if TRACE_HAS_STACKTRACE
2202 if constexpr (std::derived_from<error_type, uni20::diagnostic_error> && detail::HasDiagnosticReport<error_type>)
2204 if (error.stacktrace().has_value())
2206 detail::abort_after_diagnostic(opts,
text);
2210 detail::abort_with_stacktrace(opts,
text,
"ERROR", 2);
typename Traits::Enum Enum
Definition namedenum.hpp:39
Definition terminal.hpp:262
Base class for exceptions raised through Uni20's diagnostic boundary.
Definition diagnostic_error.hpp:25
A sequence of styled text spans and semantic glyph tokens.
Definition presentation.hpp:216
styled_text & append(std::string_view text, terminal::TerminalStyle style={})
Append a text span.
Definition presentation.cpp:1164
bool empty() const noexcept
Return whether this document has no spans.
Definition presentation.cpp:1182
Definition trace_impl.hpp:568
Definition trace_impl.hpp:690
Concept for types that are either real or complex.
Definition scalar_concepts.hpp:87
Concept for real scalar types (float, double, etc.).
Definition scalar_concepts.hpp:69
Detect mdspan-like objects without depending on trace or tensor.
Definition presentation_mdspan.hpp:70
locale_t value
Definition data_table.cpp:49
presentation::styled_text text
Definition display.cpp:141
bool is_a_terminal(std::FILE *stream)
Test whether a C output stream refers to a terminal.
Definition terminal.cpp:508
int columns()
Return the output terminal column count.
Definition terminal.cpp:502
std::size_t displayWidth(std::string_view str, uni20::presentation::output_policy const &policy)
Definition trace_impl.hpp:1075
std::string formatMdspanForTrace(MDS const &mds, FormattingOptions const &opts, int value_width, trace_format_context context, std::string_view label)
Definition trace_impl.hpp:857
void CheckCall(const char *cond, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1839
void TraceModuleStackCall(const char *module, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1805
void DebugTraceCall(const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1587
void DebugCheckCall(const char *cond, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1854
void print(fmt::format_string< Args... > fmt_str, Args &&... args)
Print formatted string via the default (empty-module) sink.
Definition trace_impl.hpp:1433
std::string format_trace_prefix(FormattingOptions const &opts)
Definition trace_impl.hpp:1488
void raise(Exception &&exception, std::source_location where=std::source_location::current())
Raise a concrete exception through Uni20's configured error boundary.
Definition trace_impl.hpp:2184
std::string formatRectangularContainerAsPresentationMatrix(const std::vector< std::vector< std::string > > &elems, FormattingOptions const &opts)
Definition trace_impl.hpp:1143
void PreconditionCall(const char *cond, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1934
uni20::presentation::styled_text formatItemText(const std::pair< std::string, bool > &name, const std::string &value, const FormattingOptions &opts, int available_width)
Definition trace_impl.hpp:1264
void append_optional_parameters(uni20::presentation::styled_text &text, FormattingOptions const &opts, uni20::presentation::styled_text const ¶meters, std::string_view style_kind, bool start_newline=false)
Definition trace_impl.hpp:1529
uni20::presentation::styled_text formatParametersTextForContext(std::vector< std::pair< std::string, bool > >::const_iterator b, const FormattingOptions &opts, trace_format_context context)
Definition trace_impl.hpp:1356
void DebugPreconditionFloatingEqCall(const char *a, const char *b, std::int64_t ulps, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:2014
void PreconditionFloatingEqCall(const char *a, const char *b, std::int64_t ulps, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1998
void CheckEqualCall(const char *a, const char *b, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1870
void TraceStackCall(const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1789
void DebugCheckFloatingEqCall(const char *a, const char *b, std::int64_t ulps, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1918
void DebugTraceStackOnceCall(const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1821
std::size_t getMaxLineWidth(const std::string &str, uni20::presentation::output_policy const &policy)
Definition trace_impl.hpp:1086
std::string formatItemString(const std::pair< std::string, bool > &name, const std::string &value, const FormattingOptions &opts, int available_width)
Definition trace_impl.hpp:1295
void PreconditionEqualCall(const char *a, const char *b, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1966
FormattingOptions & get_formatting_options(const std::string &module="")
get the FormattingOptions object for a given module; use "" as the module name (or default parameter)...
Definition trace_impl.hpp:528
void DebugPreconditionCall(const char *cond, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1950
void append_trace_module_location(uni20::presentation::styled_text &text, FormattingOptions const &opts, std::string_view label, std::string_view style_kind, const char *module, const char *file, int line)
Definition trace_impl.hpp:1502
std::string formatValue(const T &value, FormattingOptions const &opts)
Format a non-container, non-Uni20-scalar type with an fmt formatter.
Definition trace_impl.hpp:579
void append_parameter_separator(uni20::presentation::styled_text &text, FormattingOptions const &opts, std::string_view style_kind, bool start_newline)
Definition trace_impl.hpp:1514
void DebugCheckEqualCall(const char *a, const char *b, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1886
std::string trim(const std::string &s)
Definition trace_impl.hpp:923
void DebugTraceOnceCall(const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1603
uni20::presentation::styled_text formatParameterListText(const char *exprList, const FormattingOptions &opts, const Args &... args)
Definition trace_impl.hpp:1411
uni20::presentation::styled_text format_trace_prefix_text(FormattingOptions const &opts)
Definition trace_impl.hpp:1464
std::vector< std::pair< std::string, bool > > parseNames(std::string_view s)
Definition trace_impl.hpp:958
uni20::presentation::styled_text formatParameterListTextForContext(const char *exprList, const FormattingOptions &opts, trace_format_context context, const Args &... args)
Definition trace_impl.hpp:1419
void TraceStackOnceCall(const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1797
std::string formatValueForContext(MDS const &mds, FormattingOptions const &opts, int value_width, trace_format_context context, std::string_view label)
Definition trace_impl.hpp:902
trace_format_context
Definition trace_impl.hpp:695
void PanicCall(const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:2030
std::string formatContainerToStringImpl(const std::string &elem, uni20::presentation::output_policy const &policy, size_t max_width=0)
Definition trace_impl.hpp:1162
void DebugTraceModuleStackCall(const char *module, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1829
void DebugPreconditionEqualCall(const char *a, const char *b, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1982
uni20::presentation::styled_text formatParametersText(std::vector< std::pair< std::string, bool > >::const_iterator b, const FormattingOptions &opts)
Definition trace_impl.hpp:1350
bool canFormatAsPresentationMatrix(const std::vector< std::vector< std::string > > &elems)
Definition trace_impl.hpp:1128
void ErrorCall(const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:2045
void append_trace_location(uni20::presentation::styled_text &text, FormattingOptions const &opts, std::string_view label, std::string_view style_kind, const char *file, int line)
Definition trace_impl.hpp:1493
void ErrorIfCall(const char *cond, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:2066
std::string format_timestamp()
Definition trace_impl.hpp:1441
void TraceModuleCall(const char *module, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1572
std::string formatParameters(std::vector< std::pair< std::string, bool > >::const_iterator b, const FormattingOptions &opts)
Definition trace_impl.hpp:1362
uni20::presentation::styled_text format_diagnostic(Error const &error, uni20::presentation::output_policy const &policy)
Format a structured diagnostic using its ADL presentation report and attached context.
Definition trace_impl.hpp:2159
bool should_show_thread_id(FormattingOptions const &opts)
Definition trace_impl.hpp:1455
void DebugTraceModuleCall(const char *module, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1619
bool isMultiline(const std::string &str)
Definition trace_impl.hpp:1064
void CheckFloatingEqCall(const char *a, const char *b, std::int64_t ulps, const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1902
void DebugTraceStackCall(const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1813
void TraceOnceCall(const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1556
size_t maxWidth(const std::string &str, uni20::presentation::output_policy const &policy)
Definition trace_impl.hpp:1108
void TraceCall(const char *exprList, const char *file, int line, const Args &... args)
Definition trace_impl.hpp:1541
std::string formatParameterList(const char *exprList, const FormattingOptions &opts, const Args &... args)
Definition trace_impl.hpp:1427
std::string formatContainerToString(const std::string &elem, size_t max_width=0)
Definition trace_impl.hpp:1168
presentation::report_builder diagnostic_report(CublasError const &error)
Build a presentation report for a cuBLAS provider failure.
Definition cublas_error_presentation.hpp:18
std::string demangle(const char *name)
Turn a compiler‐mangled name into a human‐readable one.
Definition demangle.hpp:22
void warning(checked_format_string< Args... > format, Args &&... args)
Emit a non-fatal warning display message.
Definition display.hpp:403
std::string format_mdspan(MDS const &mds, output_policy const &policy, ElementFormatter &&formatter, mdspan_format_options const &options={})
Render every mdspan/tensor element as display-cell-aligned text art.
Definition presentation_mdspan.hpp:585
semantic_glyph
Names semantic glyphs independently of their rendered spelling.
Definition presentation.hpp:117
std::string render_text(std::string_view text, output_policy const &policy)
Render raw UTF-8 text through charset and ASCII fallback policy.
Definition presentation.cpp:1231
std::string indent_text(std::string_view text, std::size_t spaces, output_policy const &policy, bool indent_first)
Indent each rendered line by a fixed number of spaces.
Definition presentation.cpp:2690
bool should_emit_color(output_policy const &policy)
Return whether a policy currently permits ANSI color output.
Definition presentation.cpp:1211
output_policy plain_policy()
Build a policy for plain file/log rendering with no ANSI color.
Definition presentation.cpp:1195
std::string render_glyph(semantic_glyph glyph, output_policy const &policy)
Render a semantic glyph according to an output policy.
Definition presentation.cpp:1218
color_mode
Selects when terminal color/style control sequences may be emitted.
Definition presentation.hpp:28
std::string format_real(T value, numeric_format_options const &options)
Format a real scalar value according to numeric presentation options.
Definition presentation.hpp:913
std::string format_complex(T const &value, numeric_format_options const &options)
Format a complex value as real+imagi.
Definition presentation.hpp:928
mdspan_preview_result format_mdspan_preview(MDS const &mds, output_policy const &policy, ElementFormatter &&formatter, mdspan_preview_options const &options={})
Render a bounded mdspan/tensor preview without visiting omitted elements.
Definition presentation_mdspan.hpp:632
output_policy terminal_policy(std::FILE *stream)
Build a policy for terminal rendering.
Definition presentation.cpp:1186
std::string pad_left(std::string_view text, std::size_t target_width, output_policy const &policy)
Left-pad rendered text to a target width.
Definition presentation.cpp:2571
std::string render(styled_text const &text, output_policy const &policy)
Render styled text with color/style sequences only when policy allows.
Definition presentation.cpp:1289
styled_text render_report(report_builder const &report, output_policy const &policy)
Format a high-level report builder into styled text.
Definition presentation.cpp:2366
std::size_t display_width(std::string_view text, output_policy const &policy, std::size_t initial_column)
Measure rendered text width under the selected policy.
Definition presentation.cpp:2560
std::ptrdiff_t index_type
Definition types.hpp:19
std::optional< semantic_glyph > glyph
Definition presentation.cpp:2435
bool iequals(std::string_view a, std::string_view b)
Definition string_util.hpp:52
Bounded preview controls for mdspan and tensor display.
Definition presentation_mdspan.hpp:51
mdspan_format_options format
Definition presentation_mdspan.hpp:52
Output policy shared by presentation renderers and layout helpers.
Definition presentation.hpp:186
color_mode color
Definition presentation.hpp:187
std::FILE * output_stream
Definition presentation.hpp:196
std::optional< std::size_t > wrap_width
Definition presentation.hpp:194