1use std::cell::RefCell;
2
3#[macro_use]
4extern crate lazy_static;
5
6#[macro_use]
7mod index;
8
9lazy_static! {
10 pub static ref DEBUG_ENABLED: bool = {
11 use std::env;
12 env::var("CHALK_DEBUG")
13 .ok()
14 .and_then(|s| s.parse::<u32>().ok())
15 .map(|x| x >= 2)
16 .unwrap_or(false)
17 };
18 pub static ref INFO_ENABLED: bool = {
19 use std::env;
20 env::var("CHALK_DEBUG")
21 .ok()
22 .and_then(|s| s.parse::<u32>().ok())
23 .map(|x| x >= 1)
24 .unwrap_or(false)
25 };
26}
27
28thread_local! {
29 pub(crate) static INDENT: RefCell<Vec<String>> = RefCell::new(vec![]);
30}
31
32const OVERFLOW_DEPTH: usize = 100;
36
37#[macro_export]
38macro_rules! debug {
39 ($($t:tt)*) => {
40 if *$crate::DEBUG_ENABLED {
41 $crate::dump(&format!($($t)*), "");
42 }
43 }
44}
45
46#[macro_export]
47macro_rules! debug_heading {
48 ($($t:tt)*) => {
49 let _ = &if *$crate::DEBUG_ENABLED {
50 let string = format!($($t)*);
51 $crate::dump(&string, " {");
52 $crate::Indent::new(true, string)
53 } else {
54 $crate::Indent::new(false, String::new())
55 };
56 }
57}
58
59#[macro_export]
60macro_rules! info {
61 ($($t:tt)*) => {
62 if *$crate::INFO_ENABLED {
63 $crate::dump(&format!($($t)*), "");
64 }
65 }
66}
67
68#[macro_export]
69macro_rules! info_heading {
70 ($($t:tt)*) => {
71 let _ = &if *$crate::INFO_ENABLED {
72 let string = format!($($t)*);
73 $crate::dump(&string, " {");
74 $crate::Indent::new(true, string)
75 } else {
76 $crate::Indent::new(false, String::new())
77 };
78 }
79}
80
81pub fn dump(string: &str, suffix: &str) {
82 let indent = INDENT.with(|i| i.borrow().len());
83 let mut first = true;
84 for line in string.lines() {
85 if first {
86 for _ in 0..indent {
87 eprint!(": ");
88 }
89 eprint!("| ");
90 } else {
91 eprintln!();
92 for _ in 0..indent {
93 eprint!(": ");
94 }
95 eprint!(": ");
96 }
97 eprint!("{}", line);
98 first = false;
99 }
100
101 eprintln!("{}", suffix);
102}
103
104pub struct Indent {
105 enabled: bool,
106}
107
108impl Indent {
109 pub fn new(enabled: bool, value: String) -> Self {
110 if enabled {
111 INDENT.with(|i| {
112 i.borrow_mut().push(value);
113 if i.borrow().len() > OVERFLOW_DEPTH {
114 eprintln!("CHALK_DEBUG OVERFLOW:");
115 for v in i.borrow().iter().rev() {
116 eprintln!("- {}", v);
117 }
118 panic!("CHALK_DEBUG OVERFLOW")
119 }
120 });
121 }
122 Indent { enabled }
123 }
124}
125
126impl Drop for Indent {
127 fn drop(&mut self) {
128 if self.enabled {
129 INDENT.with(|i| i.borrow_mut().pop().unwrap());
130 dump("}", "");
131 }
132 }
133}