Skip to main content

impl_sim/
lib.rs

1#![doc(html_root_url = "https://docs.rs/impl_sim/0.3.0")]
2//! impl_sim auto implement callback functions for trait Sim
3//!
4
5use proc_macro::TokenStream;
6use proc_macro2::TokenStream as PM2TS;
7use proc_macro2::TokenTree;
8// use proc_macro2::{TokenTree, Group, Ident, Literal, Punct};
9// use proc_macro2::{Delimiter, Span, Spacing};
10use quote::{quote, ToTokens}; // quote::ToTokens in proc_macro2
11use syn; // syn::{parse_macro_input, ItemFn};
12
13/// macro implement callback function
14#[proc_macro]
15pub fn impl_sim_fn(item: TokenStream) -> TokenStream {
16  let ts: PM2TS = item.into();
17  let tk = match ts.into_iter().next().unwrap() {
18    TokenTree::Ident(t) => Some(t), // match only Ident
19    _ => None // panic when arrive here
20  };
21  let f = &tk.unwrap();
22  let s = &f.to_string();
23  match s.as_str() {
24    "draw_geom" => {
25      quote! {
26        /// #f
27        fn #f(&self, geom: dGeomID,
28          pos: Option<*const dReal>, rot: Option<*const dReal>, ws: i32) {
29          ostatln!(concat!("called ", #s));
30          self.super_get().#f(geom, pos, rot, ws);
31        }
32      }
33    },
34    "near_callback" => {
35      quote! {
36        /// #f
37        fn #f(&mut self, dat: *mut c_void, o1: dGeomID, o2: dGeomID) {
38          ostatln!(concat!("called ", #s));
39          self.super_mut().#f(dat, o1, o2);
40        }
41      }
42    },
43    "step_callback" => {
44      quote! {
45        /// #f
46        fn #f(&mut self, pause: i32) {
47          ostatln!(concat!("called ", #s));
48          self.super_mut().#f(pause);
49        }
50      }
51    },
52    "command_callback" => {
53      quote! {
54        /// #f
55        fn #f(&mut self, cmd: i32) {
56          ostatln!(concat!("called ", #s));
57          self.super_mut().#f(cmd);
58        }
59      }
60    },
61    _ => {
62      quote! {
63        /// #f
64        fn #f(&mut self) {
65          ostatln!(concat!("called ", #s));
66          self.super_mut().#f();
67        }
68      }
69    }
70  }.into()
71}
72
73/// derive callback functions for trait Sim
74#[proc_macro_attribute]
75pub fn impl_sim_derive(attr: TokenStream, item: TokenStream) -> TokenStream {
76  let mut ast = syn::parse_macro_input!(item as syn::ItemImpl);
77  let ts: PM2TS = attr.into();
78  for tt in ts {
79    match tt {
80      TokenTree::Ident(f) => { // match only Ident
81        ast.items.push(syn::parse_quote! {
82          impl_sim_fn!(#f);
83        });
84      },
85      _ => {} // skip Punct ',' etc
86    }
87  }
88  ast.into_token_stream().into()
89}