1use std::cell::RefCell;
4use std::rc::Rc;
5
6use nifty_check::hir::Program;
7use nifty_runtime::{Backend, Ui, WakeHandler};
8
9use crate::app::{App, ErrorHandler};
10use crate::machine::RuntimeError;
11
12pub struct LiveApp<B: Backend> {
13 ui: Ui<B>,
14 on_error: ErrorHandler,
15 app: RefCell<Option<App<B>>>,
17}
18
19impl<B: Backend> LiveApp<B> {
20 pub fn new(backend: B, on_error: ErrorHandler) -> Self {
22 Self {
23 ui: Ui::new(backend),
24 on_error,
25 app: RefCell::new(None),
26 }
27 }
28
29 pub fn load(&self, program: Program) -> Result<(), RuntimeError> {
39 let next = match &*self.app.borrow() {
40 Some(running) => running.reload(program)?,
41 None => App::start(program, self.ui.clone(), Rc::clone(&self.on_error))?,
42 };
43 *self.app.borrow_mut() = Some(next);
44 Ok(())
45 }
46
47 #[must_use = "dropping the waker means `on_wake` never runs"]
50 pub fn waker(&self, on_wake: WakeHandler) -> B::Waker {
51 self.ui.waker(on_wake)
52 }
53
54 pub fn run(&self) {
56 self.ui.run();
57 }
58}
59
60impl<B: Backend> std::fmt::Debug for LiveApp<B> {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 f.debug_struct("LiveApp").finish_non_exhaustive()
63 }
64}