nu_protocol/engine/
error_handler.rs

1use crate::RegId;
2
3/// Describes an error handler stored during IR evaluation.
4#[derive(Debug, Clone, Copy)]
5pub struct ErrorHandler {
6    /// Instruction index within the block that will handle the error
7    pub handler_index: usize,
8    /// Register to put the error information into, when an error occurs
9    pub error_register: Option<RegId>,
10}
11
12/// Keeps track of error handlers pushed during evaluation of an IR block.
13#[derive(Debug, Clone, Default)]
14pub struct ErrorHandlerStack {
15    handlers: Vec<ErrorHandler>,
16}
17
18impl ErrorHandlerStack {
19    pub const fn new() -> ErrorHandlerStack {
20        ErrorHandlerStack { handlers: vec![] }
21    }
22
23    /// Get the current base of the stack, which establishes a frame.
24    pub fn get_base(&self) -> usize {
25        self.handlers.len()
26    }
27
28    /// Push a new error handler onto the stack.
29    pub fn push(&mut self, handler: ErrorHandler) {
30        self.handlers.push(handler);
31    }
32
33    /// Try to pop an error handler from the stack. Won't go below `base`, to avoid retrieving a
34    /// handler belonging to a parent frame.
35    pub fn pop(&mut self, base: usize) -> Option<ErrorHandler> {
36        if self.handlers.len() > base {
37            self.handlers.pop()
38        } else {
39            None
40        }
41    }
42
43    /// Reset the stack to the state it was in at the beginning of the frame, in preparation to
44    /// return control to the parent frame.
45    pub fn leave_frame(&mut self, base: usize) {
46        if self.handlers.len() >= base {
47            self.handlers.truncate(base);
48        } else {
49            panic!(
50                "ErrorHandlerStack bug: tried to leave frame at {base}, but current base is {}",
51                self.get_base()
52            )
53        }
54    }
55}