Skip to main content

rbatis_codegen/codegen/
func.rs

1use crate::error::Error;
2use proc_macro2::{Ident, Span};
3use quote::quote;
4use quote::ToTokens;
5use syn::{BinOp, Expr, Lit, Member};
6
7///translate like `#{a + b}` Expr to rust code Expr
8pub fn translate(context: &str, arg: Expr, ignore: &[String]) -> Result<Expr, Error> {
9    match arg {
10        Expr::Path(b) => {
11            let token = b.to_token_stream().to_string();
12            if token == "null" {
13                return syn::parse_str::<Expr>("rbs::Value::Null").map_err(|e| Error::from(e));
14            }
15            if token == "sql" {
16                return Ok(Expr::Path(b));
17            }
18            let param = b.to_token_stream().to_string().trim().to_string();
19            let mut fetch_from_arg = true;
20            for x in ignore {
21                if param.eq(x) {
22                    fetch_from_arg = false;
23                }
24            }
25            if fetch_from_arg {
26                syn::parse_str::<Expr>(&format!("&arg[\"{}\"]", param)).map_err(|e| Error::from(e))
27            } else {
28                syn::parse_str::<Expr>(&format!("{}", param)).map_err(|e| Error::from(e))
29            }
30        }
31        Expr::MethodCall(mut b) => {
32            //receiver is named need to convert to arg["xxx"]
33            b.receiver = Box::new(translate(context, *b.receiver, ignore)?);
34            Ok(Expr::MethodCall(b))
35        }
36        Expr::Binary(mut b) => {
37            b.left = Box::new(translate(context, *b.left, ignore)?);
38            b.right = Box::new(translate(context, *b.right, ignore)?);
39            match b.op {
40                BinOp::Add(_) => {
41                    let left_token = b.left.to_token_stream().to_string();
42                    if left_token.trim().ends_with("\"") && left_token.trim().starts_with("\"") {
43                        return syn::parse_str::<Expr>(&format!(
44                            "(String::from({})).op_add({})",
45                            b.left.to_token_stream(),
46                            b.right.to_token_stream()
47                        ))
48                        .map_err(|e| Error::from(e));
49                    } else {
50                        return syn::parse_str::<Expr>(&format!(
51                            "({}).op_add(&{})",
52                            b.left.to_token_stream(),
53                            b.right.to_token_stream()
54                        ))
55                        .map_err(|e| Error::from(e));
56                    }
57                }
58                BinOp::And(_) => {
59                    b.left = Box::new(
60                        syn::parse_str::<Expr>(&format!(
61                            "bool::op_from({})",
62                            b.left.to_token_stream().to_string().trim()
63                        ))
64                        .expect("codegen_func fail"),
65                    );
66                    b.right = Box::new(
67                        syn::parse_str::<Expr>(&format!(
68                            "bool::op_from({})",
69                            b.right.to_token_stream().to_string().trim()
70                        ))
71                        .expect("codegen_func fail"),
72                    );
73                }
74                BinOp::Or(_) => {
75                    b.left = Box::new(
76                        syn::parse_str::<Expr>(&format!(
77                            "bool::op_from({})",
78                            b.left.to_token_stream().to_string().trim()
79                        ))
80                        .expect("codegen_func fail"),
81                    );
82                    b.right = Box::new(
83                        syn::parse_str::<Expr>(&format!(
84                            "bool::op_from({})",
85                            b.right.to_token_stream().to_string().trim()
86                        ))
87                        .expect("codegen_func fail"),
88                    );
89                }
90
91                // The `-` operator (subtraction)
92                BinOp::Sub(_) => {
93                    return syn::parse_str::<Expr>(&format!(
94                        "({}).op_sub(&{})",
95                        b.left.to_token_stream(),
96                        b.right.to_token_stream()
97                    ))
98                    .map_err(|e| Error::from(e));
99                }
100                // The `*` operator (multiplication)
101                BinOp::Mul(_) => {
102                    return syn::parse_str::<Expr>(&format!(
103                        "({}).op_mul(&{})",
104                        b.left.to_token_stream(),
105                        b.right.to_token_stream()
106                    ))
107                    .map_err(|e| Error::from(e));
108                }
109                // The `/` operator (division)
110                BinOp::Div(_) => {
111                    return syn::parse_str::<Expr>(&format!(
112                        "({}).op_div(&{})",
113                        b.left.to_token_stream(),
114                        b.right.to_token_stream()
115                    ))
116                    .map_err(|e| Error::from(e));
117                }
118                // The `%` operator (modulus)
119                BinOp::Rem(_) => {
120                    return syn::parse_str::<Expr>(&format!(
121                        "({}).op_rem(&{})",
122                        b.left.to_token_stream(),
123                        b.right.to_token_stream()
124                    ))
125                    .map_err(|e| Error::from(e));
126                }
127                // The `&` operator (bitwise and)
128                BinOp::BitAnd(_) => {
129                    return syn::parse_str::<Expr>(&format!(
130                        "({}).op_bitand(&{})",
131                        b.left.to_token_stream(),
132                        b.right.to_token_stream()
133                    ))
134                    .map_err(|e| Error::from(e));
135                }
136                // The `|` operator (bitwise or)
137                BinOp::BitOr(_) => {
138                    return syn::parse_str::<Expr>(&format!(
139                        "({}).op_bitor(&{})",
140                        b.left.to_token_stream(),
141                        b.right.to_token_stream()
142                    ))
143                    .map_err(|e| Error::from(e));
144                }
145                // The `==` operator (equality)
146                BinOp::Eq(_) => {
147                    return syn::parse_str::<Expr>(&format!(
148                        "({}).op_eq(&{})",
149                        b.left.to_token_stream(),
150                        b.right.to_token_stream()
151                    ))
152                    .map_err(|e| Error::from(e));
153                }
154                // The `<` operator (less than)
155                BinOp::Lt(_) => {
156                    return syn::parse_str::<Expr>(&format!(
157                        "({}).op_lt(&{})",
158                        b.left.to_token_stream(),
159                        b.right.to_token_stream()
160                    ))
161                    .map_err(|e| Error::from(e));
162                }
163                // The `<=` operator (less than or equal to)
164                BinOp::Le(_) => {
165                    return syn::parse_str::<Expr>(&format!(
166                        "({}).op_le(&{})",
167                        b.left.to_token_stream(),
168                        b.right.to_token_stream()
169                    ))
170                    .map_err(|e| Error::from(e));
171                }
172                // The `!=` operator (not equal to)
173                BinOp::Ne(_) => {
174                    return syn::parse_str::<Expr>(&format!(
175                        "({}).op_ne(&{})",
176                        b.left.to_token_stream(),
177                        b.right.to_token_stream()
178                    ))
179                    .map_err(|e| Error::from(e));
180                }
181                // The `>=` operator (greater than or equal to)
182                BinOp::Ge(_) => {
183                    return syn::parse_str::<Expr>(&format!(
184                        "({}).op_ge(&{})",
185                        b.left.to_token_stream(),
186                        b.right.to_token_stream()
187                    ))
188                    .map_err(|e| Error::from(e));
189                }
190                // The `>` operator (greater than)
191                BinOp::Gt(_) => {
192                    return syn::parse_str::<Expr>(&format!(
193                        "({}).op_gt(&{})",
194                        b.left.to_token_stream(),
195                        b.right.to_token_stream()
196                    ))
197                    .map_err(|e| Error::from(e));
198                }
199                // The `^` operator (bitwise xor)
200                BinOp::BitXor(_) => {
201                    return syn::parse_str::<Expr>(&format!(
202                        "({}).op_bitxor(&{})",
203                        b.left.to_token_stream(),
204                        b.right.to_token_stream()
205                    ))
206                    .map_err(|e| Error::from(e));
207                }
208                // The `<<` operator (shift left)
209                BinOp::Shl(_) => {
210                    return syn::parse_str::<Expr>(&format!(
211                        "({}).op_shl(&{})",
212                        b.left.to_token_stream(),
213                        b.right.to_token_stream()
214                    ))
215                    .map_err(|e| Error::from(e));
216                }
217                // The `>>` operator (shift right)
218                BinOp::Shr(_) => {
219                    return syn::parse_str::<Expr>(&format!(
220                        "({}).op_shr(&{})",
221                        b.left.to_token_stream(),
222                        b.right.to_token_stream()
223                    ))
224                    .map_err(|e| Error::from(e));
225                }
226                // Unknown operator
227                _ => {
228                    return Err(Error::from(format!(
229                        "unsupported token {}",
230                        b.op.to_token_stream()
231                    )))
232                }
233            }
234            Ok(Expr::Binary(b))
235        }
236        Expr::Unary(mut b) => {
237            b.expr = Box::new(translate(context, *b.expr, ignore)?);
238            if b.op.to_token_stream().to_string().trim() == "-" {
239                return syn::parse_str::<Expr>(&format!(
240                    "0i64.op_sub({})",
241                    b.expr.to_token_stream().to_string().trim()
242                ))
243                .map_err(|e| Error::from(e));
244            }
245            if b.op.to_token_stream().to_string().trim() == "!" {
246                b.expr = Box::new(
247                    syn::parse_str::<Expr>(&format!(
248                        "bool::from({})",
249                        b.expr.to_token_stream().to_string().trim()
250                    ))
251                    .map_err(|e| Error::from(e))?,
252                );
253            }
254            Ok(Expr::Unary(b))
255        }
256        //(a-b)
257        Expr::Paren(mut b) => {
258            b.expr = Box::new(translate(context, *b.expr, ignore)?);
259            Ok(Expr::Paren(b))
260        }
261        //a.b
262        Expr::Field(mut b) => {
263            b.base = Box::new(translate(context, *b.base, ignore)?);
264            match b.member {
265                Member::Named(named) => {
266                    return syn::parse_str::<Expr>(&format!(
267                        "(&{}[\"{}\"])",
268                        b.base.to_token_stream(),
269                        named.to_token_stream()
270                    ))
271                    .map_err(|e| Error::from(e));
272                }
273                Member::Unnamed(_) => {}
274            }
275            Ok(Expr::Field(b))
276        }
277        Expr::Reference(mut b) => {
278            b.expr = Box::new(translate(context, *b.expr, ignore)?);
279            let result = Expr::Reference(b);
280            Ok(result)
281        }
282        Expr::Index(mut b) => {
283            b.expr = Box::new(translate(context, *b.expr, ignore)?);
284            syn::parse_str::<Expr>(&format!(
285                "&{}[{}]",
286                b.expr.to_token_stream(),
287                b.index.to_token_stream()
288            ))
289            .map_err(|e| Error::from(e))
290        }
291        Expr::Let(_let_expr) => Err(Error::from("unsupported token `let`")),
292        Expr::Lit(b) => {
293            match b.lit {
294                Lit::Str(_) => {}
295                Lit::ByteStr(_) => {}
296                Lit::Byte(_) => {}
297                Lit::Char(_) => {}
298                Lit::Int(i) => {
299                    //cast int to i64
300                    return syn::parse_str::<Expr>(&format!("{}i64", i))
301                        .map_err(|e| Error::from(e));
302                }
303                Lit::Float(f) => {
304                    //cast int to f64
305                    return syn::parse_str::<Expr>(&format!("{}f64", f))
306                        .map_err(|e| Error::from(e));
307                }
308                Lit::Bool(_) => {}
309                Lit::Verbatim(_) => {}
310                _ => {}
311            }
312            Ok(Expr::Lit(b))
313        }
314        _ => Ok(arg),
315    }
316}
317
318/// gen method or body(if func_name_ident is empty)
319pub fn impl_fn(
320    context: &str,
321    func_name_ident: &str,
322    args: &str,
323    serialize_result: bool,
324    ignore: &[String],
325) -> proc_macro2::TokenStream {
326    let mut string_data = args.to_string();
327    string_data = string_data[1..string_data.len() - 1].to_string();
328    //convert string define
329    let mut last_char = '_';
330    let mut string_data_new = String::new();
331    for x in string_data.chars() {
332        if x == '\'' && last_char != '\\' {
333            string_data_new.push('\"');
334        } else {
335            string_data_new.push(x);
336        }
337        last_char = x;
338    }
339    string_data = string_data_new;
340    let t = syn::parse_str::<Expr>(&string_data);
341    if t.is_err() {
342        panic!(
343            "[rbatis-codegen]syn::parse_str: {} fail: {}",
344            args,
345            t.err().expect("codegen_func fail").to_string()
346        )
347    }
348    let mut t = t.expect("codegen_func fail");
349    t = translate(context, t, ignore).expect("translate fail");
350    string_data = t.to_token_stream().to_string();
351    let t = syn::parse_str::<Expr>(&string_data);
352    if t.is_err() {
353        panic!(
354            "[rbatis-codegen]syn::parse_str: {} fail: {}",
355            args,
356            t.err().expect("codegen_func fail").to_string()
357        )
358    }
359    let t = t.expect("codegen_func fail");
360    let mut result_impl = quote! { {#t} };
361    if serialize_result {
362        result_impl = quote! {rbs::value({#t}).unwrap_or_default()};
363    }
364    if func_name_ident.is_empty() || func_name_ident.eq("\"\"") {
365        quote! {#result_impl}
366    } else {
367        let func_name_ident = Ident::new(&func_name_ident.to_string(), Span::call_site());
368        quote! {
369            pub fn #func_name_ident(arg:&rbs::Value) -> rbs::Value {
370               use rbatis_codegen::ops::*;
371               #result_impl
372            }
373        }
374    }
375}