1use crate::{
17 PipelineData, PipelineExecutionData, ShellError, Span, Value,
18 ast::{Block, PipelineElement},
19 engine::{EngineState, Stack},
20 ir::IrBlock,
21};
22use std::{fmt::Debug, ops::DerefMut};
23
24pub trait DebugContext: Clone + Copy + Debug {
31 #[allow(unused_variables)]
33 fn enter_block(engine_state: &EngineState, block: &Block) {}
34
35 #[allow(unused_variables)]
37 fn leave_block(engine_state: &EngineState, block: &Block) {}
38
39 #[allow(unused_variables)]
41 fn enter_element(engine_state: &EngineState, element: &PipelineElement) {}
42
43 #[allow(unused_variables)]
45 fn leave_element(
46 engine_state: &EngineState,
47 element: &PipelineElement,
48 result: &Result<PipelineData, ShellError>,
49 ) {
50 }
51
52 #[allow(unused_variables)]
54 fn enter_instruction(
55 engine_state: &EngineState,
56 stack: &Stack,
57 ir_block: &IrBlock,
58 instruction_index: usize,
59 registers: &[PipelineExecutionData],
60 ) {
61 }
62
63 #[allow(unused_variables)]
65 fn leave_instruction(
66 engine_state: &EngineState,
67 stack: &Stack,
68 ir_block: &IrBlock,
69 instruction_index: usize,
70 registers: &[PipelineExecutionData],
71 error: Option<&ShellError>,
72 ) {
73 }
74}
75
76#[derive(Clone, Copy, Debug)]
80pub struct WithDebug;
81
82impl DebugContext for WithDebug {
83 fn enter_block(engine_state: &EngineState, block: &Block) {
84 if let Ok(mut debugger) = engine_state.debugger.lock() {
85 debugger.deref_mut().enter_block(engine_state, block);
86 }
87 }
88
89 fn leave_block(engine_state: &EngineState, block: &Block) {
90 if let Ok(mut debugger) = engine_state.debugger.lock() {
91 debugger.deref_mut().leave_block(engine_state, block);
92 }
93 }
94
95 fn enter_element(engine_state: &EngineState, element: &PipelineElement) {
96 if let Ok(mut debugger) = engine_state.debugger.lock() {
97 debugger.deref_mut().enter_element(engine_state, element);
98 }
99 }
100
101 fn leave_element(
102 engine_state: &EngineState,
103 element: &PipelineElement,
104 result: &Result<PipelineData, ShellError>,
105 ) {
106 if let Ok(mut debugger) = engine_state.debugger.lock() {
107 debugger
108 .deref_mut()
109 .leave_element(engine_state, element, result);
110 }
111 }
112
113 fn enter_instruction(
114 engine_state: &EngineState,
115 stack: &Stack,
116 ir_block: &IrBlock,
117 instruction_index: usize,
118 registers: &[PipelineExecutionData],
119 ) {
120 if let Ok(mut debugger) = engine_state.debugger.lock() {
121 debugger.deref_mut().enter_instruction(
122 engine_state,
123 stack,
124 ir_block,
125 instruction_index,
126 registers,
127 )
128 }
129 }
130
131 fn leave_instruction(
132 engine_state: &EngineState,
133 stack: &Stack,
134 ir_block: &IrBlock,
135 instruction_index: usize,
136 registers: &[PipelineExecutionData],
137 error: Option<&ShellError>,
138 ) {
139 if let Ok(mut debugger) = engine_state.debugger.lock() {
140 debugger.deref_mut().leave_instruction(
141 engine_state,
142 stack,
143 ir_block,
144 instruction_index,
145 registers,
146 error,
147 )
148 }
149 }
150}
151
152#[derive(Clone, Copy, Debug)]
156pub struct WithoutDebug;
157
158impl DebugContext for WithoutDebug {}
159
160pub trait Debugger: Send + Debug {
164 fn activate(&mut self) {}
168
169 fn deactivate(&mut self) {}
174
175 #[allow(unused_variables)]
177 fn enter_block(&mut self, engine_state: &EngineState, block: &Block) {}
178
179 #[allow(unused_variables)]
181 fn leave_block(&mut self, engine_state: &EngineState, block: &Block) {}
182
183 #[allow(unused_variables)]
185 fn enter_element(&mut self, engine_state: &EngineState, pipeline_element: &PipelineElement) {}
186
187 #[allow(unused_variables)]
189 fn leave_element(
190 &mut self,
191 engine_state: &EngineState,
192 element: &PipelineElement,
193 result: &Result<PipelineData, ShellError>,
194 ) {
195 }
196
197 #[allow(unused_variables)]
202 fn enter_instruction(
203 &mut self,
204 engine_state: &EngineState,
205 stack: &Stack,
206 ir_block: &IrBlock,
207 instruction_index: usize,
208 registers: &[PipelineExecutionData],
209 ) {
210 }
211
212 #[allow(unused_variables)]
216 fn leave_instruction(
217 &mut self,
218 engine_state: &EngineState,
219 stack: &Stack,
220 ir_block: &IrBlock,
221 instruction_index: usize,
222 registers: &[PipelineExecutionData],
223 error: Option<&ShellError>,
224 ) {
225 }
226
227 #[allow(unused_variables)]
231 fn report(&self, engine_state: &EngineState, debugger_span: Span) -> Result<Value, ShellError> {
232 Ok(Value::nothing(debugger_span))
233 }
234}
235
236#[derive(Debug)]
240pub struct NoopDebugger;
241
242impl Debugger for NoopDebugger {}