Guest User

Untitled

a guest
Jan 18th, 2019
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.39 KB | None | 0 0
  1. use proc_macro2::{Span, TokenStream};
  2. use quote::quote;
  3. use syn::{
  4. fold::Fold,
  5. parse::{Parse, ParseStream, Result},
  6. parse_quote,
  7. punctuated::Punctuated,
  8. Expr, ExprLit, FieldValue, Ident, ItemFn, LitStr, Local, Member, Pat, Stmt, Token,
  9. };
  10.  
  11. pub fn gen(tokens: TokenStream) -> TokenStream {
  12. let ast = syn::parse2::<ItemFn>(tokens).unwrap();
  13. let mut cs = RewriteSignals::default();
  14. let ast = cs.fold_item_fn(ast);
  15. // println!("ast = {:#?}", ast);
  16. let output = quote! {
  17. #ast
  18. };
  19. output.into()
  20. }
  21.  
  22. pub enum SignalAttr {
  23. Expr(syn::Expr),
  24. NamedExpr {
  25. name: syn::Ident,
  26. colon: syn::token::Colon,
  27. expr: Expr,
  28. },
  29. }
  30.  
  31. impl SignalAttr {
  32. fn is_keyword(path: Ident) -> Result<Ident> {
  33. if path == "shape"
  34. || path == "name"
  35. || path == "reset"
  36. || path == "reset_less"
  37. || path == "min"
  38. || path == "max"
  39. {
  40. Ok(path)
  41. } else {
  42. Err(syn::Error::new(
  43. path.span(),
  44. "expected `shape`, `name`, `reset`, `reset_less`, `min`, or `max`.",
  45. ))
  46. }
  47. }
  48. }
  49.  
  50. impl Parse for SignalAttr {
  51. fn parse(input: ParseStream) -> Result<Self> {
  52. if input.peek(Ident) && input.peek2(Token![:]) {
  53. let name: Ident = input.parse()?;
  54. let name = Self::is_keyword(name)?;
  55. let colon: Token![:] = input.parse()?;
  56. let expr: Expr = input.parse()?;
  57. Ok(SignalAttr::NamedExpr { name, colon, expr })
  58. } else {
  59. let e: Expr = input.parse()?;
  60. Ok(SignalAttr::Expr(e))
  61. }
  62. }
  63. }
  64.  
  65. pub fn is_signal(e: &Expr) -> bool {
  66. match e {
  67. Expr::Macro(m) => m.mac.path.is_ident("signal"),
  68. _ => false,
  69. }
  70. }
  71.  
  72. pub fn validate_signal_attrs(attrs: &Punctuated<SignalAttr, Token![,]>) -> Result<()> {
  73. use syn::spanned::Spanned;
  74. for attr in attrs.iter().skip(1) {
  75. match attr {
  76. SignalAttr::Expr(e) => Err(syn::Error::new(e.span(), "expected named expression"))?,
  77. _ => {}
  78. }
  79. }
  80. Ok(())
  81. }
  82.  
  83. pub struct RewriteSignals {
  84. name: Option<Ident>,
  85. }
  86.  
  87. impl Default for RewriteSignals {
  88. fn default() -> Self {
  89. RewriteSignals { name: None }
  90. }
  91. }
  92.  
  93. impl RewriteSignals {
  94. fn rewrite_field(&mut self, fv: FieldValue) -> FieldValue {
  95. let FieldValue {
  96. attrs,
  97. member,
  98. expr,
  99. ..
  100. } = fv;
  101.  
  102. assert!(self.name.is_none());
  103. self.name = match member {
  104. Member::Named(ref ident) => Some(ident.clone()),
  105. _ => unreachable!(),
  106. };
  107. let expr = self.fold_expr(expr);
  108.  
  109. parse_quote! {
  110. #(#attrs),* #member : #expr
  111. }
  112. }
  113.  
  114. fn rewrite_let(&mut self, local: Local) -> Stmt {
  115. let Local { pats, ty, init, .. } = local;
  116. let pat = &pats[0];
  117. let ty = ty.map(|(colon_token, ty)| quote!(#colon_token #ty));
  118. assert!(self.name.is_none());
  119. self.name = match *pat {
  120. Pat::Ident(ref p) => Some(p.ident.clone()),
  121. _ => unreachable!(),
  122. };
  123.  
  124. let init = self.fold_expr(*init.unwrap().1);
  125.  
  126. parse_quote! {
  127. let #pat #ty = #init;
  128. }
  129. }
  130.  
  131. fn parse_signal(expr: Expr) -> SignalParams {
  132. match expr {
  133. Expr::Macro(syn::ExprMacro { mac, .. }) => {
  134. parse_signal_attrs(mac.tts).expect("Failed to parse signal attributes")
  135. }
  136. _ => unreachable!(),
  137. }
  138. }
  139.  
  140. fn gen_signal(params: &SignalParams) -> Expr {
  141. assert!(params.name.is_some());
  142. let name = &params.name;
  143.  
  144. let reset = match params.reset {
  145. Some(ref reset) => quote!(#reset),
  146. None => quote!(0),
  147. };
  148.  
  149. let reset_less = match params.reset_less {
  150. Some(ref reset_less) => quote!(#reset_less),
  151. None => quote!(false),
  152. };
  153.  
  154. let min_max = match (&params.shape, &params.min, &params.max) {
  155. (None, None, None) => quote!(0, 1),
  156. (Some((width, _)), _, _) => quote!(0, (1 << #width) - 1),
  157. (_, Some(min), None) => quote!(#min as i64, 1),
  158. (_, None, Some(max)) => quote!(0, #max as i64),
  159. (_, Some(min), Some(max)) => quote!(#min as i64, #max as i64),
  160. };
  161.  
  162. parse_quote! {
  163. Value::signal(#name, #min_max, #reset, #reset_less)
  164. }
  165. }
  166.  
  167. fn is_named_member(member: &Member) -> bool {
  168. match member {
  169. Member::Named(_) => true,
  170. _ => false,
  171. }
  172. }
  173.  
  174. fn gen_string_lit(ident: &str) -> Expr {
  175. ExprLit {
  176. attrs: vec![],
  177. lit: LitStr::new(ident, Span::call_site()).into(),
  178. }
  179. .into()
  180. }
  181. }
  182.  
  183. impl Fold for RewriteSignals {
  184. fn fold_expr(&mut self, e: Expr) -> Expr {
  185. if !is_signal(&e) {
  186. return syn::fold::fold_expr(self, e);
  187. }
  188.  
  189. let mut params = Self::parse_signal(e);
  190. // set name from variable name if signal! didn't specify one.
  191. if params.name.is_none() {
  192. params.name = match self.name.take() {
  193. Some(name) => Some(Self::gen_string_lit(&name.to_string())),
  194. None => Some(Self::gen_string_lit("$signal")),
  195. };
  196. }
  197.  
  198. Self::gen_signal(&params)
  199. }
  200.  
  201. fn fold_field_value(&mut self, f: FieldValue) -> FieldValue {
  202. if Self::is_named_member(&f.member) && is_signal(&f.expr) {
  203. return self.rewrite_field(f);
  204. }
  205. syn::fold::fold_field_value(self, f)
  206. }
  207.  
  208. fn fold_stmt(&mut self, s: Stmt) -> Stmt {
  209. match s {
  210. Stmt::Local(s) => {
  211. if s.init.as_ref().map_or(false, |(_, init)| is_signal(init)) {
  212. return self.rewrite_let(s);
  213. }
  214. Stmt::Local(syn::fold::fold_local(self, s))
  215. }
  216. _ => syn::fold::fold_stmt(self, s),
  217. }
  218. }
  219. }
  220.  
  221. #[derive(Default)]
  222. pub struct SignalParams {
  223. pub shape: Option<(Expr, Expr)>,
  224. pub name: Option<Expr>,
  225. pub reset: Option<Expr>,
  226. pub reset_less: Option<Expr>,
  227. pub min: Option<Expr>,
  228. pub max: Option<Expr>,
  229. }
  230.  
  231. pub fn parse_signal_attrs(tokens: TokenStream) -> Result<SignalParams> {
  232. let parser = Punctuated::<SignalAttr, Token![,]>::parse_terminated;
  233. let attrs = syn::parse::Parser::parse2(parser, tokens)?;
  234. validate_signal_attrs(&attrs)?;
  235. let mut params = SignalParams::default();
  236. for attr in attrs {
  237. match attr {
  238. SignalAttr::Expr(expr) => {
  239. params.shape = Some((expr, syn::parse_str("false").expect("bug")))
  240. }
  241. SignalAttr::NamedExpr { name, expr, .. } => {
  242. if name == "name" {
  243. params.name = Some(expr)
  244. } else if name == "reset" {
  245. params.reset = Some(expr)
  246. } else if name == "reset_less" {
  247. params.reset_less = Some(expr)
  248. } else if name == "min" {
  249. params.min = Some(expr)
  250. } else if name == "max" {
  251. params.max = Some(expr)
  252. }
  253. }
  254. }
  255. }
  256. Ok(params)
  257. }
  258.  
  259. #[cfg(test)]
  260. mod test {
  261. use matches::matches;
  262. use syn::{self, fold::Fold};
  263.  
  264. #[test]
  265. fn test_is_signal() {
  266. let t: syn::Expr = syn::parse_str("signal!()").unwrap();
  267. assert!(super::is_signal(&t));
  268. }
  269.  
  270. #[test]
  271. fn test_signal_empty_attrs() {
  272. let parser =
  273. syn::punctuated::Punctuated::<super::SignalAttr, syn::Token![,]>::parse_terminated;
  274. let attrs = syn::parse::Parser::parse_str(parser, "").expect("Failed to parse");
  275. assert!(attrs.is_empty());
  276. super::validate_signal_attrs(&attrs).expect("Invalid attributes");
  277. }
  278.  
  279. #[test]
  280. fn test_signal_expr_attrs() {
  281. let parser =
  282. syn::punctuated::Punctuated::<super::SignalAttr, syn::Token![,]>::parse_terminated;
  283. let attrs = syn::parse::Parser::parse_str(parser, "1").expect("Failed to parse");
  284. assert_eq!(attrs.len(), 1);
  285. super::validate_signal_attrs(&attrs).expect("Invalid attributes");
  286. }
  287.  
  288. #[test]
  289. fn test_signal_named_attrs() {
  290. let parser =
  291. syn::punctuated::Punctuated::<super::SignalAttr, syn::Token![,]>::parse_terminated;
  292. let attrs =
  293. syn::parse::Parser::parse_str(parser, "name: \"sig\"").expect("Failed to parse");
  294. assert_eq!(attrs.len(), 1);
  295. super::validate_signal_attrs(&attrs).expect("Invalid attributes");
  296. }
  297.  
  298. #[test]
  299. fn test_signal_multi_attrs() {
  300. let parser =
  301. syn::punctuated::Punctuated::<super::SignalAttr, syn::Token![,]>::parse_terminated;
  302. let attrs =
  303. syn::parse::Parser::parse_str(parser, "1, name: \"sig\"").expect("Failed to parse");
  304. assert_eq!(attrs.len(), 2);
  305. super::validate_signal_attrs(&attrs).expect("Invalid attributes");
  306. }
  307.  
  308. #[test]
  309. fn test_signal_all_attrs() {
  310. let parser =
  311. syn::punctuated::Punctuated::<super::SignalAttr, syn::Token![,]>::parse_terminated;
  312. let attrs = syn::parse::Parser::parse_str(
  313. parser,
  314. "1, name: \"sig\", reset: 0, reset_less: true, min: -1, max: 1",
  315. )
  316. .expect("Failed to parse");
  317. assert_eq!(attrs.len(), 6);
  318. super::validate_signal_attrs(&attrs).expect("Invalid attributes");
  319. }
  320.  
  321. #[test]
  322. #[should_panic]
  323. fn test_invalid_signal_name_attrs() {
  324. let parser =
  325. syn::punctuated::Punctuated::<super::SignalAttr, syn::Token![,]>::parse_terminated;
  326. let attrs = syn::parse::Parser::parse_str(parser, "foo: \"sig\"").expect("Failed to parse");
  327. super::validate_signal_attrs(&attrs).expect("Invalid attributes");
  328. }
  329.  
  330. #[test]
  331. #[should_panic]
  332. fn test_invalid_signal_multi_attrs() {
  333. let parser =
  334. syn::punctuated::Punctuated::<super::SignalAttr, syn::Token![,]>::parse_terminated;
  335. let attrs =
  336. syn::parse::Parser::parse_str(parser, "foo: \"sig\", 1").expect("Failed to parse");
  337. super::validate_signal_attrs(&attrs).expect("Invalid attributes");
  338. }
  339.  
  340. #[test]
  341. fn test_parse_empty_signal() {
  342. let t: syn::Expr = syn::parse_str("signal!()").unwrap();
  343. match t {
  344. syn::Expr::Macro(syn::ExprMacro { mac, .. }) => {
  345. let params =
  346. super::parse_signal_attrs(mac.tts).expect("Failed to parse signal attributes");
  347. assert_eq!(params.shape, None);
  348. assert_eq!(params.name, None);
  349. assert_eq!(params.reset, None);
  350. assert_eq!(params.reset_less, None);
  351. assert_eq!(params.min, None);
  352. assert_eq!(params.max, None);
  353. }
  354. _ => panic!("Expected a macro"),
  355. }
  356. }
  357.  
  358. #[test]
  359. fn test_parse_simple_signal() {
  360. use syn::Expr;
  361. let t: Expr = syn::parse_str("signal!(1)").unwrap();
  362. match t {
  363. Expr::Macro(syn::ExprMacro { mac, .. }) => {
  364. let params =
  365. super::parse_signal_attrs(mac.tts).expect("Failed to parse signal attributes");
  366. assert_eq!(
  367. params.shape,
  368. Some((
  369. syn::parse_str("1").unwrap(),
  370. syn::parse_str("false").unwrap()
  371. ))
  372. );
  373. assert_eq!(params.name, None);
  374. assert_eq!(params.reset, None);
  375. assert_eq!(params.reset_less, None);
  376. assert_eq!(params.min, None);
  377. assert_eq!(params.max, None);
  378. }
  379. _ => panic!("Expected a macro"),
  380. }
  381. }
  382.  
  383. #[test]
  384. fn test_parse_complex_signal() {
  385. use syn::Expr;
  386. let t: Expr =
  387. syn::parse_str("signal!(name: \"sig\", reset: 2, reset_less: true, min: 0, max: 10)")
  388. .unwrap();
  389. match t {
  390. Expr::Macro(syn::ExprMacro { mac, .. }) => {
  391. let params =
  392. super::parse_signal_attrs(mac.tts).expect("Failed to parse signal attributes");
  393. assert_eq!(params.shape, None);
  394. assert_eq!(params.name, Some(syn::parse_str("\"sig\"").unwrap()));
  395. assert_eq!(params.reset, Some(syn::parse_str("2").unwrap()));
  396. assert_eq!(params.reset_less, Some(syn::parse_str("true").unwrap()));
  397. assert_eq!(params.min, Some(syn::parse_str("0").unwrap()));
  398. assert_eq!(params.max, Some(syn::parse_str("10").unwrap()));
  399. }
  400. _ => panic!("Expected a macro"),
  401. }
  402. }
  403.  
  404. #[test]
  405. fn test_let_signal() {
  406. let t: syn::Stmt = syn::parse_str("let o = signal!();").unwrap();
  407. let mut cs = super::RewriteSignals::default();
  408. cs.fold_stmt(t);
  409. }
  410.  
  411. #[test]
  412. fn test_field_signal() {
  413. let t: syn::ItemFn =
  414. syn::parse_str("pub fn new() -> Self { Foo { a: signal!() } }").unwrap();
  415. let mut cs = super::RewriteSignals::default();
  416. cs.fold_item_fn(t);
  417. }
  418.  
  419. #[test]
  420. fn test_expr_signal() {
  421. let t: syn::Stmt = syn::parse_str(
  422. "let rst = if reset_less { None } else { Some(signal!(name: \"rst\")) };",
  423. )
  424. .unwrap();
  425. let mut cs = super::RewriteSignals::default();
  426. cs.fold_stmt(t);
  427. }
  428.  
  429. #[test]
  430. fn test_domain_attribute() {
  431. use crate::domain::Domain;
  432. use proc_macro2::Span;
  433. use syn::Ident;
  434. let parser = syn::Attribute::parse_outer;
  435. let t = syn::parse::Parser::parse_str(parser, "#[comb]").unwrap();
  436. assert_eq!(t.len(), 1);
  437. assert_eq!(Domain::try_from(&t[0]).expect("Expected Domain"), Domain::Comb);
  438.  
  439. let t = syn::parse::Parser::parse_str(parser, "#[sync]").unwrap();
  440. assert_eq!(t.len(), 1);
  441. assert_eq!(Domain::try_from(&t[0]).expect("Expected Domain"), Domain::Sync(Ident::new("sync", Span::call_site())));
  442.  
  443. let t = syn::parse::Parser::parse_str(parser, "#[sync(\"por\")]").unwrap();
  444. assert_eq!(t.len(), 1);
  445. assert_eq!(Domain::try_from(&t[0]).expect("Expected Domain"), Domain::Sync(Ident::new("por", Span::call_site())));
  446. }
  447.  
  448. /*
  449. #[test]
  450. fn test_stmt_attr() {
  451. let t: syn::Stmt = syn::parse_str("#[sync] self.v = self.v + 1;").unwrap();
  452. println!("t = {:#?}", t);
  453. match t {
  454. syn::Stmt::Semi(ref e, ..) => {
  455.  
  456. },
  457. _ => panic!("Expected Stmt::Semi")
  458. }
  459. }
  460. */
  461. }
Add Comment
Please, Sign In to add comment