use crate::{
PipelineData, PipelineExecutionData, ShellError, Span, Value,
ast::{Block, PipelineElement},
engine::EngineState,
ir::IrBlock,
};
use std::{fmt::Debug, ops::DerefMut};
pub trait DebugContext: Clone + Copy + Debug {
#[allow(unused_variables)]
fn enter_block(engine_state: &EngineState, block: &Block) {}
#[allow(unused_variables)]
fn leave_block(engine_state: &EngineState, block: &Block) {}
#[allow(unused_variables)]
fn enter_element(engine_state: &EngineState, element: &PipelineElement) {}
#[allow(unused_variables)]
fn leave_element(
engine_state: &EngineState,
element: &PipelineElement,
result: &Result<PipelineData, ShellError>,
) {
}
#[allow(unused_variables)]
fn enter_instruction(
engine_state: &EngineState,
ir_block: &IrBlock,
instruction_index: usize,
registers: &[PipelineExecutionData],
) {
}
#[allow(unused_variables)]
fn leave_instruction(
engine_state: &EngineState,
ir_block: &IrBlock,
instruction_index: usize,
registers: &[PipelineExecutionData],
error: Option<&ShellError>,
) {
}
}
#[derive(Clone, Copy, Debug)]
pub struct WithDebug;
impl DebugContext for WithDebug {
fn enter_block(engine_state: &EngineState, block: &Block) {
if let Ok(mut debugger) = engine_state.debugger.lock() {
debugger.deref_mut().enter_block(engine_state, block);
}
}
fn leave_block(engine_state: &EngineState, block: &Block) {
if let Ok(mut debugger) = engine_state.debugger.lock() {
debugger.deref_mut().leave_block(engine_state, block);
}
}
fn enter_element(engine_state: &EngineState, element: &PipelineElement) {
if let Ok(mut debugger) = engine_state.debugger.lock() {
debugger.deref_mut().enter_element(engine_state, element);
}
}
fn leave_element(
engine_state: &EngineState,
element: &PipelineElement,
result: &Result<PipelineData, ShellError>,
) {
if let Ok(mut debugger) = engine_state.debugger.lock() {
debugger
.deref_mut()
.leave_element(engine_state, element, result);
}
}
fn enter_instruction(
engine_state: &EngineState,
ir_block: &IrBlock,
instruction_index: usize,
registers: &[PipelineExecutionData],
) {
if let Ok(mut debugger) = engine_state.debugger.lock() {
debugger.deref_mut().enter_instruction(
engine_state,
ir_block,
instruction_index,
registers,
)
}
}
fn leave_instruction(
engine_state: &EngineState,
ir_block: &IrBlock,
instruction_index: usize,
registers: &[PipelineExecutionData],
error: Option<&ShellError>,
) {
if let Ok(mut debugger) = engine_state.debugger.lock() {
debugger.deref_mut().leave_instruction(
engine_state,
ir_block,
instruction_index,
registers,
error,
)
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct WithoutDebug;
impl DebugContext for WithoutDebug {}
pub trait Debugger: Send + Debug {
fn activate(&mut self) {}
fn deactivate(&mut self) {}
#[allow(unused_variables)]
fn enter_block(&mut self, engine_state: &EngineState, block: &Block) {}
#[allow(unused_variables)]
fn leave_block(&mut self, engine_state: &EngineState, block: &Block) {}
#[allow(unused_variables)]
fn enter_element(&mut self, engine_state: &EngineState, pipeline_element: &PipelineElement) {}
#[allow(unused_variables)]
fn leave_element(
&mut self,
engine_state: &EngineState,
element: &PipelineElement,
result: &Result<PipelineData, ShellError>,
) {
}
#[allow(unused_variables)]
fn enter_instruction(
&mut self,
engine_state: &EngineState,
ir_block: &IrBlock,
instruction_index: usize,
registers: &[PipelineExecutionData],
) {
}
#[allow(unused_variables)]
fn leave_instruction(
&mut self,
engine_state: &EngineState,
ir_block: &IrBlock,
instruction_index: usize,
registers: &[PipelineExecutionData],
error: Option<&ShellError>,
) {
}
#[allow(unused_variables)]
fn report(&self, engine_state: &EngineState, debugger_span: Span) -> Result<Value, ShellError> {
Ok(Value::nothing(debugger_span))
}
}
#[derive(Debug)]
pub struct NoopDebugger;
impl Debugger for NoopDebugger {}