1extern crate proc_macro;
2
3use self::proc_macro::{TokenStream as TokenStream1, TokenTree};
4use proc_macro2::TokenStream;
5use proc_macro_error::proc_macro_error;
6use quote::quote;
7
8mod chains;
9mod check;
10mod file;
11mod patterns;
12mod script;
13mod token;
14
15use crate::{
16 chains::ChainIter,
17 check::Checker,
18 patterns::{all, caps},
19 script::Script,
20};
21
22use proc_macro_hack::proc_macro_hack;
23
24fn to_ident(tt: &TokenTree) -> TokenStream {
25 let s: TokenStream1 = tt.clone().into();
26 s.into()
27}
28
29fn gen_all(script: &Script) -> TokenStream {
30 let mut s = TokenStream::new();
31
32 let chains = ChainIter::new(script);
33 let pchains = chains.pchains();
34
35 for c in chains {
36 s.extend(c.gen());
37 }
38
39 for c in pchains {
40 s.extend(c.gen());
41 }
42
43 s
44}
45
46#[proc_macro_error]
47#[proc_macro_hack]
48pub fn lua(input: TokenStream1) -> TokenStream1 {
49 let script = Script::new(input, true);
50
51 Checker::new()
52 .defines(all(&script).map(|(_, arg)| arg.as_lua().into()).collect())
53 .check(&script);
54
55 let defs = gen_all(&script);
56
57 let body_str = script.script();
58 let script_str = script.wrap();
59
60 let args = all(&script).map(|(_, arg)| {
61 let arg = arg.as_lua().to_string();
62 quote! { #arg }
63 });
64
65 let caps = caps(&script).map(|(_, arg)| {
66 let arg = to_ident(arg.as_rust());
67 quote! { #arg }
68 });
69
70 let script_code = quote! {
71 {
72 use redis_lua::Script;
73
74 #defs
75
76 Chain0::new(redis_lua::Info::new(#script_str, #body_str, &[#(#args),*]), (), #(#caps),*)
77 }
78 };
79 script_code.into()
80}
81
82#[proc_macro_error]
83#[proc_macro_hack]
84pub fn lua_s(input: TokenStream1) -> TokenStream1 {
85 let script = Script::new(input, false);
86
87 Checker::new().define("ARGV").check(&script);
88
89 let script = script.script();
90 let script_code = quote! {
91 #script
92 };
93 script_code.into()
94}