#[allow(unused)]
#[cfg(test)]
mod tests {
use std::{
ffi::{CStr, CString, c_char, c_void},
ptr,
};
use pixelscript::{
lua::LuaScripting,
python::PythonScripting,
shared::{
PixelScript, PtrMagic, pxs_Runtime,
var::{pxs_Var, pxs_VarT},
},
*,
};
macro_rules! create_raw_string {
($rstr:expr) => {{ CString::new($rstr).unwrap().into_raw() }};
}
macro_rules! free_raw_string {
($rptr:expr) => {{
if !$rptr.is_null() {
unsafe {
let _ = std::ffi::CString::from_raw($rptr);
}
}
}};
}
struct Diary {
owner: String,
items: Vec<String>
}
impl Diary {
pub fn new(owner: String) -> Self {
Diary {
owner,
items: vec![]
}
}
}
impl PtrMagic for Diary {}
pub extern "C" fn free_diary(ptr: *mut c_void) {
let _ = unsafe { Diary::from_raw(ptr as *mut Diary) };
}
extern "C" fn add_item(args: pxs_VarT) -> pxs_VarT {
unsafe {
let pixel_object_var = pxs_Var::from_borrow(pxs_listget(args, 1));
let host_ptr = pixel_object_var.get_host_ptr();
let d = Diary::from_borrow(host_ptr as *mut Diary);
let item = pxs_listget(args, 2);
let contents = pxs_getstring(item);
let str = own_string!(contents);
d.items.push(str);
pxs_newnull()
}
}
extern "C" fn new_diary(args: pxs_VarT) -> pxs_VarT {
unsafe {
let p_name = pxs_Var::from_borrow(pxs_listget(args, 1));
let p_name = p_name.get_string().unwrap();
let p = Diary::new(p_name.clone());
let typename = create_raw_string!("Diary");
let ptr = Diary::into_raw(p) as *mut c_void;
let pixel_object = pxs_newobject(ptr, free_diary, typename);
let add_item_raw = create_raw_string!("add_item");
pxs_object_add_reffunc(pixel_object, add_item_raw, add_item);
let var = pxs_newhost(pixel_object);
free_raw_string!(add_item_raw);
free_raw_string!(typename);
var
}
}
struct Person {
name: String,
}
impl Person {
pub fn new(n_name: String) -> Self {
Person { name: n_name }
}
pub fn set_name(&mut self, n_name: String) {
self.name = n_name;
}
pub fn get_name(&self) -> String {
self.name.clone()
}
}
impl PtrMagic for Person {}
pub extern "C" fn free_person(ptr: *mut c_void) {
let _ = unsafe { Person::from_raw(ptr as *mut Person) };
}
pub extern "C" fn set_name(args: *mut pxs_Var) -> *mut pxs_Var {
unsafe {
let pixel_object_var = pxs_listget(args, 1);
let host_ptr = pxs_gethost(pxs_listget(args, 0), pixel_object_var);
let p = Person::from_borrow(host_ptr as *mut Person);
let name = {
let arg = pxs_Var::from_borrow(pxs_listget(args, 2));
if arg.is_string() {
let raw = pxs_getstring(arg);
let owned = own_string!(raw);
owned
} else {
println!("Arg: {:#?}", arg);
let arg = pxs_listget(args, 2);
let ptr = pxs_gethost(pxs_listget(args, 0), arg);
let np = Person::from_borrow(ptr as *mut Person);
np.name.clone()
}
};
p.set_name(name.clone());
pxs_Var::into_raw(pxs_Var::new_null())
}
}
pub extern "C" fn get_name(args: *mut pxs_Var) -> *mut pxs_Var {
unsafe {
let pixel_object_var = pxs_listget(args, 1);
let host_ptr = pxs_gethost(pxs_listget(args, 0), pixel_object_var);
let p = Person::from_borrow(host_ptr as *mut Person);
pxs_Var::new_string(p.get_name().clone()).into_raw()
}
}
pub extern "C" fn new_person(args: *mut pxs_Var) -> *mut pxs_Var {
unsafe {
let p_name = pxs_Var::from_borrow(pxs_listget(args, 1));
let p_name = p_name.get_string().unwrap();
let p = Person::new(p_name.clone());
let typename = create_raw_string!("Person");
let ptr = Person::into_raw(p) as *mut c_void;
let pixel_object = pxs_newobject(ptr, free_person, typename);
let set_name_raw = create_raw_string!("set_name");
let get_name_raw = create_raw_string!("get_name");
pxs_object_addfunc(pixel_object, set_name_raw, set_name);
pxs_object_addfunc(pixel_object, get_name_raw, get_name);
let var = pxs_newhost(pixel_object);
free_raw_string!(set_name_raw);
free_raw_string!(get_name_raw);
free_raw_string!(typename);
var
}
}
pub extern "C" fn print_wrapper(args: *mut pxs_Var) -> *mut pxs_Var {
unsafe {
let runtime = pxs_listget(args, 0);
let mut string = String::new();
for i in 1..pxs_listlen(args) {
let var = pxs_tostring(runtime, pxs_listget(args, i));
if let Ok(s) = (*var).get_string() {
string.push_str(format!("{s} ").as_str());
}
pxs_freevar(var);
}
println!("From Runtime: {string}");
}
pxs_Var::new_null().into_raw()
}
pub extern "C" fn add_wrapper(args: *mut pxs_Var) -> *mut pxs_Var {
unsafe {
let n1 = pxs_Var::from_borrow(pxs_listget(args, 1));
let n2 = pxs_Var::from_borrow(pxs_listget(args, 2));
pxs_Var::new_i64(n1.value.i64_val + n2.value.i64_val).into_raw()
}
}
pub extern "C" fn sub_wrapper(args: *mut pxs_Var) -> *mut pxs_Var {
unsafe {
let n1 = pxs_Var::from_borrow(pxs_listget(args, 1));
let n2 = pxs_Var::from_borrow(pxs_listget(args, 2));
pxs_Var::new_i64(n1.value.i64_val - n2.value.i64_val).into_raw()
}
}
unsafe extern "C" fn file_loader(file_path: *const c_char) -> *mut c_char {
let file_path = unsafe { CStr::from_ptr(file_path).to_str().unwrap() };
if file_path.is_empty() {
return create_raw_string!("");
}
let file_exists = std::fs::exists(file_path).unwrap();
if !file_exists {
return create_raw_string!("");
}
let contents = std::fs::read_to_string(file_path).unwrap();
create_raw_string!(contents)
}
unsafe extern "C" fn dir_reader(dir_path: *const c_char) -> pxs_VarT {
let dir_path = unsafe { CStr::from_ptr(dir_path).to_str().unwrap() };
if dir_path.is_empty() {
return pxs_newnull();
}
let dir_exists = std::fs::exists(dir_path).unwrap();
if !dir_exists {
return pxs_newnull();
}
let files = std::fs::read_dir(dir_path).unwrap();
let result = pxs_newlist();
for f in files {
let entry = f.unwrap();
let raw = create_raw_string!(entry.file_name().into_string().unwrap());
pxs_listadd(result, pxs_newstring(raw));
unsafe{free_raw_string!(raw);}
}
result
}
fn test_add_module() {
println!("Inside Test add module");
pxs_initialize();
let module_name = create_raw_string!("pxs");
let module = pxs_newmod(module_name);
let add_name = create_raw_string!("add");
let n1_name = create_raw_string!("n1");
let n2_name: *mut i8 = create_raw_string!("n2");
pxs_addfunc(module, add_name, add_wrapper);
let n1 = pxs_newint(1);
let n2 = pxs_newint(2);
pxs_addvar(module, n1_name, n1);
pxs_addvar(module, n2_name, n2);
let name = create_raw_string!("print");
pxs_addfunc(module, name, print_wrapper);
let var_name = create_raw_string!("name");
let jordan = create_raw_string!("Jordan C");
let var = pxs_newstring(jordan);
pxs_addvar(module, var_name, var);
let object_name = create_raw_string!("Person");
pxs_addobject(module, object_name, new_person);
let math_module_name = create_raw_string!("math");
let math_module = pxs_newmod(math_module_name);
let sub_name = create_raw_string!("sub");
pxs_addfunc(math_module, sub_name, sub_wrapper);
let zero_name = create_raw_string!("ZERO");
pxs_addvar(math_module, zero_name, pxs_newint(0));
let diary_name = create_raw_string!("Diary");
pxs_addobject(math_module, diary_name, new_diary);
pxs_add_submod(module, math_module);
pxs_addmod(module);
free_raw_string!(diary_name);
free_raw_string!(zero_name);
free_raw_string!(module_name);
free_raw_string!(add_name);
free_raw_string!(n1_name);
free_raw_string!(n2_name);
free_raw_string!(object_name);
free_raw_string!(name);
free_raw_string!(var_name);
free_raw_string!(math_module_name);
free_raw_string!(sub_name);
}
#[test]
fn test_execute() {
println!("Test starting");
pxs_initialize();
test_add_module();
pxs_set_filereader(file_loader);
pxs_set_dirreader(dir_reader);
let runtime = pxs_Runtime::pxs_Lua;
let mut lines = vec![];
loop {
let mut input = String::new(); std::io::stdin()
.read_line(&mut input) .expect("Failed to read line");
if input.contains("quit") {
break;
} else if input.contains("run") {
let full_lines = lines.join("\n");
let err = match runtime {
pxs_Runtime::pxs_Lua => LuaScripting::execute(&full_lines, "<test_repl>"),
pxs_Runtime::pxs_Python => PythonScripting::execute(&full_lines, "<test_repl>"),
_ => todo!(), };
if !err.is_empty() {
println!("Repl error is: {err}");
}
lines.clear();
} else {
lines.push(input.clone());
}
}
pxs_finalize();
}
}