mirror of
https://git.proxmox.com/git/perlmod
synced 2025-10-04 18:27:16 +00:00
support functions without return values
this makes for surprisingly ugly code Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
0cdb12e277
commit
913a8a72ce
@ -109,6 +109,14 @@ pub fn handle_function(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let has_return_value = match &func.sig.output {
|
||||||
|
syn::ReturnType::Default => false,
|
||||||
|
syn::ReturnType::Type(_arrow, ty) => match &**ty {
|
||||||
|
syn::Type::Tuple(tuple) => !tuple.elems.is_empty(),
|
||||||
|
_ => true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
let too_many_args_error = syn::LitStr::new(
|
let too_many_args_error = syn::LitStr::new(
|
||||||
&format!(
|
&format!(
|
||||||
"too many parameters for function '{}', (expected {})",
|
"too many parameters for function '{}', (expected {})",
|
||||||
@ -118,24 +126,39 @@ pub fn handle_function(
|
|||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let handle_return = if attr.raw_return {
|
let mut handle_return;
|
||||||
quote! {
|
let return_type;
|
||||||
Ok(result.into_mortal().into_raw())
|
let wrapper_func;
|
||||||
|
if has_return_value {
|
||||||
|
return_type = quote! { *mut ::perlmod::ffi::SV };
|
||||||
|
|
||||||
|
handle_return = quote! {
|
||||||
|
let result = match #name(#passed_arguments) {
|
||||||
|
Ok(output) => output,
|
||||||
|
Err(err) => {
|
||||||
|
return Err(::perlmod::Value::new_string(&err.to_string())
|
||||||
|
.into_mortal()
|
||||||
|
.into_raw());
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if attr.raw_return {
|
||||||
|
handle_return.extend(quote! {
|
||||||
|
Ok(result.into_mortal().into_raw())
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
quote! {
|
handle_return.extend(quote! {
|
||||||
match ::perlmod::to_value(&result) {
|
match ::perlmod::to_value(&result) {
|
||||||
Ok(value) => Ok(value.into_mortal().into_raw()),
|
Ok(value) => Ok(value.into_mortal().into_raw()),
|
||||||
Err(err) => Err(::perlmod::Value::new_string(&err.to_string())
|
Err(err) => Err(::perlmod::Value::new_string(&err.to_string())
|
||||||
.into_mortal()
|
.into_mortal()
|
||||||
.into_raw()),
|
.into_raw()),
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let tokens = quote! {
|
wrapper_func = quote! {
|
||||||
#func
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn #xs_name(cv: &::perlmod::ffi::CV) {
|
pub extern "C" fn #xs_name(cv: &::perlmod::ffi::CV) {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -145,11 +168,42 @@ pub fn handle_function(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return_type = quote! { () };
|
||||||
|
|
||||||
|
if attr.raw_return {
|
||||||
|
bail!(&attr.raw_return => "raw_return attribute is illegal without a return value");
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_return = quote! {
|
||||||
|
#name(#passed_arguments);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
wrapper_func = quote! {
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn #xs_name(cv: &::perlmod::ffi::CV) {
|
||||||
|
unsafe {
|
||||||
|
match #impl_xs_name(cv) {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(sv) => ::perlmod::ffi::croak(sv),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let tokens = quote! {
|
||||||
|
#func
|
||||||
|
|
||||||
|
#wrapper_func
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn #impl_xs_name(
|
fn #impl_xs_name(
|
||||||
_cv: &::perlmod::ffi::CV,
|
_cv: &::perlmod::ffi::CV,
|
||||||
) -> Result<*mut ::perlmod::ffi::SV, *mut ::perlmod::ffi::SV> {
|
) -> Result<#return_type, *mut ::perlmod::ffi::SV> {
|
||||||
let argmark = unsafe { ::perlmod::ffi::pop_arg_mark() };
|
let argmark = unsafe { ::perlmod::ffi::pop_arg_mark() };
|
||||||
let mut args = argmark.iter();
|
let mut args = argmark.iter();
|
||||||
|
|
||||||
@ -169,15 +223,6 @@ pub fn handle_function(
|
|||||||
argmark.set_stack();
|
argmark.set_stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = match #name(#passed_arguments) {
|
|
||||||
Ok(output) => output,
|
|
||||||
Err(err) => {
|
|
||||||
return Err(::perlmod::Value::new_string(&err.to_string())
|
|
||||||
.into_mortal()
|
|
||||||
.into_raw());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#handle_return
|
#handle_return
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -14,9 +14,7 @@ mod export {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[export]
|
#[export]
|
||||||
fn something(#[raw] value: Value) -> Result<(), Error> {
|
fn something(#[raw] value: Value) {
|
||||||
println!("Called something!");
|
println!("Called something!");
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user