daily pastebin goal
68%
SHARE
TWEET

Untitled

a guest Jan 18th, 2019 75 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top