use std::borrow::Cow;
use quote::{quote_spanned, ToTokens};
use syn::{ItemFn, Result};
use crate::{
export::ExportConfig,
utils::{
Component,
Context,
EmptyPolymorphism,
Exportable,
Facade,
FunctionPolymorphism,
Group,
Invocation,
Prototype,
Shallow,
SignaturePolymorphism,
DUMP,
EXCLUDED,
INCLUDED,
RENAME,
SHALLOW,
},
};
pub fn export_item_fn(item: &mut ItemFn) -> Result<ExportConfig> {
let attrs = item.drain_attrs()?;
attrs.check(DUMP | INCLUDED | EXCLUDED | SHALLOW | RENAME)?;
Shallow.init(attrs.shallow());
let span = item.sig.ident.span();
let core = span.face_core();
let mut group = Group::default();
let mut package_prototype = Prototype::for_package(span);
let mut signature_polymorphism = SignaturePolymorphism::new(
&item.sig.ident,
&mut item.sig.generics,
&mut item.sig.inputs,
&item.sig.output,
)?;
let invocation = Invocation::new(&item.sig)?;
loop {
let function_polymorphism = FunctionPolymorphism {
scope: &EmptyPolymorphism,
signature: &signature_polymorphism,
};
let name = attrs
.rename_checked(&function_polymorphism)?
.unwrap_or_else(|| item.sig.ident.to_string());
let name_ref = Context.make_unique_identifier(name.as_str(), span);
let function_type = invocation.make_function_type(
&mut group,
&function_polymorphism,
name.as_str(),
&name_ref,
item.rust_doc(),
)?;
let constructor = quote_spanned!(span=> {
fn component(
origin: #core::runtime::Origin,
_lhs: #core::runtime::Arg,
) -> #core::runtime::RuntimeResult<#core::runtime::Cell> {
#core::runtime::Cell::give(origin, #function_type)
}
component as fn(
#core::runtime::Origin,
#core::runtime::Arg,
) -> #core::runtime::RuntimeResult::<#core::runtime::Cell>
});
package_prototype.component(Component {
name_ref: Cow::Owned(name_ref),
constructor,
hint: Cow::Owned(function_type),
doc: item.rust_doc(),
});
if !signature_polymorphism.rotate() {
break;
}
}
group.prototype(package_prototype);
Ok(ExportConfig {
dump: attrs.dump(),
stream: match attrs.disabled() {
true => None,
false => match attrs.shallow() {
true => Some(Shallow.to_token_stream()),
false => Some(group.to_token_stream()),
},
},
})
}