use crate::{
borrow_string, create_raw_string, free_raw_string, pxs_debug, python::{consume_error, get_fn_idx_from_name, pocketpy, var::pocketpyref_to_var, var_to_pocketpyref}, shared::{func::call_function, pxs_Runtime, var::pxs_Var}
};
pub(super) unsafe fn py_get_arg(argv: pocketpy::py_StackRef, i: usize) -> pocketpy::py_StackRef {
unsafe { argv.add(i) }
}
pub(super) unsafe fn py_assign(left: pocketpy::py_Ref, right: pocketpy::py_Ref) {
unsafe {
*left = *right;
}
}
#[allow(unused)]
pub(super) unsafe fn get_from_obj(obj: pocketpy::py_Ref, key: &str) -> Option<pocketpy::py_Ref> {
unsafe {
let c_key = create_raw_string!(key);
let pyname = pocketpy::py_name(c_key);
free_raw_string!(c_key);
let ok = pocketpy::py_getattr(obj, pyname);
if !ok {
#[allow(unused)]
let err = consume_error();
pxs_debug!("{err}");
None
} else {
Some(pocketpy::py_retval())
}
}
}
pub(super) unsafe fn get_string_from_obj(obj: pocketpy::py_Ref, key: String) -> String {
unsafe {
let c_key = create_raw_string!(key);
let pyname = pocketpy::py_name(c_key);
let res = pocketpy::py_getattr(obj, pyname);
if res {
let r0 = pocketpy::py_retval();
let val = pocketpy::py_tostr(r0);
let val = borrow_string!(val);
free_raw_string!(c_key);
val.to_string().clone()
} else {
let err = consume_error();
pxs_debug!("Python error when trying to get a string from obj: {err}");
err
}
}
}
pub(super) unsafe fn get_builtin(key: &str) -> pocketpy::py_Ref {
unsafe{
let ckey = create_raw_string!(key);
let module_name = create_raw_string!("builtins");
let builtins = pocketpy::py_getmodule(module_name);
let res = pocketpy::py_getdict(builtins, pocketpy::py_name(ckey));
free_raw_string!(ckey);
free_raw_string!(module_name);
res
}
}
#[allow(unused)]
pub(super) unsafe fn get_global(key: &str) -> pocketpy::py_Ref {
unsafe{
let ckey = create_raw_string!(key);
let res = pocketpy::py_getglobal(pocketpy::py_name(ckey));
free_raw_string!(ckey);
res
}
}
pub(super) unsafe fn raise(msg: &str) -> bool {
let c_msg = create_raw_string!(msg);
unsafe {
let ret_slot = pocketpy::py_retval();
pocketpy::py_newstr(ret_slot, c_msg);
free_raw_string!(c_msg);
return true;
}
}
pub(super) unsafe extern "C" fn pocketpy_bridge(argc: i32, argv: pocketpy::py_StackRef) -> bool {
if argc < 1 {
unsafe {
return raise("Python: argc < 1");
}
}
let c_name = unsafe { pocketpy::py_tostr(py_get_arg(argv, 0)) };
let name = borrow_string!(c_name);
let fn_idx = get_fn_idx_from_name(name);
if fn_idx.is_none() {
return unsafe { raise("Python: fn_idx is empty.") };
}
let fn_idx = fn_idx.unwrap();
let mut vars: Vec<pxs_Var> = vec![];
vars.push(pxs_Var::new_i64(pxs_Runtime::pxs_Python as i64));
for i in 1..argc {
let arg_ref = unsafe { py_get_arg(argv, i as usize) };
vars.push(pocketpyref_to_var(arg_ref));
}
let mut success = true;
unsafe {
let res = call_function(fn_idx, vars);
let ret_slot = pocketpy::py_retval();
var_to_pocketpyref(ret_slot, &res, None);
if res.is_exception() {
success = false;
}
}
success
}