diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/guile/guile.rs | 76 | ||||
-rw-r--r-- | src/guile/guiledefs.c | 9 | ||||
-rw-r--r-- | src/guile/main.rs | 5 | ||||
-rw-r--r-- | src/macro_processor/macro_processor.rs | 47 |
4 files changed, 89 insertions, 48 deletions
diff --git a/src/guile/guile.rs b/src/guile/guile.rs index 4a0e25b..36df62a 100644 --- a/src/guile/guile.rs +++ b/src/guile/guile.rs @@ -2,34 +2,20 @@ use std::ffi::{CStr, CString}; use std::os::raw::{c_char, c_int, c_void}; #[link(name = "guile-3.0")] -#[allow(dead_code)] extern "C" { fn scm_init_guile(); - fn scm_c_define_gsubr( - name: *const c_char, - req: c_int, - opt: c_int, - rst: c_int, - func: extern "C" fn() -> *mut c_void, - ); fn scm_c_eval_string(expr: *const c_char) -> *mut c_void; fn scm_to_locale_string(scm_obj: *mut c_void) -> *const c_char; - fn scm_c_write(scm_obj: *mut c_void, port: *mut c_void); - fn scm_open_output_string() -> *mut c_void; - fn scm_get_output_string(port: *mut c_void) -> *mut c_void; fn scm_is_string(scm_obj: *mut c_void) -> c_int; - fn scm_is_number(scm_obj: *mut c_void) -> c_int; fn scm_object_to_string(scm_obj: *mut c_void, printer: *mut c_void) -> *mut c_void; } #[link(name = "guiledefs")] extern "C" { pub static scm_undefined: *mut c_void; -} - -extern "C" fn my_rust_function() -> *mut c_void { - println!("Hello from Rust!"); - unsafe { scm_undefined } + pub static scm_unspecified: *mut c_void; + fn defs_scm_is_eq(x: *mut c_void, y: *mut c_void) -> c_int; + fn defs_scm_define_string(name: *const c_char, value: *const c_char); } /// Convert a scm object into a string using Guile-builtins @@ -38,16 +24,14 @@ fn string_from_scm(scm_obj: *mut c_void) -> Result<String, ()> { if scm_obj.is_null() { return Err(()); } - if scm_is_string(scm_obj) != 0 { + if defs_scm_is_eq(scm_obj, scm_unspecified) != 0 { + return Ok(String::new()); + } else if scm_is_string(scm_obj) != 0 { let res_str = CStr::from_ptr(scm_to_locale_string(scm_obj)) .to_string_lossy() .into_owned(); return Ok(res_str); } else { - let port = scm_open_output_string(); - if port.is_null() { - return Err(()); - } let res = scm_object_to_string(scm_obj, scm_undefined); if res.is_null() { return Err(()); @@ -60,27 +44,39 @@ fn string_from_scm(scm_obj: *mut c_void) -> Result<String, ()> { } } -pub fn smp_guile_init() {} +#[derive(Clone)] +pub struct Guile {} -pub fn testguile() { - unsafe { - scm_init_guile(); +impl Guile { + pub fn new() -> Self { + unsafe { + scm_init_guile(); + } + Guile {} + } - let func_name = CString::new("my-rust-function").unwrap(); - scm_c_define_gsubr( - func_name.as_ptr(), - 0, // required arguments - 0, // optional arguments - 0, // rest arguments - my_rust_function, - ); + pub fn evaluate_expression(&self, expr: &str) -> Result<String, ()> { + unsafe { + let c_expr = CString::new(expr).map_err(|_| ())?; + let result = scm_c_eval_string(c_expr.as_ptr()); + string_from_scm(result) + } + } - let expr = CString::new("(+ 2 3)").unwrap(); - let result = scm_c_eval_string(expr.as_ptr()); - println!("{:?}", string_from_scm(result)); + pub fn define_string(&self, name: &str, value: &str) { + let c_name = CString::new(name).expect("CString::new failed"); + let c_value = CString::new(value).expect("CString::new failed"); + unsafe { + defs_scm_define_string(c_name.as_ptr(), c_value.as_ptr()); + } + } +} - let expr = CString::new("(my-rust-function)").unwrap(); - let result = scm_c_eval_string(expr.as_ptr()); - println!("{:?}", string_from_scm(result)); +impl Drop for Guile { + fn drop(&mut self) { + if let Err(e) = self.evaluate_expression("(exit)") { + panic!("Error while exiting {:#?}", e); + } } } + diff --git a/src/guile/guiledefs.c b/src/guile/guiledefs.c index 9f52c43..a0e9bd2 100644 --- a/src/guile/guiledefs.c +++ b/src/guile/guiledefs.c @@ -1,3 +1,12 @@ #include <libguile.h> struct scm_unused_struct * scm_undefined = SCM_UNDEFINED; +struct scm_unused_struct * scm_unspecified = SCM_UNSPECIFIED; + +int defs_scm_is_eq(SCM x, SCM y) { + return scm_is_eq(x, y); +} + +void defs_scm_define_string(const char* name, const char* value) { + scm_c_define(name, scm_from_utf8_string(value)); +} diff --git a/src/guile/main.rs b/src/guile/main.rs deleted file mode 100644 index 6957c8c..0000000 --- a/src/guile/main.rs +++ /dev/null @@ -1,5 +0,0 @@ -use skaldpress::guile::guile::testguile; - -fn main() { - testguile(); -} diff --git a/src/macro_processor/macro_processor.rs b/src/macro_processor/macro_processor.rs index 0b714f0..306c8da 100644 --- a/src/macro_processor/macro_processor.rs +++ b/src/macro_processor/macro_processor.rs @@ -1,10 +1,12 @@ +#[cfg(feature = "guile")] +use crate::guile::guile::Guile; +#[cfg(feature = "deadlinks")] +use crate::macro_processor::deadlinks::smp_builtin_wodl; use crate::macro_processor::error::SMPError; use std::collections::HashMap; use std::fs; use std::process::Command; -#[cfg(feature = "deadlinks")] -use crate::macro_processor::deadlinks::smp_builtin_wodl; // print only with debug_assertions macro_rules! dprint { ($($x:tt)*) => { @@ -591,6 +593,8 @@ enum ParserState { InQuotes, InMacro, InMacroArgs, + #[cfg(feature = "guile")] + InGuile, DNL, } @@ -627,6 +631,8 @@ pub struct MacroProcessor { pub macro_invocations: Vec<(String, Vec<String>)>, /// Emitted warnings pub warnings: Vec<MacroProcessorWarning>, + #[cfg(feature = "guile")] + pub guile: Guile, } impl MacroProcessor { @@ -635,6 +641,8 @@ impl MacroProcessor { macros: HashMap::new(), macro_invocations: Vec::new(), warnings: Vec::new(), + #[cfg(feature = "guile")] + guile: Guile::new(), }; smp.define_builtins(); smp @@ -729,7 +737,7 @@ impl MacroProcessor { /// * `name` - The name of the new macro /// * `body` - The body of the new macro, this will be expanded when macro is executed pub fn define_macro_string(&mut self, name: String, body: String) { - self.macros.insert(name, MacroType::String(body)); + self.define_macro(name, MacroType::String(body)); } /// Define a new macro as any MacroType @@ -739,6 +747,13 @@ impl MacroProcessor { /// * `name` - The name of the new macro /// * `macro_expansion` - The MacroType struct to use. pub fn define_macro(&mut self, name: String, macro_expansion: MacroType) { + #[cfg(feature = "guile")] + { + match ¯o_expansion { + MacroType::String(s) => self.guile.define_string(&(name.clone()), s), + _ => (), + } + } self.macros.insert(name, macro_expansion); } @@ -836,6 +851,9 @@ impl MacroProcessor { let mut quote_level = 0; let mut parens_level = 0; + #[cfg(feature = "guile")] + let mut guile_expr = String::new(); + let mut chars = input.char_indices().peekable(); while let Some((i, c)) = chars.next() { highlight_debug!(input, macro_name_start, i); @@ -858,6 +876,13 @@ impl MacroProcessor { continue; } + #[cfg(feature = "guile")] + if c == '%' && peek == Some(&'(') { + state = ParserState::InGuile; + chars.next(); + continue; + } + if c == '%' && peek == Some(&'"') { state = ParserState::InQuotes; quote_level += 1; @@ -888,6 +913,22 @@ impl MacroProcessor { output.push(c); } }, + #[cfg(feature = "guile")] + ParserState::InGuile => match c { + ')' if peek == Some(&'%') => { + let r = self + .guile + .evaluate_expression(&guile_expr) + .expect("fatal guile error"); + output.push_str(&r); + guile_expr.clear(); + state = ParserState::Normal; + chars.next(); + } + _ => { + guile_expr.push(c); + } + }, ParserState::InMacro => { if c.is_alphanumeric() || c == '_' { macro_name.push(c); |