Skip to main content

xwrapup_macros/
lib.rs

1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use syn::parse_macro_input;
5
6use xwrapup_parser::ds_node::DsRoot;
7use xwrapup_parser::ds_rune::decipher::decipher;
8use xwrapup_parser::ds_rune::DsRune;
9
10/// Default rune: generates println debug output (xwrapup style).
11struct DefaultRune {
12    tokens: proc_macro2::TokenStream,
13    parent_name: String,
14}
15
16impl DefaultRune {
17    fn new() -> Self {
18        Self {
19            tokens: proc_macro2::TokenStream::new(),
20            parent_name: String::new(),
21        }
22    }
23}
24
25impl DsRune for DefaultRune {
26    fn inscribe_root(&mut self, parent_expr: &syn::Expr) {
27        use quote::quote;
28        self.tokens.extend(quote! {
29            println!("let parent = {:?}", #parent_expr);
30        });
31        self.parent_name = "parent".to_string();
32    }
33
34    fn inscribe_widget(
35        &mut self,
36        name: &syn::Ident,
37        attrs: &[xwrapup_parser::ds_node::ds_attr::DsAttr],
38        children: &[xwrapup_parser::ds_node::DsTreeRef],
39    ) {
40        use quote::quote;
41        let name_string = name.to_string();
42        let parent_name = &self.parent_name;
43
44        self.tokens.extend(quote! {
45            println!("let {} = obj::new({})", #name_string, #parent_name);
46        });
47
48        for attr in attrs {
49            let attr_name = attr.name.to_string();
50            let attr_value = &attr.value;
51            self.tokens.extend(quote! {
52                println!("{}.set_{}({:?})", #name_string, #attr_name, #attr_value);
53            });
54        }
55
56        let prev_parent = self.parent_name.clone();
57        self.parent_name = name_string;
58        for child in children {
59            decipher(child, self);
60        }
61        self.parent_name = prev_parent;
62    }
63
64    fn inscribe_if(
65        &mut self,
66        condition: &syn::Expr,
67        children: &[xwrapup_parser::ds_node::DsTreeRef],
68    ) {
69        use quote::quote;
70        let con = quote!(#condition).to_string();
71        self.tokens.extend(quote! {
72            println!("if {} {{", #con);
73        });
74        for child in children {
75            decipher(child, self);
76        }
77        self.tokens.extend(quote! {
78            println!("}}");
79        });
80    }
81
82    fn inscribe_iter(
83        &mut self,
84        iterable: &syn::Expr,
85        variable: &syn::Ident,
86        children: &[xwrapup_parser::ds_node::DsTreeRef],
87    ) {
88        use quote::quote;
89        let iterable_str = quote!(#iterable).to_string();
90        let variable_str = variable.to_string();
91        self.tokens.extend(quote! {
92            println!("for {} in {} {{", #variable_str, #iterable_str);
93        });
94        for child in children {
95            decipher(child, self);
96        }
97        self.tokens.extend(quote! {
98            println!("}}");
99        });
100    }
101
102    fn seal(self) -> proc_macro2::TokenStream {
103        self.tokens
104    }
105}
106
107#[proc_macro]
108pub fn ui(input: TokenStream) -> TokenStream {
109    let root = parse_macro_input!(input as DsRoot);
110
111    let mut rune = DefaultRune::new();
112
113    // Inscribe root
114    rune.inscribe_root(&root.get_parent());
115
116    // Traverse the content tree
117    let content = root.get_content();
118    decipher(&content, &mut rune);
119
120    TokenStream::from(rune.seal())
121}