intuicio_frontend_simpleton/library/
debug.rs

1use crate::{
2    library::bytes::Bytes, Array, Boolean, Function, Integer, Map, Real, Reference, Text, Type,
3};
4use intuicio_core::registry::Registry;
5use intuicio_derive::intuicio_function;
6use std::fmt::Write;
7
8#[intuicio_function(module_name = "debug")]
9pub fn assert(status: Reference, message: Reference) -> Reference {
10    if !*status.read::<Boolean>().unwrap() {
11        panic!("{}", message.read::<Text>().unwrap().as_str());
12    }
13    Reference::null()
14}
15
16fn debug_indent(result: &mut dyn Write, indent: usize) {
17    for _ in 0..(indent * 2) {
18        result.write_char(' ').unwrap()
19    }
20}
21
22fn debug_impl(value: &Reference, result: &mut dyn Write, indent: &mut Option<usize>) {
23    if value.is_null() {
24        write!(result, "null").unwrap();
25    } else if let Some(value) = value.read::<Boolean>() {
26        write!(result, "{}", *value).unwrap();
27    } else if let Some(value) = value.read::<Integer>() {
28        write!(result, "{}", *value).unwrap();
29    } else if let Some(value) = value.read::<Real>() {
30        write!(result, "{}", *value).unwrap();
31    } else if let Some(value) = value.read::<Text>() {
32        write!(result, r#""{}""#, value.as_str()).unwrap();
33    } else if let Some(value) = value.read::<Bytes>() {
34        write!(result, "#{:?}", value.get_ref()).unwrap();
35    } else if let Some(value) = value.read::<Array>() {
36        write!(result, "[").unwrap();
37        if !value.is_empty() {
38            if let Some(indent) = indent {
39                *indent += 1;
40                writeln!(result).unwrap();
41                debug_indent(result, *indent);
42            }
43            for (index, value) in value.iter().enumerate() {
44                if index > 0 {
45                    write!(result, ", ").unwrap();
46                    if let Some(indent) = indent {
47                        writeln!(result).unwrap();
48                        debug_indent(result, *indent);
49                    }
50                }
51                debug_impl(value, result, indent);
52            }
53            if let Some(indent) = indent {
54                *indent -= 1;
55                writeln!(result).unwrap();
56                debug_indent(result, *indent);
57            }
58        }
59        write!(result, "]").unwrap();
60    } else if let Some(value) = value.read::<Map>() {
61        write!(result, "{{").unwrap();
62        if !value.is_empty() {
63            if let Some(indent) = indent {
64                *indent += 1;
65                writeln!(result).unwrap();
66                debug_indent(result, *indent);
67            }
68            for (index, (key, value)) in value.iter().enumerate() {
69                if index > 0 {
70                    write!(result, ", ").unwrap();
71                    if let Some(indent) = indent {
72                        writeln!(result).unwrap();
73                        debug_indent(result, *indent);
74                    }
75                }
76                write!(result, "{}: ", key).unwrap();
77                debug_impl(value, result, indent);
78            }
79            if let Some(indent) = indent {
80                *indent -= 1;
81                writeln!(result).unwrap();
82                debug_indent(result, *indent);
83            }
84        }
85        write!(result, "}}").unwrap();
86    } else if let Some(value) = value.read::<Type>() {
87        write!(
88            result,
89            "<{}::{}>",
90            value.handle().unwrap().module_name().unwrap_or(""),
91            value.handle().unwrap().name()
92        )
93        .unwrap();
94    } else if let Some(value) = value.read::<Function>() {
95        let signature = value.handle().unwrap().signature();
96        write!(
97            result,
98            "<{}::{}(",
99            signature.module_name.as_deref().unwrap_or(""),
100            signature.name,
101        )
102        .unwrap();
103        for (index, parameter) in signature.inputs.iter().enumerate() {
104            if index > 0 {
105                write!(result, ", ").unwrap();
106            }
107            write!(result, "{}", parameter.name).unwrap();
108        }
109        write!(result, ")>").unwrap();
110    } else if let Some(value) = value.read_object() {
111        match &**value.type_handle() {
112            intuicio_core::types::Type::Struct(type_) => {
113                write!(
114                    result,
115                    "<{}::{}> {{",
116                    type_.module_name.as_deref().unwrap_or(""),
117                    type_.name
118                )
119                .unwrap();
120                if !type_.fields().is_empty() {
121                    if let Some(indent) = indent {
122                        *indent += 1;
123                        writeln!(result).unwrap();
124                        debug_indent(result, *indent);
125                    }
126                    for (index, field) in type_.fields().iter().enumerate() {
127                        if let Some(value) = value.read_field::<Reference>(&field.name) {
128                            if index > 0 {
129                                write!(result, ", ").unwrap();
130                                if let Some(indent) = indent {
131                                    writeln!(result).unwrap();
132                                    debug_indent(result, *indent);
133                                }
134                            }
135                            write!(result, "{}: ", field.name).unwrap();
136                            debug_impl(value, result, indent);
137                        } else {
138                            if index > 0 {
139                                write!(result, ", ").unwrap();
140                            }
141                            write!(result, "<?>").unwrap();
142                        }
143                    }
144                    if let Some(indent) = indent {
145                        *indent -= 1;
146                        writeln!(result).unwrap();
147                        debug_indent(result, *indent);
148                    }
149                }
150                write!(result, "}}").unwrap();
151            }
152            intuicio_core::types::Type::Enum(_) => {}
153        }
154    } else {
155        write!(result, "<?>").unwrap();
156    }
157}
158
159#[intuicio_function(module_name = "debug", use_registry)]
160pub fn debug(registry: &Registry, value: Reference, pretty: Reference) -> Reference {
161    let mut result = String::new();
162    let indent = Some(0);
163    debug_impl(
164        &value,
165        &mut result,
166        &mut if *pretty.read::<Boolean>().unwrap() {
167            indent
168        } else {
169            None
170        },
171    );
172    Reference::new_text(result, registry)
173}
174
175pub fn install(registry: &mut Registry) {
176    registry.add_function(assert::define_function(registry));
177    registry.add_function(debug::define_function(registry));
178}