@@ -7,6 +7,7 @@ use itertools::Itertools;
77use proc_macro2:: TokenStream ;
88use quote:: { format_ident, quote} ;
99use std:: fmt:: Write ;
10+ use syn:: spanned:: Spanned ;
1011
1112pub struct WrappedFunction {
1213 pub function_declaration : TokenStream ,
@@ -20,7 +21,7 @@ pub fn wrap_function(function: &syn::ItemFn) -> Vec<WrappedFunction> {
2021 & original_identifier. to_string( ) ,
2122 ) ] ;
2223
23- let mut docs_buf = String :: new ( ) ;
24+ let mut documentation_buffer = String :: new ( ) ;
2425 for attr in & function. attrs {
2526 if attr. path ( ) . is_ident ( "function" ) {
2627 attr. parse_nested_meta ( |meta| {
@@ -42,7 +43,8 @@ pub fn wrap_function(function: &syn::ItemFn) -> Vec<WrappedFunction> {
4243 && let syn:: Expr :: Lit ( expr) = & meta. value
4344 && let syn:: Lit :: Str ( lit_str) = & expr. lit
4445 {
45- writeln ! ( docs_buf, "{}" , lit_str. value( ) . trim( ) ) . expect ( "failed to write docs" ) ;
46+ writeln ! ( documentation_buffer, "{}" , lit_str. value( ) . trim( ) )
47+ . expect ( "failed to write docs" ) ;
4648 }
4749 }
4850
@@ -54,7 +56,7 @@ pub fn wrap_function(function: &syn::ItemFn) -> Vec<WrappedFunction> {
5456 }
5557
5658 // TODO: CONTINUE HERE
57- let return_type = quote ! { crate :: interpreter :: function:: StaticType :: Any } ; // RIP ROP RAP
59+ let return_type = map_return_type ( & function. sig . output ) ;
5860
5961 // If the function has no argument then the cartesian product stuff below doesn't work
6062 if function. sig . inputs . is_empty ( ) {
@@ -67,7 +69,7 @@ pub fn wrap_function(function: &syn::ItemFn) -> Vec<WrappedFunction> {
6769 function_name,
6870 vec ! [ ] ,
6971 return_type. clone ( ) ,
70- & docs_buf ,
72+ & documentation_buffer ,
7173 )
7274 } )
7375 . collect ( ) ;
@@ -102,7 +104,7 @@ pub fn wrap_function(function: &syn::ItemFn) -> Vec<WrappedFunction> {
102104 function_name,
103105 args,
104106 return_type. clone ( ) ,
105- & docs_buf ,
107+ & documentation_buffer ,
106108 ) ;
107109 variation_id += 1 ;
108110 wrapped
@@ -112,6 +114,69 @@ pub fn wrap_function(function: &syn::ItemFn) -> Vec<WrappedFunction> {
112114 . collect ( )
113115}
114116
117+ fn map_return_type ( output : & syn:: ReturnType ) -> TokenStream {
118+ let convert = build ( ) ;
119+ match output {
120+ syn:: ReturnType :: Default => {
121+ // in case return type is not specified (for closures rust defaults to type inference which doesn't help us here)
122+ quote ! { crate :: interpreter:: function:: StaticType :: Tuple ( vec![ ] ) }
123+ }
124+ syn:: ReturnType :: Type ( _, ty) => map_type ( ty) ,
125+ }
126+ }
127+
128+ fn map_type ( ty : & syn:: Type ) -> TokenStream {
129+ match ty {
130+ syn:: Type :: Path ( p) => map_type_path ( p) ,
131+ syn:: Type :: Reference ( r) => map_type ( r. elem . as_ref ( ) ) ,
132+ // add more variants when needed
133+ _ => quote:: quote! { crate :: interpreter:: function:: StaticType :: Any } ,
134+ }
135+ }
136+
137+ fn map_type_path ( p : & syn:: TypePath ) -> TokenStream {
138+ let segment = p. path . segments . last ( ) . unwrap ( ) ;
139+
140+ match segment. ident . to_string ( ) . as_str ( ) {
141+ // Primitive single identifiers
142+ "i32" | "i64" | "isize" | "u32" | "u64" => {
143+ quote:: quote! { crate :: interpreter:: function:: StaticType :: Int }
144+ }
145+ "f32" | "f64" => {
146+ quote:: quote! { crate :: interpreter:: function:: StaticType :: Float }
147+ }
148+ "bool" => {
149+ quote:: quote! { crate :: interpreter:: function:: StaticType :: Bool }
150+ }
151+ "String" | "str" => {
152+ quote:: quote! { crate :: interpreter:: function:: StaticType :: String }
153+ }
154+
155+ // Generic wrappers like anyhow::Result<T>, std::result::Result<T>
156+ // "HashMap" =>
157+ "Result" => match & segment. arguments {
158+ syn:: PathArguments :: AngleBracketed ( args) => {
159+ // Extract the first generic argument
160+ if let Some ( syn:: GenericArgument :: Type ( inner_ty) ) = args. args . first ( ) {
161+ // Recurse on T
162+ map_type ( inner_ty)
163+ } else {
164+ panic ! ( "Result without generic arguments" ) ;
165+ }
166+ }
167+
168+ _ => {
169+ panic ! ( "Result return type found without syn::PathArguments::AngleBracketed" ) ;
170+ }
171+ } ,
172+
173+ // Fallback
174+ _ => {
175+ quote:: quote! { crate :: interpreter:: function:: StaticType :: Any }
176+ }
177+ }
178+ }
179+
115180/// Wraps an original rust function `function` in an outer function with the identifier `identifier`
116181/// It's registered with the environment as `register_as_function_name`
117182/// The argument translations mapping is defined by `input_arguments`
0 commit comments