use core::mem;
#[cfg(feature = "io")]
use drone_core::ffi::CStr;
#[cfg(feature = "io")]
use drone_micropython_raw::mp_lexer_new_from_file;
use drone_micropython_raw::{
mp_call_function_0, mp_compile, mp_lexer_new_from_str_len, mp_lexer_t,
mp_obj_print_exception, mp_obj_t, mp_parse, mp_parse_input_kind_t,
mp_plat_print, nlr_pop, nlr_push, MP_QSTR__lt_stdin_gt_, MP_EMIT_OPT_NONE,
};
#[derive(Debug, Fail)]
#[fail(display = "MicroPython uncaught exception.")]
pub struct UncaughtException;
pub(crate) unsafe fn exec_source(
source: &str,
) -> Result<(), UncaughtException> {
exec(|| {
mp_lexer_new_from_str_len(
MP_QSTR__lt_stdin_gt_ as _,
source.as_ptr(),
source.len(),
0,
)
})
}
#[cfg(feature = "io")]
pub(crate) unsafe fn exec_path(path: &CStr) -> Result<(), UncaughtException> {
exec(|| mp_lexer_new_from_file(path.as_ptr()))
}
unsafe fn exec<F>(f: F) -> Result<(), UncaughtException>
where
F: FnOnce() -> *mut mp_lexer_t,
{
exec_raw_fun(|| {
let lex = f();
let source_name = (*lex).source_name;
let mut parse_tree =
mp_parse(lex, mp_parse_input_kind_t::MP_PARSE_FILE_INPUT);
mp_compile(&mut parse_tree, source_name, MP_EMIT_OPT_NONE, false)
})
}
unsafe fn exec_raw_fun<F>(f: F) -> Result<(), UncaughtException>
where
F: FnOnce() -> mp_obj_t,
{
let mut nlr = mem::uninitialized();
if nlr_push(&mut nlr) == 0 {
mp_call_function_0(f());
nlr_pop();
Ok(())
} else {
mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
Err(UncaughtException)
}
}