start adding closure subroutines
This commit is contained in:
parent
a43c8a487f
commit
432388fcb4
|
@ -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",
|
||||
]
|
||||
|
|
|
@ -12,6 +12,7 @@ readme = "Readme.md"
|
|||
|
||||
[dependencies]
|
||||
thiserror = "1.0"
|
||||
lazy_static = "1.4"
|
||||
|
||||
[build-dependencies]
|
||||
pkg-config = "0.3"
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue