polydat_core/library/
log_levels.rs1use crate::ast::Value;
27
28fn log_at(level: crate::library::support::audit::LogLevel, fn_name: &str, value: &Value) {
29 let msg = format!("{fn_name}: {}", value.to_display_string());
30 crate::library::support::audit::log(level, &msg);
31}
32
33#[crate::polydat_node(category = Diagnostic, purity = SideChannel(LogBuffer))]
34fn log_debug(value: Value) -> Value {
35 log_at(
36 crate::library::support::audit::LogLevel::Debug,
37 "log_debug",
38 &value,
39 );
40 value
41}
42
43#[crate::polydat_node(category = Diagnostic, purity = SideChannel(LogBuffer))]
44fn log_info(value: Value) -> Value {
45 log_at(
46 crate::library::support::audit::LogLevel::Info,
47 "log_info",
48 &value,
49 );
50 value
51}
52
53#[crate::polydat_node(category = Diagnostic, purity = SideChannel(LogBuffer))]
54fn log_warn(value: Value) -> Value {
55 log_at(
56 crate::library::support::audit::LogLevel::Warn,
57 "log_warn",
58 &value,
59 );
60 value
61}
62
63#[crate::polydat_node(category = Diagnostic, purity = SideChannel(LogBuffer))]
64fn log_error(value: Value) -> Value {
65 log_at(
66 crate::library::support::audit::LogLevel::Error,
67 "log_error",
68 &value,
69 );
70 value
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use crate::ast::{PolydatNode, PortType, Slot};
77
78 #[test]
79 fn log_debug_passthrough() {
80 let node = LogDebug::new(PortType::Str);
81 let mut out = [Value::None];
82 node.eval(&[Value::Str("hello".into())], &mut out);
83 assert_eq!(out[0].as_str(), "hello");
84 }
85
86 #[test]
87 fn log_info_passthrough() {
88 let node = LogInfo::new(PortType::Bool);
89 let mut out = [Value::None];
90 node.eval(&[Value::Bool(true)], &mut out);
91 assert!(out[0].as_bool());
92 }
93
94 #[test]
95 fn log_warn_passthrough() {
96 let node = LogWarn::new(PortType::U64);
97 let mut out = [Value::None];
98 node.eval(&[Value::U64(42)], &mut out);
99 assert_eq!(out[0].as_u64(), 42);
100 }
101
102 #[test]
103 fn log_error_passthrough() {
104 let node = LogError::new(PortType::F64);
105 let mut out = [Value::None];
106 node.eval(&[Value::F64(1.5)], &mut out);
107 assert_eq!(out[0].as_f64(), 1.5);
108 }
109
110 #[test]
111 fn log_node_meta_has_one_input_one_output() {
112 let node = LogInfo::new(PortType::Str);
113 assert_eq!(node.meta().ins.len(), 1);
114 assert_eq!(node.meta().outs.len(), 1);
115 assert_eq!(node.meta().name, "log_info");
116 }
117
118 #[test]
119 fn log_info_meta_tracks_constructor_port_type() {
120 let node = LogInfo::new(PortType::Bool);
121 assert_eq!(node.meta().outs[0].typ, PortType::Bool);
122 if let Slot::Wire(p) = &node.meta().ins[0] {
123 assert_eq!(p.typ, PortType::Bool);
124 } else {
125 panic!("expected Slot::Wire");
126 }
127 }
128
129 #[test]
130 fn log_purity_is_side_channel() {
131 use crate::ast::{Purity, SideChannelSink};
132 let node = LogInfo::new(PortType::U64);
133 let p = node.purity();
134 assert!(matches!(
135 p,
136 Purity::SideChannel {
137 sink: SideChannelSink::LogBuffer
138 }
139 ));
140 }
141}