authorgravatar for me@tadeo.caTadeo Kondrak <me@tadeo.ca> 2020-10-03 15:26:07-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-10-03 21:29:29-04:00
log26546af1b892925e1cfeb06564c7296e85abc840
treec2a116f146f63f44c67bab8f684731b08eec41fe
parentd1e779cea82665a05a9e6e3427e8ea117f7a9eaf

Revert "Include dbg.h to third-party libs"

This reverts commit c8b4cc2ff9cf15a42f95b2302e02431a0004f5c8. This includes many C++ standard library headers: #include <algorithm> #include <chrono> #include <ctime> #include <iomanip> #include <ios> #include <iostream> #include <memory> #include <sstream> #include <string> #include <tuple> #include <type_traits> #include <vector> which adds more than a second of compile time for each file that includes the header: ir.cpp before: 8.041s ir.cpp after: 6.847s

5 files changed, 0 insertions(+), 910 deletions(-)

CMakeLists.txt-1
......@@ -257,7 +257,6 @@ target_include_directories(embedded_softfloat PUBLIC
257257)
258258include_directories("${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/include")
259259set(SOFTFLOAT_LIBRARIES embedded_softfloat)
260include_directories("${CMAKE_SOURCE_DIR}/deps/dbg-macro")
261260
262261find_package(Threads)
263262
deps/dbg-macro/LICENSE deleted-21
......@@ -1,21 +0,0 @@
1MIT License
2
3Copyright (c) 2019 David Peter <mail@david-peter.de>
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
deps/dbg-macro/README.md deleted-172
......@@ -1,172 +0,0 @@
1# `dbg(…)`
2
3[![Build Status](https://travis-ci.org/sharkdp/dbg-macro.svg?branch=master)](https://travis-ci.org/sharkdp/dbg-macro) [![Build status](https://ci.appveyor.com/api/projects/status/vmo9rw4te2wifkul/branch/master?svg=true)](https://ci.appveyor.com/project/sharkdp/dbg-macro) [![Try it online](https://img.shields.io/badge/try-online-f34b7d.svg)](https://repl.it/@sharkdp/dbg-macro-demo) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](dbg.h)
4
5*A macro for `printf`-style debugging fans.*
6
7Debuggers are great. But sometimes you just don't have the time or patience to set
8up everything correctly and just want a quick way to inspect some values at runtime.
9
10This projects provides a [single header file](dbg.h) with a `dbg(…)`
11macro that can be used in all circumstances where you would typically write
12`printf("…", …)` or `std::cout << …`. But it comes with a few extras.
13
14## Examples
15
16``` c++
17#include <vector>
18#include <dbg.h>
19
20// You can use "dbg(..)" in expressions:
21int factorial(int n) {
22 if (dbg(n <= 1)) {
23 return dbg(1);
24 } else {
25 return dbg(n * factorial(n - 1));
26 }
27}
28
29int main() {
30 std::string message = "hello";
31 dbg(message); // [example.cpp:15 (main)] message = "hello" (std::string)
32
33 const int a = 2;
34 const int b = dbg(3 * a) + 1; // [example.cpp:18 (main)] 3 * a = 6 (int)
35
36 std::vector<int> numbers{b, 13, 42};
37 dbg(numbers); // [example.cpp:21 (main)] numbers = {7, 13, 42} (size: 3) (std::vector<int>)
38
39 dbg("this line is executed"); // [example.cpp:23 (main)] this line is executed
40
41 factorial(4);
42
43 return 0;
44}
45```
46
47The code above produces this output ([try it yourself](https://repl.it/@sharkdp/dbg-macro-demo)):
48
49![dbg(…) macro output](https://i.imgur.com/NHEYk9A.png)
50
51## Features
52
53 * Easy to read, colorized output (colors auto-disable when the output is not an interactive terminal)
54 * Prints file name, line number, function name and the original expression
55 * Adds type information for the printed-out value
56 * Specialized pretty-printers for containers, pointers, string literals, enums, `std::optional`, etc.
57 * Can be used inside expressions (passing through the original value)
58 * The `dbg.h` header issues a compiler warning when included (so you don't forget to remove it).
59 * Compatible and tested with C++11, C++14 and C++17.
60
61## Installation
62
63To make this practical, the `dbg.h` header should to be readily available from all kinds of different
64places and in all kinds of environments. The quick & dirty way is to actually copy the header file
65to `/usr/include` or to clone the repository and symlink `dbg.h` to `/usr/include/dbg.h`.
66``` bash
67git clone https://github.com/sharkdp/dbg-macro
68sudo ln -s $(readlink -f dbg-macro/dbg.h) /usr/include/dbg.h
69```
70If you don't want to make untracked changes to your filesystem, check below if there is a package for
71your operating system or package manager.
72
73### On Arch Linux
74
75You can install [`dbg-macro` from the AUR](https://aur.archlinux.org/packages/dbg-macro/):
76``` bash
77yay -S dbg-macro
78```
79
80### With vcpkg
81
82You can install the [`dbg-macro` port](https://github.com/microsoft/vcpkg/tree/master/ports/dbg-macro) via:
83``` bash
84vcpkg install dbg-macro
85```
86
87## Configuration
88
89* Set the `DBG_MACRO_DISABLE` flag to disable the `dbg(…)` macro (i.e. to make it a no-op).
90* Set the `DBG_MACRO_NO_WARNING` flag to disable the *"'dbg.h' header is included in your code base"* warnings.
91
92## Advanced features
93
94### Hexadecimal, octal and binary format
95
96If you want to format integers in hexadecimal, octal or binary representation, you can
97simply wrap them in `dbg::hex(…)`, `dbg::oct(…)` or `dbg::bin(…)`:
98```c++
99const uint32_t secret = 12648430;
100dbg(dbg::hex(secret));
101```
102
103### Printing type names
104
105`dbg(…)` already prints the type for each value in parenthesis (see screenshot above). But
106sometimes you just want to print a type (maybe because you don't have a value for that type).
107In this case, you can use the `dbg::type<T>()` helper to pretty-print a given type `T`.
108For example:
109```c++
110template <typename T>
111void my_function_template() {
112 using MyDependentType = typename std::remove_reference<T>::type&&;
113 dbg(dbg::type<MyDependentType>());
114}
115```
116
117### Print the current time
118
119To print a timestamp, you can use the `dbg::time()` helper:
120```c++
121dbg(dbg::time());
122```
123
124### Customization
125
126If you want `dbg(…)` to work for your custom datatype, you can simply overload `operator<<` for
127`std::ostream&`:
128```c++
129std::ostream& operator<<(std::ostream& out, const user_defined_type& v) {
130 out << "…";
131 return out;
132}
133```
134
135If you want to modify the type name that is printed by `dbg(…)`, you can add a custom
136`get_type_name` overload:
137```c++
138// Customization point for type information
139namespace dbg {
140 std::string get_type_name(type_tag<bool>) {
141 return "truth value";
142 }
143}
144```
145
146## Development
147
148If you want to contribute to `dbg-macro`, here is how you can build the tests and demos:
149
150Make sure that the submodule(s) are up to date:
151```bash
152git submodule update --init
153```
154
155Then, use the typical `cmake` workflow. Usage of `-DCMAKE_CXX_STANDARD=17` is optional,
156but recommended in order to have the largest set of features enabled:
157```bash
158mkdir build
159cd build
160cmake .. -DCMAKE_CXX_STANDARD=17
161make
162```
163
164To run the tests, simply call:
165```bash
166make test
167```
168You can find the unit tests in `tests/basic.cpp`.
169
170## Acknowledgement
171
172This project is inspired by Rusts [`dbg!(…)` macro](https://doc.rust-lang.org/std/macro.dbg.html).
deps/dbg-macro/dbg.h deleted-711
......@@ -1,711 +0,0 @@
1/*****************************************************************************
2
3 dbg(...) macro
4
5License (MIT):
6
7 Copyright (c) 2019 David Peter <mail@david-peter.de>
8
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to
11 deal in the Software without restriction, including without limitation the
12 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13 sell copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 SOFTWARE.
26
27*****************************************************************************/
28
29#ifndef DBG_MACRO_DBG_H
30#define DBG_MACRO_DBG_H
31
32#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
33#define DBG_MACRO_UNIX
34#elif defined(_MSC_VER)
35#define DBG_MACRO_WINDOWS
36#endif
37
38#ifndef DBG_MACRO_NO_WARNING
39#pragma message("WARNING: the 'dbg.h' header is included in your code base")
40#endif // DBG_MACRO_NO_WARNING
41
42#include <algorithm>
43#include <chrono>
44#include <ctime>
45#include <iomanip>
46#include <ios>
47#include <iostream>
48#include <memory>
49#include <sstream>
50#include <string>
51#include <tuple>
52#include <type_traits>
53#include <vector>
54
55#ifdef DBG_MACRO_UNIX
56#include <unistd.h>
57#endif
58
59#if __cplusplus >= 201703L || defined(_MSC_VER)
60#define DBG_MACRO_CXX_STANDARD 17
61#elif __cplusplus >= 201402L
62#define DBG_MACRO_CXX_STANDARD 14
63#else
64#define DBG_MACRO_CXX_STANDARD 11
65#endif
66
67#if DBG_MACRO_CXX_STANDARD >= 17
68#include <optional>
69#include <variant>
70#endif
71
72namespace dbg {
73
74#ifdef DBG_MACRO_UNIX
75inline bool isColorizedOutputEnabled() {
76 return isatty(fileno(stderr));
77}
78#else
79inline bool isColorizedOutputEnabled() {
80 return true;
81}
82#endif
83
84struct time {};
85
86namespace pretty_function {
87
88// Compiler-agnostic version of __PRETTY_FUNCTION__ and constants to
89// extract the template argument in `type_name_impl`
90
91#if defined(__clang__)
92#define DBG_MACRO_PRETTY_FUNCTION __PRETTY_FUNCTION__
93static constexpr size_t PREFIX_LENGTH =
94 sizeof("const char *dbg::type_name_impl() [T = ") - 1;
95static constexpr size_t SUFFIX_LENGTH = sizeof("]") - 1;
96#elif defined(__GNUC__) && !defined(__clang__)
97#define DBG_MACRO_PRETTY_FUNCTION __PRETTY_FUNCTION__
98static constexpr size_t PREFIX_LENGTH =
99 sizeof("const char* dbg::type_name_impl() [with T = ") - 1;
100static constexpr size_t SUFFIX_LENGTH = sizeof("]") - 1;
101#elif defined(_MSC_VER)
102#define DBG_MACRO_PRETTY_FUNCTION __FUNCSIG__
103static constexpr size_t PREFIX_LENGTH =
104 sizeof("const char *__cdecl dbg::type_name_impl<") - 1;
105static constexpr size_t SUFFIX_LENGTH = sizeof(">(void)") - 1;
106#else
107#error "This compiler is currently not supported by dbg_macro."
108#endif
109
110} // namespace pretty_function
111
112// Formatting helpers
113
114template <typename T>
115struct print_formatted {
116 static_assert(std::is_integral<T>::value,
117 "Only integral types are supported.");
118
119 print_formatted(T value, int numeric_base)
120 : inner(value), base(numeric_base) {}
121
122 operator T() const { return inner; }
123
124 const char* prefix() const {
125 switch (base) {
126 case 8:
127 return "0o";
128 case 16:
129 return "0x";
130 case 2:
131 return "0b";
132 default:
133 return "";
134 }
135 }
136
137 T inner;
138 int base;
139};
140
141template <typename T>
142print_formatted<T> hex(T value) {
143 return print_formatted<T>{value, 16};
144}
145
146template <typename T>
147print_formatted<T> oct(T value) {
148 return print_formatted<T>{value, 8};
149}
150
151template <typename T>
152print_formatted<T> bin(T value) {
153 return print_formatted<T>{value, 2};
154}
155
156// Implementation of 'type_name<T>()'
157
158template <typename T>
159const char* type_name_impl() {
160 return DBG_MACRO_PRETTY_FUNCTION;
161}
162
163template <typename T>
164struct type_tag {};
165
166template <int&... ExplicitArgumentBarrier, typename T>
167std::string get_type_name(type_tag<T>) {
168 namespace pf = pretty_function;
169
170 std::string type = type_name_impl<T>();
171 return type.substr(pf::PREFIX_LENGTH,
172 type.size() - pf::PREFIX_LENGTH - pf::SUFFIX_LENGTH);
173}
174
175template <typename T>
176std::string type_name() {
177 if (std::is_volatile<T>::value) {
178 if (std::is_pointer<T>::value) {
179 return type_name<typename std::remove_volatile<T>::type>() + " volatile";
180 } else {
181 return "volatile " + type_name<typename std::remove_volatile<T>::type>();
182 }
183 }
184 if (std::is_const<T>::value) {
185 if (std::is_pointer<T>::value) {
186 return type_name<typename std::remove_const<T>::type>() + " const";
187 } else {
188 return "const " + type_name<typename std::remove_const<T>::type>();
189 }
190 }
191 if (std::is_pointer<T>::value) {
192 return type_name<typename std::remove_pointer<T>::type>() + "*";
193 }
194 if (std::is_lvalue_reference<T>::value) {
195 return type_name<typename std::remove_reference<T>::type>() + "&";
196 }
197 if (std::is_rvalue_reference<T>::value) {
198 return type_name<typename std::remove_reference<T>::type>() + "&&";
199 }
200 return get_type_name(type_tag<T>{});
201}
202
203inline std::string get_type_name(type_tag<short>) {
204 return "short";
205}
206
207inline std::string get_type_name(type_tag<unsigned short>) {
208 return "unsigned short";
209}
210
211inline std::string get_type_name(type_tag<long>) {
212 return "long";
213}
214
215inline std::string get_type_name(type_tag<unsigned long>) {
216 return "unsigned long";
217}
218
219inline std::string get_type_name(type_tag<std::string>) {
220 return "std::string";
221}
222
223template <typename T>
224std::string get_type_name(type_tag<std::vector<T, std::allocator<T>>>) {
225 return "std::vector<" + type_name<T>() + ">";
226}
227
228template <typename T1, typename T2>
229std::string get_type_name(type_tag<std::pair<T1, T2>>) {
230 return "std::pair<" + type_name<T1>() + ", " + type_name<T2>() + ">";
231}
232
233template <typename... T>
234std::string type_list_to_string() {
235 std::string result;
236 auto unused = {(result += type_name<T>() + ", ", 0)..., 0};
237 static_cast<void>(unused);
238
239 if (sizeof...(T) > 0) {
240 result.pop_back();
241 result.pop_back();
242 }
243 return result;
244}
245
246template <typename... T>
247std::string get_type_name(type_tag<std::tuple<T...>>) {
248 return "std::tuple<" + type_list_to_string<T...>() + ">";
249}
250
251template <typename T>
252inline std::string get_type_name(type_tag<print_formatted<T>>) {
253 return type_name<T>();
254}
255
256// Implementation of 'is_detected' to specialize for container-like types
257
258namespace detail_detector {
259
260struct nonesuch {
261 nonesuch() = delete;
262 ~nonesuch() = delete;
263 nonesuch(nonesuch const&) = delete;
264 void operator=(nonesuch const&) = delete;
265};
266
267template <typename...>
268using void_t = void;
269
270template <class Default,
271 class AlwaysVoid,
272 template <class...>
273 class Op,
274 class... Args>
275struct detector {
276 using value_t = std::false_type;
277 using type = Default;
278};
279
280template <class Default, template <class...> class Op, class... Args>
281struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
282 using value_t = std::true_type;
283 using type = Op<Args...>;
284};
285
286} // namespace detail_detector
287
288template <template <class...> class Op, class... Args>
289using is_detected = typename detail_detector::
290 detector<detail_detector::nonesuch, void, Op, Args...>::value_t;
291
292namespace detail {
293
294namespace {
295using std::begin;
296using std::end;
297#if DBG_MACRO_CXX_STANDARD < 17
298template <typename T>
299constexpr auto size(const T& c) -> decltype(c.size()) {
300 return c.size();
301}
302template <typename T, std::size_t N>
303constexpr std::size_t size(const T (&)[N]) {
304 return N;
305}
306#else
307using std::size;
308#endif
309} // namespace
310
311template <typename T>
312using detect_begin_t = decltype(detail::begin(std::declval<T>()));
313
314template <typename T>
315using detect_end_t = decltype(detail::end(std::declval<T>()));
316
317template <typename T>
318using detect_size_t = decltype(detail::size(std::declval<T>()));
319
320template <typename T>
321struct is_container {
322 static constexpr bool value =
323 is_detected<detect_begin_t, T>::value &&
324 is_detected<detect_end_t, T>::value &&
325 is_detected<detect_size_t, T>::value &&
326 !std::is_same<std::string,
327 typename std::remove_cv<
328 typename std::remove_reference<T>::type>::type>::value;
329};
330
331template <typename T>
332using ostream_operator_t =
333 decltype(std::declval<std::ostream&>() << std::declval<T>());
334
335template <typename T>
336struct has_ostream_operator : is_detected<ostream_operator_t, T> {};
337
338} // namespace detail
339
340// Helper to dbg(…)-print types
341template <typename T>
342struct print_type {};
343
344template <typename T>
345print_type<T> type() {
346 return print_type<T>{};
347}
348
349// Specializations of "pretty_print"
350
351template <typename T>
352inline void pretty_print(std::ostream& stream, const T& value, std::true_type) {
353 stream << value;
354}
355
356template <typename T>
357inline void pretty_print(std::ostream&, const T&, std::false_type) {
358 static_assert(detail::has_ostream_operator<const T&>::value,
359 "Type does not support the << ostream operator");
360}
361
362template <typename T>
363inline typename std::enable_if<!detail::is_container<const T&>::value &&
364 !std::is_enum<T>::value,
365 bool>::type
366pretty_print(std::ostream& stream, const T& value) {
367 pretty_print(stream, value,
368 typename detail::has_ostream_operator<const T&>::type{});
369 return true;
370}
371
372inline bool pretty_print(std::ostream& stream, const bool& value) {
373 stream << std::boolalpha << value;
374 return true;
375}
376
377inline bool pretty_print(std::ostream& stream, const char& value) {
378 const bool printable = value >= 0x20 && value <= 0x7E;
379
380 if (printable) {
381 stream << "'" << value << "'";
382 } else {
383 stream << "'\\x" << std::setw(2) << std::setfill('0') << std::hex
384 << std::uppercase << (0xFF & value) << "'";
385 }
386 return true;
387}
388
389template <typename P>
390inline bool pretty_print(std::ostream& stream, P* const& value) {
391 if (value == nullptr) {
392 stream << "nullptr";
393 } else {
394 stream << value;
395 }
396 return true;
397}
398
399template <typename T, typename Deleter>
400inline bool pretty_print(std::ostream& stream,
401 std::unique_ptr<T, Deleter>& value) {
402 pretty_print(stream, value.get());
403 return true;
404}
405
406template <typename T>
407inline bool pretty_print(std::ostream& stream, std::shared_ptr<T>& value) {
408 pretty_print(stream, value.get());
409 stream << " (use_count = " << value.use_count() << ")";
410
411 return true;
412}
413
414template <size_t N>
415inline bool pretty_print(std::ostream& stream, const char (&value)[N]) {
416 stream << value;
417 return false;
418}
419
420template <>
421inline bool pretty_print(std::ostream& stream, const char* const& value) {
422 stream << '"' << value << '"';
423 return true;
424}
425
426template <size_t Idx>
427struct pretty_print_tuple {
428 template <typename... Ts>
429 static void print(std::ostream& stream, const std::tuple<Ts...>& tuple) {
430 pretty_print_tuple<Idx - 1>::print(stream, tuple);
431 stream << ", ";
432 pretty_print(stream, std::get<Idx>(tuple));
433 }
434};
435
436template <>
437struct pretty_print_tuple<0> {
438 template <typename... Ts>
439 static void print(std::ostream& stream, const std::tuple<Ts...>& tuple) {
440 pretty_print(stream, std::get<0>(tuple));
441 }
442};
443
444template <typename... Ts>
445inline bool pretty_print(std::ostream& stream, const std::tuple<Ts...>& value) {
446 stream << "{";
447 pretty_print_tuple<sizeof...(Ts) - 1>::print(stream, value);
448 stream << "}";
449
450 return true;
451}
452
453template <>
454inline bool pretty_print(std::ostream& stream, const std::tuple<>&) {
455 stream << "{}";
456
457 return true;
458}
459
460template <>
461inline bool pretty_print(std::ostream& stream, const time&) {
462 using namespace std::chrono;
463
464 const auto now = system_clock::now();
465 const auto us =
466 duration_cast<microseconds>(now.time_since_epoch()).count() % 1000000;
467 const auto hms = system_clock::to_time_t(now);
468 const std::tm* tm = std::localtime(&hms);
469 stream << "current time = " << std::put_time(tm, "%H:%M:%S") << '.'
470 << std::setw(6) << std::setfill('0') << us;
471
472 return false;
473}
474
475// Converts decimal integer to binary string
476template <typename T>
477std::string decimalToBinary(T n) {
478 const size_t length = 8 * sizeof(T);
479 std::string toRet;
480 toRet.resize(length);
481
482 for (size_t i = 0; i < length; ++i) {
483 const auto bit_at_index_i = (n >> i) & 1;
484 toRet[length - 1 - i] = bit_at_index_i + '0';
485 }
486
487 return toRet;
488}
489
490template <typename T>
491inline bool pretty_print(std::ostream& stream,
492 const print_formatted<T>& value) {
493 if (value.inner < 0) {
494 stream << "-";
495 }
496 stream << value.prefix();
497
498 // Print using setbase
499 if (value.base != 2) {
500 stream << std::setw(sizeof(T)) << std::setfill('0')
501 << std::setbase(value.base) << std::uppercase;
502
503 if (value.inner >= 0) {
504 // The '+' sign makes sure that a uint_8 is printed as a number
505 stream << +value.inner;
506 } else {
507 using unsigned_type = typename std::make_unsigned<T>::type;
508 stream << +(static_cast<unsigned_type>(-(value.inner + 1)) + 1);
509 }
510 } else {
511 // Print for binary
512 if (value.inner >= 0) {
513 stream << decimalToBinary(value.inner);
514 } else {
515 using unsigned_type = typename std::make_unsigned<T>::type;
516 stream << decimalToBinary<unsigned_type>(
517 static_cast<unsigned_type>(-(value.inner + 1)) + 1);
518 }
519 }
520
521 return true;
522}
523
524template <typename T>
525inline bool pretty_print(std::ostream& stream, const print_type<T>&) {
526 stream << type_name<T>();
527
528 stream << " [sizeof: " << sizeof(T) << " byte, ";
529
530 stream << "trivial: ";
531 if (std::is_trivial<T>::value) {
532 stream << "yes";
533 } else {
534 stream << "no";
535 }
536
537 stream << ", standard layout: ";
538 if (std::is_standard_layout<T>::value) {
539 stream << "yes";
540 } else {
541 stream << "no";
542 }
543 stream << "]";
544
545 return false;
546}
547
548template <typename Container>
549inline typename std::enable_if<detail::is_container<const Container&>::value,
550 bool>::type
551pretty_print(std::ostream& stream, const Container& value) {
552 stream << "{";
553 const size_t size = detail::size(value);
554 const size_t n = std::min(size_t{10}, size);
555 size_t i = 0;
556 using std::begin;
557 using std::end;
558 for (auto it = begin(value); it != end(value) && i < n; ++it, ++i) {
559 pretty_print(stream, *it);
560 if (i != n - 1) {
561 stream << ", ";
562 }
563 }
564
565 if (size > n) {
566 stream << ", ...";
567 stream << " size:" << size;
568 }
569
570 stream << "}";
571 return true;
572}
573
574template <typename Enum>
575inline typename std::enable_if<std::is_enum<Enum>::value, bool>::type
576pretty_print(std::ostream& stream, Enum const& value) {
577 using UnderlyingType = typename std::underlying_type<Enum>::type;
578 stream << static_cast<UnderlyingType>(value);
579
580 return true;
581}
582
583inline bool pretty_print(std::ostream& stream, const std::string& value) {
584 stream << '"' << value << '"';
585 return true;
586}
587
588template <typename T1, typename T2>
589inline bool pretty_print(std::ostream& stream, const std::pair<T1, T2>& value) {
590 stream << "{";
591 pretty_print(stream, value.first);
592 stream << ", ";
593 pretty_print(stream, value.second);
594 stream << "}";
595 return true;
596}
597
598#if DBG_MACRO_CXX_STANDARD >= 17
599
600template <typename T>
601inline bool pretty_print(std::ostream& stream, const std::optional<T>& value) {
602 if (value) {
603 stream << '{';
604 pretty_print(stream, *value);
605 stream << '}';
606 } else {
607 stream << "nullopt";
608 }
609
610 return true;
611}
612
613template <typename... Ts>
614inline bool pretty_print(std::ostream& stream,
615 const std::variant<Ts...>& value) {
616 stream << "{";
617 std::visit([&stream](auto&& arg) { pretty_print(stream, arg); }, value);
618 stream << "}";
619
620 return true;
621}
622
623#endif
624
625class DebugOutput {
626 public:
627 DebugOutput(const char* filepath,
628 int line,
629 const char* function_name,
630 const char* expression)
631 : m_use_colorized_output(isColorizedOutputEnabled()),
632 m_filepath(filepath),
633 m_line(line),
634 m_function_name(function_name),
635 m_expression(expression) {
636 const std::size_t path_length = m_filepath.length();
637 if (path_length > MAX_PATH_LENGTH) {
638 m_filepath = ".." + m_filepath.substr(path_length - MAX_PATH_LENGTH,
639 MAX_PATH_LENGTH);
640 }
641 }
642
643 template <typename T>
644 T&& print(const std::string& type, T&& value) const {
645 const T& ref = value;
646 std::stringstream stream_value;
647 const bool print_expr_and_type = pretty_print(stream_value, ref);
648
649 std::stringstream output;
650 output << ansi(ANSI_DEBUG) << "[" << m_filepath << ":" << m_line << " ("
651 << m_function_name << ")] " << ansi(ANSI_RESET);
652 if (print_expr_and_type) {
653 output << ansi(ANSI_EXPRESSION) << m_expression << ansi(ANSI_RESET)
654 << " = ";
655 }
656 output << ansi(ANSI_VALUE) << stream_value.str() << ansi(ANSI_RESET);
657 if (print_expr_and_type) {
658 output << " (" << ansi(ANSI_TYPE) << type << ansi(ANSI_RESET) << ")";
659 }
660 output << std::endl;
661 std::cerr << output.str();
662
663 return std::forward<T>(value);
664 }
665
666 private:
667 const char* ansi(const char* code) const {
668 if (m_use_colorized_output) {
669 return code;
670 } else {
671 return ANSI_EMPTY;
672 }
673 }
674
675 const bool m_use_colorized_output;
676
677 std::string m_filepath;
678 const int m_line;
679 const std::string m_function_name;
680 const std::string m_expression;
681
682 static constexpr std::size_t MAX_PATH_LENGTH = 20;
683
684 static constexpr const char* const ANSI_EMPTY = "";
685 static constexpr const char* const ANSI_DEBUG = "\x1b[02m";
686 static constexpr const char* const ANSI_EXPRESSION = "\x1b[36m";
687 static constexpr const char* const ANSI_VALUE = "\x1b[01m";
688 static constexpr const char* const ANSI_TYPE = "\x1b[32m";
689 static constexpr const char* const ANSI_RESET = "\x1b[0m";
690};
691
692// Identity function to suppress "-Wunused-value" warnings in DBG_MACRO_DISABLE
693// mode
694template <typename T>
695T&& identity(T&& t) {
696 return std::forward<T>(t);
697}
698
699} // namespace dbg
700
701#ifndef DBG_MACRO_DISABLE
702// We use a variadic macro to support commas inside expressions (e.g.
703// initializer lists):
704#define dbg(...) \
705 dbg::DebugOutput(__FILE__, __LINE__, __func__, #__VA_ARGS__) \
706 .print(dbg::type_name<decltype(__VA_ARGS__)>(), (__VA_ARGS__))
707#else
708#define dbg(...) dbg::identity(__VA_ARGS__)
709#endif // DBG_MACRO_DISABLE
710
711#endif // DBG_MACRO_DBG_H
src/stage1/all_types.hpp-5
......@@ -18,11 +18,6 @@
1818#include "target.hpp"
1919#include "tokenizer.hpp"
2020
21#ifndef NDEBUG
22#define DBG_MACRO_NO_WARNING
23#include <dbg.h>
24#endif
25
2621struct AstNode;
2722struct ZigFn;
2823struct Scope;