1extern crate proc_macro;
2use proc_macro::TokenStream;
3
4mod component;
5
6use syn::{DeriveInput, Expr};
7
8#[proc_macro_derive(Component, attributes(component))]
9pub fn component(input: TokenStream) -> TokenStream {
10 let input: DeriveInput = syn::parse(input).unwrap();
11
12 let gen = component::impl_component(&input);
13
14 gen.into()
15}
16
17fn eval_expr(expr: Expr) -> u64 {
19 use syn::{BinOp, ExprBinary, ExprLit, ExprUnary, Lit, UnOp};
20 match expr {
21 Expr::Binary(ExprBinary {
22 left, op, right, ..
23 }) => {
24 let l = eval_expr(*left);
25 let r = eval_expr(*right);
26 match op {
27 BinOp::Add(_) => l + r,
28 BinOp::Sub(_) => l - r,
29 BinOp::Mul(_) => l * r,
30 BinOp::Div(_) => l / r,
31 BinOp::Rem(_) => l % r,
32 BinOp::BitXor(_) => l ^ r,
33 BinOp::BitAnd(_) => l & r,
34 BinOp::BitOr(_) => l | r,
35 BinOp::Shl(_) => l << r,
36 BinOp::Shr(_) => l >> r,
37 op => panic!("Unsuported operator type: {:?}", op),
38 }
39 }
40 Expr::Unary(ExprUnary { op, expr, .. }) => {
41 let a = eval_expr(*expr);
42 match op {
43 UnOp::Not(_) => !a,
44 op => panic!("Unsuported operator type: {:?}", op),
45 }
46 }
47 Expr::Lit(ExprLit {
48 lit: Lit::Int(i), ..
49 }) => i.base10_parse::<u64>().expect("Invalid integer literal"),
50 _ => panic!("Unsuported expression type"),
51 }
52}
53
54#[allow(non_snake_case)]
58#[proc_macro]
59pub fn U(input: TokenStream) -> TokenStream {
60 use proc_macro2::Span;
61 use quote::quote;
62 use syn::Ident;
63 let expr: Expr = syn::parse(input).expect("Expected an expression");
64
65 let num = eval_expr(expr);
66 let ident = Ident::new(&format!("U{}", num), Span::call_site());
67 (quote! {
68 #ident
69 })
70 .into()
71}