I suspect there’s a much easier way, but something along these lines can be made to work:
fn define(symbol: &mut Symbol, definition: Definition) {
thread_local! {
pub static TMP: Cell<Option<Box<str>>> = Cell::new(Some(String::from("").into()));
}
match symbol {
Symbol::Unknown(_) => {
// make a temporary replacement
let mut tmp = Symbol::Unknown(TMP.with(|cell| cell.take()).take().unwrap());
// put the real value in tmp
std::mem::swap(&mut tmp, symbol);
// build the new value
let mut tmp = if let Symbol::Unknown(ident) = tmp {
Symbol::Defined(ident, definition)
} else { panic!() };
// swap it back
std::mem::swap(&mut tmp, symbol);
// store our temporary string for next time
if let Symbol::Unknown(ident) = tmp {
TMP.with(|cell| cell.set(Some(ident)));
} else { panic!() }
},
Symbol::Defined(_, _) => todo!()
}
}