pub fn infer_type_internal(_attr: TokenStream, item: TokenStream) -> TokenStream {
    //  println!("attr: {:#?}", attr); println!("item: {:#?}", item);
    //  Parse the macro input as Rust function definition.
    let input: syn::ItemFn = parse_macro_input!(item as syn::ItemFn);
    //  println!("input: {:#?}", input);

    //  Process the Function Declaration
    //  e.g. `fn start_sensor_listener(sensor: _, sensor_type: _, poll_time: _) -> MynewtResult<()>`
    let sig = &input.sig;
    //  println!("sig: {:#?}", sig);

    //  `fname` is function name e.g. `start_sensor_listener`
    let fname = sig.ident.to_string();
    unsafe { CURRENT_FUNC = Some(Box::new(fname.clone())); }
    //  println!("fname: {:#?}", fname);

    //  For each parameter e.g. `sensor`, `sensor_type`, `poll_time`...
    let mut all_para: ParaMap = HashMap::new();
    for input in &sig.inputs {
        //  Mark each parameter for Type Inference.
        //  println!("input: {:#?}", input);
        match input {
            syn::FnArg::Typed(arg_captured) => {
                //  println!("arg_captured: {:#?}", arg_captured);
                let pat = &arg_captured.pat;
                //  println!("pat: {:#?}", pat);
                //  `para` is the name of the parameter e.g. `sensor`
                let para = quote!{ #pat }.to_string();
                //  println!("para: {:#?}", para);
                all_para.insert(Box::new(para), Box::new("_".to_string()));
                s(pat.span());
            }
            _ => { assert!(false, "Unknown input"); }
        }
    }

    //  Infer the types from the Block of code inside the function.
    let block = input.block;
    infer_from_block(&mut all_para, &block);

    //  Now that the types have been inferred, generate the Rust function declaration with the inferred types.
    let mut new_inputs = sig.inputs.clone();
    let mut all_para_types: ParaTypeList = Vec::new();
    //  For each parameter e.g. `sensor`, `sensor_type`, `poll_time`...
    for input in &mut new_inputs {
        //  Set the inferred type of each parameter.
        //  println!("input: {:#?}", input);
        match input {
            syn::FnArg::Typed(arg_captured) => {
                //  `para` is the name of the parameter e.g. `sensor`
                //  Change the type of the argument.
                let pat = &arg_captured.pat;
                let para = quote!{ #pat }.to_string();
                let type_str = match all_para.get(&para) {
                    //  Return the type if it exists.
                    Some(type_str) => type_str,
                    //  If we can't infer the type, leave as `_` for now. Maybe another function will infer this type.
                    None => "_"
                };
                if type_str != "_" {
                    //  If the type exists, remember it.
                    let tokens = type_str.parse().unwrap();
                    arg_captured.ty =  Box::new(parse_macro_input!(tokens as syn::Type));
                }
                //  Remember the parameter type globally e.g. `[sensor, &Strn]`
                let para_type: ParaType = vec![Box::new(para), Box::new(type_str.to_string())];
                all_para_types.push(para_type);                
            }
            _ => { assert!(false, "Unknown input"); }
        }
    }
    //  Add this function to the global declaration list. Must reload because another process may have updated the file.
    let mut new_func_map = load_decls();
    new_func_map.insert(Box::new(fname), all_para_types);
    save_decls(&new_func_map);

    //  Combine the new Rust function definition with the old function body.
    let new_sig = syn::Signature {
        inputs: new_inputs,
        ..sig.clone()
    };
    let output = syn::ItemFn {
        sig:    new_sig,
        block:  block,
        ..input
    };
    //  Return the new Rust function definition to the Rust Compiler.
    let expanded = quote! {        
        #output
    };
    expanded.into()
}
/// Given a Rust function definition, infer the placeholder types in the function
Given a Rust function definition, infer the placeholder types in the function
Given a Rust function definition infer the placeholder types in the function
pub fn infer_type_internal(_attr: TokenStream, item: TokenStream) -> TokenStream {
    //  println!("attr: {:#?}", attr); println!("item: {:#?}", item);
    //  Parse the macro input as Rust function definition.
    let input: syn::ItemFn = parse_macro_input!(item as syn::ItemFn);
    //  println!("input: {:#?}", input);
    //  Process the Function Declaration
    //  e.g. `fn start_sensor_listener(sensor: _, sensor_type: _, poll_time: _) -> MynewtResult<()>`
    let sig = &input.sig;
    //  println!("sig: {:#?}", sig);
    //  `fname` is function name e.g. `start_sensor_listener`
    let fname = sig.ident.to_string();
    unsafe { CURRENT_FUNC = Some(Box::new(fname.clone())); }
    //  println!("fname: {:#?}", fname);
    //  For each parameter e.g. `sensor`, `sensor_type`, `poll_time`...
    let mut all_para: ParaMap = HashMap::new();
    for input in &sig.inputs {
        //  Mark each parameter for Type Inference.
        //  println!("input: {:#?}", input);
        match input {
            syn::FnArg::Typed(arg_captured) => {
                //  println!("arg_captured: {:#?}", arg_captured);
                let pat = &arg_captured.pat;
                //  println!("pat: {:#?}", pat);
                //  `para` is the name of the parameter e.g. `sensor`
                let para = quote!{ #pat }.to_string();
                //  println!("para: {:#?}", para);
                all_para.insert(Box::new(para), Box::new("_".to_string()));
                s(pat.span());
            }
            _ => { assert!(false, "Unknown input"); }
        }
    }
    //  Infer the types from the Block of code inside the function.
    let block = input.block;
    infer_from_block(&mut all_para, &block);
    //  Now that the types have been inferred, generate the Rust function declaration with the inferred types.
    let mut new_inputs = sig.inputs.clone();
    let mut all_para_types: ParaTypeList = Vec::new();
    //  For each parameter e.g. `sensor`, `sensor_type`, `poll_time`...
    for input in &mut new_inputs {
        //  Set the inferred type of each parameter.
        //  println!("input: {:#?}", input);
        match input {
            syn::FnArg::Typed(arg_captured) => {
                //  `para` is the name of the parameter e.g. `sensor`
                //  Change the type of the argument.
                let pat = &arg_captured.pat;
                let para = quote!{ #pat }.to_string();
                let type_str = match all_para.get(&para) {
                    //  Return the type if it exists.
                    Some(type_str) => type_str,
                    //  If we can't infer the type, leave as `_` for now. Maybe another function will infer this type.
                    None => "_"
                };
                if type_str != "_" {
                    //  If the type exists, remember it.
                    let tokens = type_str.parse().unwrap();
                    arg_captured.ty =  Box::new(parse_macro_input!(tokens as syn::Type));
                }
                //  Remember the parameter type globally e.g. `[sensor, &Strn]`
                let para_type: ParaType = vec![Box::new(para), Box::new(type_str.to_string())];
                all_para_types.push(para_type);                
            }
            _ => { assert!(false, "Unknown input"); }
        }
    }
    //  Add this function to the global declaration list. Must reload because another process may have updated the file.
    let mut new_func_map = load_decls();
    new_func_map.insert(Box::new(fname), all_para_types);
    save_decls(&new_func_map);
    //  Combine the new Rust function definition with the old function body.
    let new_sig = syn::Signature {
        inputs: new_inputs,
        ..sig.clone()
    };
    let output = syn::ItemFn {
        sig:    new_sig,
        block:  block,
        ..input
    };
    //  Return the new Rust function definition to the Rust Compiler.
    let expanded = quote! {        
        #output
    };
    expanded.into()
}
pub fn infer_type_internal ( _attr : TokenStream , item : TokenStream ) -> TokenStream { //  println!("attr: {:#?}", attr); println!("item: {:#?}", item); //  Parse the macro input as Rust function definition. let input : syn :: ItemFn = parse_macro_input ! ( item as syn ItemFn ) ; //  println!("input: {:#?}", input); //  Process the Function Declaration //  e.g. `fn start_sensor_listener(sensor: _, sensor_type: _, poll_time: _) -> MynewtResult<()>` let sig = & input . sig ; //  println!("sig: {:#?}", sig); //  `fname` is function name e.g. `start_sensor_listener` let fname = sig . ident . to_string ( ) ; unsafe { CURRENT_FUNC = Some ( Box :: new ( fname . clone ( ) ) ) ; } //  println!("fname: {:#?}", fname); //  For each parameter e.g. `sensor`, `sensor_type`, `poll_time`... let mut all_para : ParaMap = HashMap :: new ( ) ; for input in & sig . inputs { //  Mark each parameter for Type Inference. //  println!("input: {:#?}", input); match input { syn :: FnArg :: Typed ( arg_captured ) => { //  println!("arg_captured: {:#?}", arg_captured); let pat = & arg_captured . pat ; //  println!("pat: {:#?}", pat); //  `para` is the name of the parameter e.g. `sensor` let para = quote ! { pat } . to_string ( ) ; //  println!("para: {:#?}", para); all_para . insert ( Box :: new ( para ) , Box :: new ( " " . to_string ( ) ) ) ; s ( pat . span ( ) ) ; } _ => { assert ! ( false " " ) ; } } } //  Infer the types from the Block of code inside the function. let block = input . block ; infer_from_block ( & mut all_para , & block ) ; //  Now that the types have been inferred, generate the Rust function declaration with the inferred types. let mut new_inputs = sig . inputs . clone ( ) ; let mut all_para_types : ParaTypeList = Vec :: new ( ) ; //  For each parameter e.g. `sensor`, `sensor_type`, `poll_time`... for input in & mut new_inputs { //  Set the inferred type of each parameter. //  println!("input: {:#?}", input); match input { syn :: FnArg :: Typed ( arg_captured ) => { //  `para` is the name of the parameter e.g. `sensor` //  Change the type of the argument. let pat = & arg_captured . pat ; let para = quote ! { pat } . to_string ( ) ; let type_str = match all_para . get ( & para ) { //  Return the type if it exists. Some ( type_str ) => type_str , //  If we can't infer the type, leave as `_` for now. Maybe another function will infer this type. None => " " } ; if type_str != " " { //  If the type exists, remember it. let tokens = type_str . parse ( ) . unwrap ( ) ; arg_captured . ty = Box :: new ( parse_macro_input ! ( tokens as syn Type ) ) ; } //  Remember the parameter type globally e.g. `[sensor, &Strn]` let para_type : ParaType = vec ! [ Box new ( para ) Box new ( type_str to_string ( ) ) ] ; all_para_types . push ( para_type ) ; } _ => { assert ! ( false " " ) ; } } } //  Add this function to the global declaration list. Must reload because another process may have updated the file. let mut new_func_map = load_decls ( ) ; new_func_map . insert ( Box :: new ( fname ) , all_para_types ) ; save_decls ( & new_func_map ) ; //  Combine the new Rust function definition with the old function body. let new_sig = syn :: Signature { inputs : new_inputs , .. sig . clone ( ) } ; let output = syn :: ItemFn { sig : new_sig , block : block , .. input } ; //  Return the new Rust function definition to the Rust Compiler. let expanded = quote ! { output } ; expanded . into ( ) }
Given a Rust function definition, infer the placeholder types in the function
Given a Rust function definition infer the placeholder types in the function
_attr
TokenStream
item
TokenStream
_attr
TokenStream
item
TokenStream