//! Fn trait implementations use quote::{Ident, Tokens}; use codegen::operations::match_values; static TRAITS: [(&str, &str, &str); 3] = [ ("FnOnce", "call_once", ""), ("FnMut", "call_mut", "&mut"), ("Fn", "call", "&"), ]; pub fn impl_fn() -> Vec { (1..9u32) .flat_map(|size| { TRAITS.into_iter() .enumerate() .map(move |(index, &(trt, func, prefix))| { let trt = Ident::from(trt); let func = Ident::from(func); let deref = Ident::from(prefix.replace("&", "ref ")); let prefix = Ident::from(prefix); let idx1 = 0..size; let idx2 = 0..size; let types1: Vec<_> = (0..size).map(|idx| Ident::from(format!("T{}", idx))).collect(); let types2 = types1.clone(); let types3 = types1.clone(); let args1: Vec<_> = (0..size).map(|idx| Ident::from(format!("args_{}", idx))).collect(); let args2 = args1.clone(); let args3 = args1.clone(); let tuple = quote! { ( #( Value<#types1>, )* ) }; let output = if index == 0 { quote! { type Output = >::Output; } } else { quote!() }; let func_impl = match_values( &args1, "e! { self.thunk.#func(( #( Value::Concrete( #args2 ), )* )) }, quote! { let sink = graph.add_node(Node::Call(self.func)); #( graph.add_edge(#args3, sink, #idx1); )* drop(graph); let args = ( #( self.parameter(#idx2), )* ); let #prefix Function { #deref module, func, #deref thunk } = self; let res = thunk.#func(args); Self::ret_impl(&module, func, res); sink }, ); quote! { #[cfg(feature = "functions")] impl #trt<#tuple> for Function where T: #trt<#tuple, Output=Value>, #( Function: Parameter<#types3> ),* { #output extern "rust-call" fn #func(#prefix self, ( #( #args1, )* ): #tuple) -> Value { #func_impl } } } }) }) .collect() }