Skip to main content

scal_ipc_macros/
lib.rs

1use proc_macro::TokenStream;
2use proc_macro2::LineColumn;
3use quote::quote;
4use syn::{
5    Expr, ItemFn, Token,
6    parse::{Parse, ParseStream},
7    parse_macro_input,
8    punctuated::Punctuated,
9    spanned::Spanned,
10};
11
12#[proc_macro_attribute]
13pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
14    let input_fn = parse_macro_input!(item as ItemFn);
15    let fn_block = &input_fn.block;
16
17    let expanded = quote! {
18        fn animation_main() -> ::scal_core::Project #fn_block
19
20        fn main() {
21            ::scal_ipc::run_main(animation_main);
22        }
23    };
24
25    expanded.into()
26}
27
28struct TimelineInput {
29    items: Punctuated<Expr, Token![,]>,
30}
31
32impl Parse for TimelineInput {
33    fn parse(input: ParseStream) -> syn::Result<Self> {
34        Ok(TimelineInput {
35            items: input.parse_terminated(Expr::parse, Token![,])?,
36        })
37    }
38}
39
40#[proc_macro]
41pub fn timeline(input: TokenStream) -> TokenStream {
42    let input = parse_macro_input!(input as TimelineInput);
43
44    let mut out = proc_macro2::TokenStream::new();
45
46    for item in &input.items {
47        let expr = item;
48        let sp: proc_macro2::Span = expr.span();
49        let lc: LineColumn = sp.start();
50        let line = lc.line as u32;
51
52        out.extend(quote! {
53            {
54                let __op = ::scal_core::IntoAnimOp::into_anim_op(#expr);
55                __op.with_location(::scal_core::SourceLoc {
56                    file: file!().to_string(),
57                    line: #line,
58                })
59            },
60        });
61    }
62
63    quote! {
64        vec![ #out ]
65    }
66    .into()
67}