I've been working on a compiler and I'm struggling with turning a &self into &mut self. Admittedly I just want to provide a nice error message before exiting from a critical error. So the self can be consumed in the process of making it mutable. I've been trying to use a refcell to create interior mutability but apparently this isn't enough.
This is my where I'd like to handle a potential critical error
fn add_constants(&self, chunk: &mut Chunk) {
chunk.add_constant(match &self.source[self.previous.get_range()].parse::<Value>() {
Result::Ok(value) => *value,
Result::Err(err) => {
let temp: RefCell<&Parser> = RefCell::new(self);
error_at_current(&mut temp.borrow_mut(), &err.to_string());
std::process::exit(3); // this is a critical failure. If this occurs we can infer a deep parsing error in [Scanner::scan_token].
}
}, self.previous.line as usize)
}
This is my error handling at the moment
pub fn error_at_current(parser: &mut Parser, error_message: &str){
error_at(parser, error_message, parser.current.line as usize);
}
fn error_at(parser: &mut Parser, error_message: &str, line: usize){
print!("[line {}] Error", line);
if parser.panic_mode{
return;
}
match parser.current.token_type {
TokenType::TokenEOF => println!(" at end"),
TokenType::TokenError => (),
_ => println!(" at {}", &parser.source[parser.previous.get_range()])
}
println!("{}", error_message);
parser.had_error = true;
parser.panic_mode = true;
}