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}