Skip to content

Commit 4a7b731

Browse files
committed
Start implementing subroutine definition macro
start work on #6 ...
1 parent 3e03029 commit 4a7b731

File tree

12 files changed

+237
-61
lines changed

12 files changed

+237
-61
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
use syn;
2+
use quote;
3+
use regex;
4+
// use syn::token::{Semi};
5+
use syn::synom::{Synom};
6+
use syn::punctuated::Punctuated;
7+
use quote::{ToTokens, Tokens};
8+
use proc_macro2::{TokenStream};
9+
10+
struct ReqArg { name: syn::Ident, typ: syn::TypePath }
11+
struct OptArg { pub arg: ReqArg }
12+
trait Arg {
13+
fn get_name(&self) -> &syn::Ident;
14+
fn get_type(&self) -> &syn::TypePath;
15+
fn get_conv(&self) -> Tokens;
16+
}
17+
18+
impl Arg for ReqArg {
19+
fn get_name(&self) -> &syn::Ident { &self.name }
20+
fn get_type(&self) -> &syn::TypePath { &self.typ }
21+
22+
fn get_conv(&self) -> Tokens {
23+
quote!(
24+
Scm::<Untyped>::from_raw(n).into_type().unwrap();
25+
)
26+
}
27+
}
28+
29+
impl Arg for OptArg {
30+
fn get_name(&self) -> &syn::Ident { self.arg.get_name() }
31+
fn get_type(&self) -> &syn::TypePath { self.arg.get_type() }
32+
33+
fn get_conv(&self) -> Tokens {
34+
quote!(
35+
// TODO: figure out how to convert SCM to Option<Scm<T>>
36+
)
37+
}
38+
}
39+
40+
impl Synom for ReqArg {
41+
named!(parse -> Self, do_parse!(
42+
name: syn!(syn::Ident) >>
43+
punct!(:) >>
44+
typ: syn!(syn::TypePath) >>
45+
cond_reduce!(
46+
typ.path.segments.last().unwrap().value().ident == "Scm") >>
47+
48+
(ReqArg { name, typ })
49+
));
50+
}
51+
52+
impl Synom for OptArg {
53+
named!(parse -> Self, do_parse!(
54+
name: syn!(syn::Ident) >>
55+
punct!(:) >>
56+
57+
_opt: syn!(syn::Ident) >>
58+
cond_reduce!(_opt == "Option") >>
59+
60+
punct!(<) >>
61+
typ: syn!(syn::TypePath) >>
62+
cond_reduce!(
63+
typ.path.segments.last().unwrap().value().ident == "Scm") >>
64+
punct!(>) >>
65+
66+
(OptArg { arg: ReqArg { name, typ } })
67+
));
68+
}
69+
70+
named!(pub parse_guile_define_subr -> TokenStream, do_parse!(
71+
name: syn!(syn::Expr) >>
72+
punct!(,) >>
73+
punct!(|) >>
74+
args: call!(Punctuated::<ReqArg, Token![,]>::parse_terminated) >>
75+
oargs: call!(Punctuated::<OptArg, Token![,]>::parse_terminated) >>
76+
punct!(|) >>
77+
punct!(->) >>
78+
ret: syn!(syn::TypePath) >>
79+
cond_reduce!(
80+
ret.path.segments.last().unwrap().value().ident == "Scm") >>
81+
body: syn!(syn::Expr) >>
82+
83+
({
84+
let arg_names = args.iter().map(|ref a| a.get_name())
85+
.collect::<Vec<_>>();
86+
let arg_names2 = arg_names.clone();
87+
let arg_types = args.iter().map(|ref a| a.get_type());
88+
let arg_convs = args.iter().map(|ref a| a.get_conv());
89+
let num_args = args.len();
90+
91+
let oarg_names = oargs.iter().map(|ref a| a.get_name())
92+
.collect::<Vec<_>>();
93+
let oarg_names2 = oarg_names.clone();
94+
let oarg_types = oargs.iter().map(|ref a| a.get_type());
95+
let oarg_convs = oargs.iter().map(|ref a| a.get_conv());
96+
let num_oargs = oargs.len();
97+
98+
quote!({
99+
unsafe {
100+
unsafe extern "C" ___tmp_c_fn(#(#arg_names: SCM),* , #(#oarg_names: SCM),* ) -> SCM {
101+
#(let #arg_names2: #arg_types = #arg_convs; )*
102+
#(let #oarg_names2: #oarg_types = #oarg_convs;)*
103+
104+
let o: #ret = #body;
105+
106+
o.into_raw()
107+
}
108+
109+
let _ = scm_c_define_gsubr(
110+
CString::new(#name).unwrap().as_ptr(),
111+
#num_args, #num_oargs, 0,
112+
___tmp_c_fn as scm_t_subr
113+
);
114+
}
115+
}).into()
116+
})
117+
));

internal_proc_macros/src/guile_impl.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,12 +288,14 @@ impl GuileDef {
288288
}).collect();
289289

290290
let mut body = quote!(
291-
unsafe { #cfunc(#(#cargs),*) }
291+
#cfunc(#(#cargs),*)
292292
);
293293

294-
if self.ret_from_raw {
295-
body = quote!(Scm::_from_raw(#body));
296-
}
294+
body = if self.ret_from_raw {
295+
quote!(unsafe { Scm::_from_raw(#body) })
296+
} else {
297+
quote!(unsafe { #body })
298+
};
297299

298300
if let syn::Type::Tuple(t) =
299301
syn::parse_str(&ret_ty.to_string()).expect("Parsing return type") {

internal_proc_macros/src/lib.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,37 +10,48 @@ extern crate proc_macro2;
1010

1111

1212
mod guile_impl;
13+
mod define_subr;
1314

1415
use guile_impl::{parse_guile_impl, parse_guile_defs};
16+
use define_subr::parse_guile_define_subr;
1517
use syn::buffer::TokenBuffer;
1618
use proc_macro2::{TokenStream};
1719
use quote::ToTokens;
1820

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

25-
format!("{}", parse_guile_impl(sb.begin())
26-
.expect("Expanding guile_impl macro").0)
27+
format!("{}", parse_guile_impl(sb.begin())
28+
.expect("Expanding guile_impl macro").0)
2729
}
2830
}
2931

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

36-
let gdefs = parse_guile_defs(sb.begin())
37-
.expect("Expanding guile_defs macro").0;
38+
let gdefs = parse_guile_defs(sb.begin())
39+
.expect("Expanding guile_defs macro").0;
3840

39-
let mut mtokens = quote::Tokens::new();
41+
let mut mtokens = quote::Tokens::new();
4042

41-
gdefs.iter().for_each(
42-
|gd| gd.construct().to_tokens(&mut mtokens));
43+
gdefs.iter().for_each(
44+
|gd| gd.construct().to_tokens(&mut mtokens));
4345

44-
format!("{}", mtokens)
46+
format!("{}", mtokens)
47+
}
48+
}
49+
50+
proc_macro_item_impl! {
51+
pub fn guile_define_subr_impl(input: &str) -> String {
52+
let sb = TokenBuffer::new2(
53+
syn::parse_str::<TokenStream>(input).expect("Turning str into tokenstream"));
54+
55+
format!("{}", parse_guile_define_subr(sb.begin()).expect("Expanding guile_define_subr macro").0)
4556
}
4657
}

src/lib.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ mod tests {
170170
// // type SlotTypes = type_list![TestStruct];
171171

172172
unsafe extern "C" fn test_data(fo: SCM) -> SCM {
173+
// let fo: Scm::<ForeignObject<TestStruct>> = Scm::<Untyped>::from_raw(fo);
174+
173175
let st = Scm::<Untyped>::from_raw(fo).into_foreign(&*FTYPE).unwrap();
174176
assert!(st.is_foreign(&*FTYPE));
175177

@@ -181,17 +183,33 @@ mod tests {
181183
}
182184

183185
unsafe extern "C" fn get_foreign_o(n: SCM) -> SCM {
184-
let n: u8 = Scm::<Untyped>::from_raw(n).into_integer().unwrap().try_as().unwrap();
186+
let n: Scm<Int> = Scm::<Untyped>::from_raw(n).into_integer().unwrap();
187+
188+
let o: Scm<ForeignObject<TestStruct>> = {
189+
let n: u8 = n.try_as().unwrap();
190+
Scm::<ForeignObject<TestStruct>>::new(&*FTYPE, TestStruct { data0: n })
191+
};
185192

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

188-
st.into_raw()
195+
// |n: Scm<Int>| -> Scm<ForeignObject<TestStruct>> {
196+
// let n: u8 = n.try_as().unwrap();
197+
// Scm::<ForeignObject<TestStruct>>::new(&*FTYPE, TestStruct { data0: n })
198+
// }
199+
200+
// (n).into_raw()
189201
}
190202

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

193205

194206
let _ = Guile::call_with_guile(|_| {
207+
208+
guile_define_subr!("get_foreign_o", |n: Scm<Int>| -> Scm<ForeignObject<TestStruct>> {
209+
let n: u8 = n.try_as().unwrap();
210+
Scm::<ForeignObject<TestStruct>>::new(&*FTYPE, TestStruct { data0: n })
211+
});
212+
195213
unsafe {
196214
let _ = scm_c_define_gsubr(
197215
CString::new("test-data").unwrap().as_ptr(),

src/scm/bool.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ impl Scm<Bool> {
1414
/// Return a true litteral Scm object
1515
#[inline]
1616
pub fn true_c() -> Scm<Bool> {
17-
Scm::_from_raw(unsafe { gu_SCM_BOOL_T() })
17+
unsafe { Scm::_from_raw(gu_SCM_BOOL_T()) }
1818
// Scm { data: unsafe { gu_SCM_BOOL_T() } , spec: PhantomData }
1919
}
2020

2121
/// Return a false litteral Scm object
2222
#[inline]
2323
pub fn false_c() -> Scm<Bool> {
24-
Scm::_from_raw(unsafe { gu_SCM_BOOL_F() })
24+
unsafe { Scm::_from_raw(gu_SCM_BOOL_F()) }
2525
// Scm { data: unsafe { gu_SCM_BOOL_F() }, spec: PhantomData }
2626
}
2727

@@ -37,6 +37,6 @@ impl Scm<Bool> {
3737
impl Not for Scm<Bool> {
3838
type Output = Scm<Bool>;
3939
fn not(self) -> Scm<Bool> {
40-
Scm::_from_raw(unsafe { scm_not(self.data) })
40+
unsafe { Scm::_from_raw(scm_not(self.data)) }
4141
}
4242
}

src/scm/foreign.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,13 @@ impl<T> Scm<Foreign<T>> {
8585
Scm::<Symbol>::from("data")
8686
].into();
8787

88-
Scm::_from_raw_with_spec(
89-
unsafe {
88+
unsafe {
89+
Scm::_from_raw_with_spec(
9090
scm_make_foreign_object_type(name.data,
9191
slots.data,
92-
Some(Self::finalizer))
93-
},
92+
Some(Self::finalizer)),
9493
Foreign { _data: PhantomData })
94+
}
9595
}
9696
// // NOTE: types in slots should probably be Boxes!!!!!
9797
// pub fn new_type(name: &Scm<ScmString>, slot_names: &Scm<List>, slot_types: Box<TypeList>) -> Self {
@@ -135,14 +135,15 @@ impl<T> Scm<ForeignObject<T>> {
135135
pub fn new(typ: &Scm<Foreign<T>>, data: T) ->
136136
Scm<ForeignObject<T>> {
137137

138-
Scm::_from_raw_with_spec(
139-
unsafe {
138+
unsafe {
139+
Scm::_from_raw_with_spec(
140140
scm_make_foreign_object_1(
141141
typ.data,
142-
Box::into_raw(Box::new(data))
143-
as *mut libc::c_void)
144-
},
145-
ForeignObject { typ: (*typ).clone() })
142+
Box::into_raw(Box::new(data)) as *mut libc::c_void
143+
),
144+
ForeignObject { typ: (*typ).clone() }
145+
)
146+
}
146147
}
147148

148149
pub unsafe fn get_raw(&self) -> *mut T {

src/scm/list.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ impl<TS: TypeSpec> From<Vec<Scm<TS>>> for Scm<List> {
1313
fn from(l: Vec<Scm<TS>>) -> Scm<List> {
1414
let mut l: Vec<SCM> = l.into_iter().map(|e| e.data).collect();
1515
l.push(unsafe { gu_SCM_UNDEFINED() });
16-
Scm::_from_raw(unsafe { gu_scm_list_n(l.as_mut_ptr()) })
16+
unsafe { Scm::_from_raw(gu_scm_list_n(l.as_mut_ptr())) }
1717
}
1818
}
1919

0 commit comments

Comments
 (0)