lib.rs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. use proc_macro::TokenStream;
  2. use std::fmt::format;
  3. use quote::{quote, quote_spanned, TokenStreamExt, ToTokens};
  4. use syn::parse::{Parse, ParseStream, Result};
  5. use syn::spanned::Spanned;
  6. use syn::{token, parse_macro_input, Ident, Token, Type, Stmt, Block, Error};
  7. use syn::token::RArrow;
  8. use proc_macro_error::{proc_macro_error, abort};
  9. #[macro_use]
  10. extern crate syn;
  11. const fmt_tip:&str = "`proc fn ProcName (Arg: ArgType) -> (Ret: RetType) { ... }`";
  12. struct ArgDef {
  13. name: Ident,
  14. colon_token: token::Colon,
  15. type_name: Type,
  16. }
  17. struct FnDef {
  18. name: Ident,
  19. args: Option<ArgDef>,
  20. ret: Option<ArgDef>,
  21. fn_body: Block,
  22. }
  23. impl Parse for ArgDef {
  24. fn parse(input: ParseStream) -> Result<Self> {
  25. Ok(ArgDef{
  26. name: input.parse()?,
  27. colon_token: input.parse()?,
  28. type_name: input.parse()?,
  29. })
  30. }
  31. }
  32. impl Parse for FnDef {
  33. fn parse(input: ParseStream) -> Result<Self> {
  34. let start_token_res = input.parse::<Ident>();
  35. let start_token = match start_token_res {
  36. Err(e) => {
  37. abort! { input.span(),
  38. "expect 'proc'";
  39. note = "expect 'proc' here, but not found.";
  40. help = fmt_tip;
  41. }
  42. },
  43. Ok(id) => id,
  44. };
  45. if start_token != "proc" {
  46. abort! { start_token.span(),
  47. "expect 'proc'";
  48. note = format!("expect 'proc' here, but found '{}'", start_token);
  49. help = fmt_tip;
  50. }
  51. }
  52. let fn_token_res = input.parse::<Token![fn]>();
  53. match fn_token_res {
  54. Err(e) => {
  55. abort! { input.span(),
  56. "expect 'fn'";
  57. note = "expect 'fn' here, but not found.";
  58. help = fmt_tip;
  59. }
  60. },
  61. Ok(_) => (),
  62. };
  63. let fn_name_res = input.parse::<Ident>();
  64. let fn_name = match fn_name_res {
  65. Err(e) => {
  66. abort! { input.span(),
  67. "expect proc name";
  68. note = "expect an ident here, but not found.";
  69. help = fmt_tip;
  70. }
  71. },
  72. Ok(id) => id,
  73. };
  74. let args_pat_inner;
  75. parenthesized!(args_pat_inner in input);
  76. let args = if args_pat_inner.is_empty() {
  77. None
  78. }else{
  79. let args_parse_res = args_pat_inner.parse::<ArgDef>();
  80. match args_parse_res {
  81. Err(e) => {
  82. abort! { input.span(),
  83. "expect args define or nothing";
  84. note = "expect args define or nothing";
  85. help = fmt_tip;
  86. }
  87. },
  88. Ok(t) => Option::Some(t),
  89. }
  90. };
  91. let ra_res = input.parse::<token::RArrow>();
  92. match ra_res {
  93. Err(e) => {
  94. abort! { input.span(),
  95. "expect '->'";
  96. note = "expect '->' here";
  97. help = fmt_tip;
  98. }
  99. },
  100. Ok(t) => Option::Some(t),
  101. };
  102. let ret_pat_inner;
  103. parenthesized!(ret_pat_inner in input);
  104. let ret = if ret_pat_inner.is_empty(){
  105. None
  106. }else{
  107. let ret_parse_res = ret_pat_inner.parse::<ArgDef>();
  108. match ret_parse_res {
  109. Err(e) => {
  110. abort! { input.span(),
  111. "expect ret define or nothing";
  112. note = "expect ret define or nothing";
  113. help = fmt_tip;
  114. }
  115. },
  116. Ok(t) => Option::Some(t),
  117. }
  118. };
  119. let fn_body_res = input.parse::<Block>();
  120. let fn_body = match fn_body_res {
  121. Err(e) => {
  122. abort! { input.span(),
  123. "expect function body here";
  124. note = "expect function body here, but not found.";
  125. help = fmt_tip;
  126. }
  127. },
  128. Ok(t) => t,
  129. };
  130. Ok(FnDef{
  131. name: fn_name,
  132. args: args,
  133. ret: ret,
  134. fn_body: fn_body,
  135. })
  136. }
  137. }
  138. /// Usage:
  139. ///
  140. /// zrfu_proc_def! {
  141. /// proc fn $PROC_NAME ( $ARGS_NAME: $ARGS_TYPE ) -> ( $RET_NAME: $RET_TYPE ) {
  142. ///
  143. /// }
  144. /// }
  145. ///
  146. /// For example:
  147. ///
  148. /// zrfu_proc_def! {
  149. /// proc fn TestProcAR ( in: Type1 ) -> ( out: Type2 ) {
  150. /// // ...
  151. /// }
  152. /// }
  153. ///
  154. /// zrfu_proc_def! {
  155. /// proc fn TestProcN () -> () {
  156. /// // ...
  157. /// }
  158. /// }
  159. ///
  160. /// zrfu_proc_def! {
  161. /// proc fn TestProcA ( in: Type1 ) -> () {
  162. /// // ...
  163. /// }
  164. /// }
  165. ///
  166. /// zrfu_proc_def! {
  167. /// proc fn TestProcR () -> ( out: Type2 ) {
  168. /// // ...
  169. /// }
  170. /// }
  171. ///
  172. #[proc_macro]
  173. #[proc_macro_error]
  174. pub fn zrfu_proc_def(input: TokenStream) -> TokenStream {
  175. let ast = parse_macro_input!(input as FnDef);
  176. let tk_proc_name = ast.name;
  177. let mut tk_strm_blk = proc_macro2::TokenStream::new();
  178. tk_strm_blk.append_all(ast.fn_body.stmts);
  179. let tk_stmts = tk_strm_blk;
  180. let tk_fields = match &ast.args {
  181. None => {
  182. match &ast.ret {
  183. None => {
  184. quote!{
  185. proc_name: String,
  186. }
  187. },
  188. Some(ret) => {
  189. let tk_ret_type = ret.type_name.clone();
  190. quote!{
  191. proc_name: String,
  192. ret: ZRFUProcReturn<#tk_ret_type>,
  193. }
  194. },
  195. }
  196. },
  197. Some(arg) => {
  198. match &ast.ret {
  199. None => {
  200. let tk_args_type = arg.type_name.clone();
  201. quote!{
  202. proc_name: String,
  203. args: ZRFUProcArgs<#tk_args_type>,
  204. }
  205. },
  206. Some(ret) => {
  207. let tk_ret_type = ret.type_name.clone();
  208. let tk_args_type = arg.type_name.clone();
  209. quote!{
  210. proc_name: String,
  211. ret: ZRFUProcReturn<#tk_ret_type>,
  212. args: ZRFUProcArgs<#tk_args_type>,
  213. }
  214. },
  215. }
  216. },
  217. };
  218. let tk_decode_input = match &ast.args {
  219. None => {
  220. quote!{
  221. ZRFUProcResultCode::NoArgsNeed
  222. }
  223. },
  224. Some(_) => {
  225. quote!{
  226. self.args.cbor_deserialize(bv)
  227. }
  228. },
  229. };
  230. let tk_encode_return = match &ast.ret {
  231. None => {
  232. quote!{
  233. ZRFUProcResultCode::NoReturnProvided
  234. }
  235. },
  236. Some(_) => {
  237. quote!{
  238. self.ret.cbor_serialize(bv)
  239. }
  240. },
  241. };
  242. let tk_process_input = match &ast.args {
  243. None => {
  244. quote!{
  245. }
  246. },
  247. Some(arg) => {
  248. let tk_argname = arg.name.clone();
  249. quote!{
  250. let #tk_argname = match self.args.get_data() {
  251. None => { return ZRFUProcResultCode::CanNotGetArgs; },
  252. Some(t) => t,
  253. };
  254. }
  255. },
  256. };
  257. let tk_process_return = match &ast.ret {
  258. None => {
  259. quote!{
  260. }
  261. },
  262. Some(ret) => {
  263. let tk_retname = ret.name.clone();
  264. quote!{
  265. self.ret.set_data(#tk_retname);
  266. }
  267. },
  268. };
  269. let tk_new_inst = match &ast.args {
  270. None => {
  271. match &ast.ret {
  272. None => {
  273. quote!{
  274. proc_name: name,
  275. }
  276. },
  277. Some(_) => {
  278. quote!{
  279. proc_name: name,
  280. ret: ZRFUProcReturn::new(),
  281. }
  282. },
  283. }
  284. },
  285. Some(_) => {
  286. match &ast.ret {
  287. None => {
  288. quote!{
  289. proc_name: name,
  290. args: ZRFUProcArgs::new(),
  291. }
  292. },
  293. Some(ret) => {
  294. quote!{
  295. proc_name: name,
  296. ret: ZRFUProcReturn::new(),
  297. args: ZRFUProcArgs::new(),
  298. }
  299. },
  300. }
  301. },
  302. };
  303. let expanded = quote!{
  304. pub struct #tk_proc_name {
  305. #tk_fields
  306. }
  307. impl ZRFUProcInstanceTrait for #tk_proc_name {
  308. fn decode_input(&mut self, bv: &mut ZRFUBytesVec) -> ZRFUProcResultCode {
  309. #tk_decode_input
  310. }
  311. fn call(&mut self) -> ZRFUProcResultCode {
  312. #tk_process_input
  313. #tk_stmts
  314. #tk_process_return
  315. return ZRFUProcResultCode::Ok;
  316. }
  317. fn encode_return(&mut self, bv: &mut ZRFUBytesVec) -> ZRFUProcResultCode {
  318. #tk_encode_return
  319. }
  320. }
  321. impl #tk_proc_name {
  322. fn factory(name: String) -> Box<dyn ZRFUProcInstanceTrait> {
  323. Box::new(#tk_proc_name{
  324. #tk_new_inst
  325. })
  326. }
  327. }
  328. };
  329. TokenStream::from(expanded)
  330. }