8#include <uni20/config.hpp>
17#include <unordered_map>
34void uni20_async_debug_value();
39concept HasAdlAsyncDebugValue =
requires(T
const&
value) { std::string{uni20_async_debug_value(
value)}; };
45template <
typename Extents> std::string format_shape_debug_info(Extents
const& extents)
47 using extents_type = std::remove_cvref_t<Extents>;
48 std::string
out =
"shape=(";
49 for (std::size_t axis = 0; axis < static_cast<std::size_t>(extents_type::rank()); ++axis)
51 if (axis != 0)
out +=
", ";
52 out += std::to_string(
static_cast<unsigned long long>(extents.extent(axis)));
61concept HasMdspanExtents =
requires(T
const&
value, std::size_t axis) {
62 std::remove_cvref_t<
decltype(
value.mdspan().extents())>::rank();
63 value.mdspan().extents().extent(axis);
69concept HasExtents =
requires(T
const&
value, std::size_t axis) {
70 std::remove_cvref_t<
decltype(
value.extents())>::rank();
71 value.extents().extent(axis);
77inline std::string sanitize_debug_value(std::string
value)
79 for (
char& ch :
value)
81 if (ch ==
'\n' || ch ==
'\r' || ch ==
'\t') ch =
' ';
90template <
typename T> std::string scalar_debug_info(T
const&
value)
93 if constexpr (std::is_same_v<value_type, bool>)
95 return value ?
"true" :
"false";
97 else if constexpr (std::is_same_v<value_type, char>)
99 return std::string{
"'"} +
value +
"'";
101 else if constexpr (std::is_integral_v<value_type>)
103 if constexpr (std::is_signed_v<value_type>)
104 return std::to_string(
static_cast<long long>(
value));
106 return std::to_string(
static_cast<unsigned long long>(
value));
112 else if constexpr (std::is_enum_v<value_type>)
114 using underlying_type = std::underlying_type_t<value_type>;
115 return scalar_debug_info(
static_cast<underlying_type
>(
value));
127template <
typename T> std::string default_debug_value(T
const&
value)
129 if constexpr (HasMdspanExtents<T>)
132 return format_shape_debug_info(
span.extents());
134 else if constexpr (HasExtents<T>)
136 return format_shape_debug_info(
value.extents());
140 return scalar_debug_info(
value);
148template <
typename T> std::string debug_value_for_value(T
const&
value)
150 if constexpr (HasAdlAsyncDebugValue<T>)
152 return sanitize_debug_value(std::string{uni20_async_debug_value(
value)});
156 return sanitize_debug_value(default_debug_value(
value));
180 return value_address_observer_ ? value_address_observer_(storage_address_) : fallback_value_address_;
191 if (value_constructed_observer_)
209 return "unconstructed";
211 return "constructed";
226 if (!value_text_observer_)
return {};
227 auto const* context = value_constructed_observer_ ? storage_address_ : fallback_value_address_;
228 return value_text_observer_(context);
237 [[nodiscard]] std::string_view
type()
const
239 std::lock_guard<std::mutex> lock(map_mutex_);
241 return std::string_view(it->second);
250#if 0 && UNI20_HAS_STACKTRACE
251 std::stacktrace
const& stack()
const {
return stack_; }
281 using ValueAddressObserver =
void const* (*)(
void const*)
noexcept;
282 using ValueConstructedObserver = bool (*)(
void const*)
noexcept;
283 using ValueTextObserver = std::string (*)(
void const*);
285 template <
typename T>
static std::string text_for_raw_value(
void const*
value)
287 return value ? detail::debug_value_for_value(*
static_cast<T const*
>(
value)) :
std::string{};
290 template <
typename T>
static std::string text_for_storage_value(
void const* control)
292 auto const*
value =
static_cast<T const*
>(shared_storage<T>::diagnostic_value_address_from_control(control));
293 return value ? detail::debug_value_for_value(*
value) :
std::string{};
296 template <
typename T>
298 : fallback_value_address_(static_cast<void const*>(
value)), type_key_(typeid(T).name()),
299 value_text_observer_(&
NodeInfo::text_for_raw_value<T>), global_index_(next_global_++)
300#if 0 && UNI20_HAS_STACKTRACE
302 stack_(
std::stacktrace::current())
306 template <
typename T>
307 explicit NodeInfo(shared_storage<T>
const& storage)
308 : storage_address_(storage.control_address()), fallback_value_address_(static_cast<void const*>(storage.get())),
309 type_key_(typeid(T).name()),
310 value_address_observer_(&shared_storage<T>::diagnostic_value_address_from_control),
311 value_constructed_observer_(&shared_storage<T>::diagnostic_constructed_from_control),
312 value_text_observer_(&
NodeInfo::text_for_storage_value<T>), global_index_(next_global_++)
313#if 0 && UNI20_HAS_STACKTRACE
315 stack_(
std::stacktrace::current())
320 inline static std::unordered_map<const char*, std::string> map_;
321 inline static std::mutex map_mutex_;
322 inline static std::atomic<uint64_t> next_global_ = 0;
325 void const* storage_address_{
nullptr};
326 void const* fallback_value_address_{
nullptr};
327 char const* type_key_;
328 ValueAddressObserver value_address_observer_{};
329 ValueConstructedObserver value_constructed_observer_{};
330 ValueTextObserver value_text_observer_{};
331 uint64_t global_index_;
332#if 0 && UNI20_HAS_STACKTRACE
333 std::stacktrace stack_;
Records node information for DAG/debugging visualization.
Definition async_node.hpp:171
std::string value_text() const
Returns type-specific display text for the current value.
Definition async_node.hpp:222
std::string_view type() const
Returns a human-readable, demangled type name.
Definition async_node.hpp:237
void const * storage_address() const
Returns the raw address of the shared storage control block.
Definition async_node.hpp:185
NodeValueState value_state() const noexcept
Reports the current construction state when observable.
Definition async_node.hpp:189
std::string_view value_state_label() const noexcept
Returns a stable label for the current construction state.
Definition async_node.hpp:202
NodeInfo()=delete
Deleted default constructor. NodeInfo can only be constructed via create.
bool value_constructed() const noexcept
Reports whether the value is currently constructed when observable.
Definition async_node.hpp:218
uint64_t global_index() const
Returns the unique global index of this node.
Definition async_node.hpp:247
static NodeInfo const * create(T const *value)
Returns the stacktrace of where the node was created.
Definition async_node.hpp:263
static NodeInfo const * create(shared_storage< T > const &storage)
Factory method to create a NodeInfo for shared async storage.
Definition async_node.hpp:275
void const * address() const
Returns the raw address of the current constructed value when observable.
Definition async_node.hpp:178
A lightweight, thread-safe, reference-counted storage for a single object.
Definition shared_storage.hpp:94
Concept for types that are either real or complex.
Definition scalar_concepts.hpp:87
locale_t value
Definition data_table.cpp:49
std::string format_scalar(T const &value, scalar_format_options const &options={})
Format any Uni20 real or complex scalar.
Definition scalar_io.hpp:367
This represents the reverse-mode adjoint for functions of complex variables, assuming a real-valued s...
Definition async/async.hpp:26
NodeValueState
Construction state reported for a debug DAG value node.
Definition async_node.hpp:24
@ Invalid
No storage or fallback value is available.
@ Constructed
A value is currently constructed.
@ Unconstructed
Storage exists but does not currently contain a value.
std::string demangle(const char *name)
Turn a compilerâmangled name into a humanâreadable one.
Definition demangle.hpp:22
typename optional_traits< T >::value_type value_type
Definition data_table.hpp:42
std::size_t span
Definition presentation.cpp:2017
Reference-counted optional in-place storage used by async buffers.