start adding closure subroutines

This commit is contained in:
Viv Lim 2022-12-11 02:07:07 -08:00
parent a43c8a487f
commit 432388fcb4
4 changed files with 56 additions and 0 deletions

7
Cargo.lock generated
View File

@ -2,6 +2,12 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "pkg-config"
version = "0.3.19"
@ -30,6 +36,7 @@ dependencies = [
name = "rust-guile"
version = "0.1.6"
dependencies = [
"lazy_static",
"pkg-config",
"thiserror",
]

View File

@ -12,6 +12,7 @@ readme = "Readme.md"
[dependencies]
thiserror = "1.0"
lazy_static = "1.4"
[build-dependencies]
pkg-config = "0.3"

View File

@ -1,4 +1,5 @@
mod exec;
pub mod subroutines;
pub use exec::exec_with_guile;
use std::{ffi::{c_void, CString}, path::PathBuf, os::unix::prelude::OsStrExt, fs::canonicalize};

47
src/api/subroutines.rs Normal file
View File

@ -0,0 +1,47 @@
use std::{cell::RefCell, rc::Rc, collections::HashMap, sync::{Mutex, atomic::{AtomicU32, AtomicBool, Ordering}}, ffi::{CString, c_void}};
use lazy_static::lazy_static;
use crate::{bindings::{SCM, scm_c_define_gsubr}, try_scm_decons, data::raw::{SCM_BOOL_F, try_scm_to_unsigned}, scm_car_unchecked};
lazy_static! {
static ref SUBROUTINES: Mutex<Vec<Box<dyn Fn(SCM) -> SCM + Send>>> = {
Mutex::new(vec![])
};
static ref SUBROUTINE_INDEX: AtomicU32 = AtomicU32::new(0);
static ref SUBROUTINE_TRAMPOLINE_INITIALIZED: AtomicBool = AtomicBool::new(false);
}
const SUBROUTINE_TRAMPOLINE_NAME: &'static str = "rust-guile-subroutine-trampoline";
pub fn register_subroutine<F>(name: &str, f: F)
where F: Fn(SCM) -> SCM + Send + 'static {
if !SUBROUTINE_TRAMPOLINE_INITIALIZED.load(Ordering::Relaxed){
let name_cstr = CString::new(SUBROUTINE_TRAMPOLINE_NAME.as_bytes()).unwrap().into_bytes_with_nul();
unsafe {
scm_c_define_gsubr(name_cstr.as_ptr() as *const i8, 1, 0, 1, subroutine_trampoline as *mut c_void);
}
SUBROUTINE_TRAMPOLINE_INITIALIZED.store(true, Ordering::Relaxed);
SUBROUTINE_INDEX.fetch_add(1, Ordering::Relaxed); // this just happens to match the index that gets inserted into the vec
}
SUBROUTINES.lock().unwrap().push(Box::new(f))
}
extern "C" fn subroutine_trampoline(sub_id: SCM, sub_args: SCM) -> SCM {
println!("entered subroutine trampoline");
match try_scm_to_unsigned(sub_id) {
Some(sub_id) => {
if let Some(subroutine) = SUBROUTINES.lock().unwrap().get(sub_id as usize) {
println!("subroutine {} found", sub_id);
subroutine(sub_args)
} else {
println!("subroutine {} not found", sub_id);
SCM_BOOL_F
}
},
None => SCM_BOOL_F
}
}