Skip to content

Commit

Permalink
Start implementing subroutine definition macro
Browse files Browse the repository at this point in the history
start work on #6 ...
  • Loading branch information
Javyre committed Mar 3, 2018
1 parent 3e03029 commit 4a7b731
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 61 deletions.
117 changes: 117 additions & 0 deletions internal_proc_macros/src/define_subr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use syn;
use quote;
use regex;
// use syn::token::{Semi};
use syn::synom::{Synom};
use syn::punctuated::Punctuated;
use quote::{ToTokens, Tokens};
use proc_macro2::{TokenStream};

struct ReqArg { name: syn::Ident, typ: syn::TypePath }
struct OptArg { pub arg: ReqArg }
trait Arg {
fn get_name(&self) -> &syn::Ident;
fn get_type(&self) -> &syn::TypePath;
fn get_conv(&self) -> Tokens;
}

impl Arg for ReqArg {
fn get_name(&self) -> &syn::Ident { &self.name }
fn get_type(&self) -> &syn::TypePath { &self.typ }

fn get_conv(&self) -> Tokens {
quote!(
Scm::<Untyped>::from_raw(n).into_type().unwrap();
)
}
}

impl Arg for OptArg {
fn get_name(&self) -> &syn::Ident { self.arg.get_name() }
fn get_type(&self) -> &syn::TypePath { self.arg.get_type() }

fn get_conv(&self) -> Tokens {
quote!(
// TODO: figure out how to convert SCM to Option<Scm<T>>
)
}
}

impl Synom for ReqArg {
named!(parse -> Self, do_parse!(
name: syn!(syn::Ident) >>
punct!(:) >>
typ: syn!(syn::TypePath) >>
cond_reduce!(
typ.path.segments.last().unwrap().value().ident == "Scm") >>

(ReqArg { name, typ })
));
}

impl Synom for OptArg {
named!(parse -> Self, do_parse!(
name: syn!(syn::Ident) >>
punct!(:) >>

_opt: syn!(syn::Ident) >>
cond_reduce!(_opt == "Option") >>

punct!(<) >>
typ: syn!(syn::TypePath) >>
cond_reduce!(
typ.path.segments.last().unwrap().value().ident == "Scm") >>
punct!(>) >>

(OptArg { arg: ReqArg { name, typ } })
));
}

named!(pub parse_guile_define_subr -> TokenStream, do_parse!(
name: syn!(syn::Expr) >>
punct!(,) >>
punct!(|) >>
args: call!(Punctuated::<ReqArg, Token![,]>::parse_terminated) >>
oargs: call!(Punctuated::<OptArg, Token![,]>::parse_terminated) >>
punct!(|) >>
punct!(->) >>
ret: syn!(syn::TypePath) >>
cond_reduce!(
ret.path.segments.last().unwrap().value().ident == "Scm") >>
body: syn!(syn::Expr) >>

({
let arg_names = args.iter().map(|ref a| a.get_name())
.collect::<Vec<_>>();
let arg_names2 = arg_names.clone();
let arg_types = args.iter().map(|ref a| a.get_type());
let arg_convs = args.iter().map(|ref a| a.get_conv());
let num_args = args.len();

let oarg_names = oargs.iter().map(|ref a| a.get_name())
.collect::<Vec<_>>();
let oarg_names2 = oarg_names.clone();
let oarg_types = oargs.iter().map(|ref a| a.get_type());
let oarg_convs = oargs.iter().map(|ref a| a.get_conv());
let num_oargs = oargs.len();

quote!({
unsafe {
unsafe extern "C" ___tmp_c_fn(#(#arg_names: SCM),* , #(#oarg_names: SCM),* ) -> SCM {
#(let #arg_names2: #arg_types = #arg_convs; )*
#(let #oarg_names2: #oarg_types = #oarg_convs;)*

let o: #ret = #body;

o.into_raw()
}

let _ = scm_c_define_gsubr(
CString::new(#name).unwrap().as_ptr(),
#num_args, #num_oargs, 0,
___tmp_c_fn as scm_t_subr
);
}
}).into()
})
));
10 changes: 6 additions & 4 deletions internal_proc_macros/src/guile_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,14 @@ impl GuileDef {
}).collect();

let mut body = quote!(
unsafe { #cfunc(#(#cargs),*) }
#cfunc(#(#cargs),*)
);

if self.ret_from_raw {
body = quote!(Scm::_from_raw(#body));
}
body = if self.ret_from_raw {
quote!(unsafe { Scm::_from_raw(#body) })
} else {
quote!(unsafe { #body })
};

if let syn::Type::Tuple(t) =
syn::parse_str(&ret_ty.to_string()).expect("Parsing return type") {
Expand Down
35 changes: 23 additions & 12 deletions internal_proc_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,48 @@ extern crate proc_macro2;


mod guile_impl;
mod define_subr;

use guile_impl::{parse_guile_impl, parse_guile_defs};
use define_subr::parse_guile_define_subr;
use syn::buffer::TokenBuffer;
use proc_macro2::{TokenStream};
use quote::ToTokens;

proc_macro_item_impl! {
/// implement a guile func
pub fn guile_impl_impl(input: &str) -> String {
let sb = TokenBuffer::new2(
syn::parse_str::<TokenStream>(input).expect("Turning str into tokenstream"));
let sb = TokenBuffer::new2(
syn::parse_str::<TokenStream>(input).expect("Turning str into tokenstream"));

format!("{}", parse_guile_impl(sb.begin())
.expect("Expanding guile_impl macro").0)
format!("{}", parse_guile_impl(sb.begin())
.expect("Expanding guile_impl macro").0)
}
}

proc_macro_item_impl! {
/// implement a guile struct
pub fn guile_defs_impl(input: &str) -> String {
let sb = TokenBuffer::new2(
syn::parse_str::<TokenStream>(input).expect("Turning str into tokenstream"));
let sb = TokenBuffer::new2(
syn::parse_str::<TokenStream>(input).expect("Turning str into tokenstream"));

let gdefs = parse_guile_defs(sb.begin())
.expect("Expanding guile_defs macro").0;
let gdefs = parse_guile_defs(sb.begin())
.expect("Expanding guile_defs macro").0;

let mut mtokens = quote::Tokens::new();
let mut mtokens = quote::Tokens::new();

gdefs.iter().for_each(
|gd| gd.construct().to_tokens(&mut mtokens));
gdefs.iter().for_each(
|gd| gd.construct().to_tokens(&mut mtokens));

format!("{}", mtokens)
format!("{}", mtokens)
}
}

proc_macro_item_impl! {
pub fn guile_define_subr_impl(input: &str) -> String {
let sb = TokenBuffer::new2(
syn::parse_str::<TokenStream>(input).expect("Turning str into tokenstream"));

format!("{}", parse_guile_define_subr(sb.begin()).expect("Expanding guile_define_subr macro").0)
}
}
24 changes: 21 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ mod tests {
// // type SlotTypes = type_list![TestStruct];

unsafe extern "C" fn test_data(fo: SCM) -> SCM {
// let fo: Scm::<ForeignObject<TestStruct>> = Scm::<Untyped>::from_raw(fo);

let st = Scm::<Untyped>::from_raw(fo).into_foreign(&*FTYPE).unwrap();
assert!(st.is_foreign(&*FTYPE));

Expand All @@ -181,17 +183,33 @@ mod tests {
}

unsafe extern "C" fn get_foreign_o(n: SCM) -> SCM {
let n: u8 = Scm::<Untyped>::from_raw(n).into_integer().unwrap().try_as().unwrap();
let n: Scm<Int> = Scm::<Untyped>::from_raw(n).into_integer().unwrap();

let o: Scm<ForeignObject<TestStruct>> = {
let n: u8 = n.try_as().unwrap();
Scm::<ForeignObject<TestStruct>>::new(&*FTYPE, TestStruct { data0: n })
};

let st = Scm::<ForeignObject<TestStruct>>::new(&*FTYPE, TestStruct { data0: n });
o.into_raw()

st.into_raw()
// |n: Scm<Int>| -> Scm<ForeignObject<TestStruct>> {
// let n: u8 = n.try_as().unwrap();
// Scm::<ForeignObject<TestStruct>>::new(&*FTYPE, TestStruct { data0: n })
// }

// (n).into_raw()
}

let st = Scm::<ForeignObject<TestStruct>>::new(&*FTYPE, TestStruct { data0: 21 });


let _ = Guile::call_with_guile(|_| {

guile_define_subr!("get_foreign_o", |n: Scm<Int>| -> Scm<ForeignObject<TestStruct>> {
let n: u8 = n.try_as().unwrap();
Scm::<ForeignObject<TestStruct>>::new(&*FTYPE, TestStruct { data0: n })
});

unsafe {
let _ = scm_c_define_gsubr(
CString::new("test-data").unwrap().as_ptr(),
Expand Down
6 changes: 3 additions & 3 deletions src/scm/bool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ impl Scm<Bool> {
/// Return a true litteral Scm object
#[inline]
pub fn true_c() -> Scm<Bool> {
Scm::_from_raw(unsafe { gu_SCM_BOOL_T() })
unsafe { Scm::_from_raw(gu_SCM_BOOL_T()) }
// Scm { data: unsafe { gu_SCM_BOOL_T() } , spec: PhantomData }
}

/// Return a false litteral Scm object
#[inline]
pub fn false_c() -> Scm<Bool> {
Scm::_from_raw(unsafe { gu_SCM_BOOL_F() })
unsafe { Scm::_from_raw(gu_SCM_BOOL_F()) }
// Scm { data: unsafe { gu_SCM_BOOL_F() }, spec: PhantomData }
}

Expand All @@ -37,6 +37,6 @@ impl Scm<Bool> {
impl Not for Scm<Bool> {
type Output = Scm<Bool>;
fn not(self) -> Scm<Bool> {
Scm::_from_raw(unsafe { scm_not(self.data) })
unsafe { Scm::_from_raw(scm_not(self.data)) }
}
}
21 changes: 11 additions & 10 deletions src/scm/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,13 @@ impl<T> Scm<Foreign<T>> {
Scm::<Symbol>::from("data")
].into();

Scm::_from_raw_with_spec(
unsafe {
unsafe {
Scm::_from_raw_with_spec(
scm_make_foreign_object_type(name.data,
slots.data,
Some(Self::finalizer))
},
Some(Self::finalizer)),
Foreign { _data: PhantomData })
}
}
// // NOTE: types in slots should probably be Boxes!!!!!
// pub fn new_type(name: &Scm<ScmString>, slot_names: &Scm<List>, slot_types: Box<TypeList>) -> Self {
Expand Down Expand Up @@ -135,14 +135,15 @@ impl<T> Scm<ForeignObject<T>> {
pub fn new(typ: &Scm<Foreign<T>>, data: T) ->
Scm<ForeignObject<T>> {

Scm::_from_raw_with_spec(
unsafe {
unsafe {
Scm::_from_raw_with_spec(
scm_make_foreign_object_1(
typ.data,
Box::into_raw(Box::new(data))
as *mut libc::c_void)
},
ForeignObject { typ: (*typ).clone() })
Box::into_raw(Box::new(data)) as *mut libc::c_void
),
ForeignObject { typ: (*typ).clone() }
)
}
}

pub unsafe fn get_raw(&self) -> *mut T {
Expand Down
2 changes: 1 addition & 1 deletion src/scm/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ impl<TS: TypeSpec> From<Vec<Scm<TS>>> for Scm<List> {
fn from(l: Vec<Scm<TS>>) -> Scm<List> {
let mut l: Vec<SCM> = l.into_iter().map(|e| e.data).collect();
l.push(unsafe { gu_SCM_UNDEFINED() });
Scm::_from_raw(unsafe { gu_scm_list_n(l.as_mut_ptr()) })
unsafe { Scm::_from_raw(gu_scm_list_n(l.as_mut_ptr())) }
}
}

Expand Down
Loading

0 comments on commit 4a7b731

Please sign in to comment.