1use crate::error::Error;
2use proc_macro2::{Ident, Span};
3use quote::quote;
4use quote::ToTokens;
5use syn::{BinOp, Expr, Lit, Member};
6
7fn 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 _ => {
210 return Err(Error::from(format!(
211 "unsupported token {}",
212 b.op.to_token_stream()
213 )))
214 }
215 }
216 Ok(Expr::Binary(b))
217 }
218 Expr::Unary(mut b) => {
219 b.expr = Box::new(translate(context, *b.expr, ignore)?);
220 if b.op.to_token_stream().to_string().trim() == "-" {
221 return syn::parse_str::<Expr>(&format!(
222 "0i64.op_sub({})",
223 b.expr.to_token_stream().to_string().trim()
224 ))
225 .map_err(|e| Error::from(e));
226 }
227 if b.op.to_token_stream().to_string().trim() == "!" {
228 b.expr = Box::new(
229 syn::parse_str::<Expr>(&format!(
230 "bool::from({})",
231 b.expr.to_token_stream().to_string().trim()
232 ))
233 .map_err(|e| Error::from(e))?,
234 );
235 }
236 Ok(Expr::Unary(b))
237 }
238 Expr::Paren(mut b) => {
240 b.expr = Box::new(translate(context, *b.expr, ignore)?);
241 Ok(Expr::Paren(b))
242 }
243 Expr::Field(mut b) => {
245 b.base = Box::new(translate(context, *b.base, ignore)?);
246 match b.member {
247 Member::Named(named) => {
248 return syn::parse_str::<Expr>(&format!(
249 "(&{}[\"{}\"])",
250 b.base.to_token_stream(),
251 named.to_token_stream()
252 ))
253 .map_err(|e| Error::from(e));
254 }
255 Member::Unnamed(_) => {}
256 }
257 Ok(Expr::Field(b))
258 }
259 Expr::Reference(mut b) => {
260 b.expr = Box::new(translate(context, *b.expr, ignore)?);
261 let result = Expr::Reference(b);
262 Ok(result)
263 }
264 Expr::Index(mut b) => {
265 b.expr = Box::new(translate(context, *b.expr, ignore)?);
266 syn::parse_str::<Expr>(&format!(
267 "&{}[{}]",
268 b.expr.to_token_stream(),
269 b.index.to_token_stream()
270 ))
271 .map_err(|e| Error::from(e))
272 }
273 Expr::Let(_let_expr) => Err(Error::from("unsupported token `let`")),
274 Expr::Lit(b) => {
275 match b.lit {
276 Lit::Str(_) => {}
277 Lit::ByteStr(_) => {}
278 Lit::Byte(_) => {}
279 Lit::Char(_) => {}
280 Lit::Int(i) => {
281 return syn::parse_str::<Expr>(&format!("{}i64", i))
283 .map_err(|e| Error::from(e));
284 }
285 Lit::Float(f) => {
286 return syn::parse_str::<Expr>(&format!("{}f64", f))
288 .map_err(|e| Error::from(e));
289 }
290 Lit::Bool(_) => {}
291 Lit::Verbatim(_) => {}
292 _ => {}
293 }
294 Ok(Expr::Lit(b))
295 }
296 _ => Ok(arg),
297 }
298}
299
300pub fn impl_fn(
302 context: &str,
303 func_name_ident: &str,
304 args: &str,
305 serialize_result: bool,
306 ignore: &[String],
307) -> proc_macro2::TokenStream {
308 let mut string_data = args.to_string();
309 string_data = string_data[1..string_data.len() - 1].to_string();
310 let mut last_char = '_';
312 let mut string_data_new = String::new();
313 for x in string_data.chars() {
314 if x == '\'' && last_char != '\\' {
315 string_data_new.push('\"');
316 } else {
317 string_data_new.push(x);
318 }
319 last_char = x;
320 }
321 string_data = string_data_new;
322 let t = syn::parse_str::<Expr>(&string_data);
323 if t.is_err() {
324 panic!(
325 "[rbatis-codegen]syn::parse_str: {} fail: {}",
326 args,
327 t.err().expect("codegen_func fail").to_string()
328 )
329 }
330 let mut t = t.expect("codegen_func fail");
331 t = translate(context, t, ignore).expect("translate fail");
332 string_data = t.to_token_stream().to_string();
333 let t = syn::parse_str::<Expr>(&string_data);
334 if t.is_err() {
335 panic!(
336 "[rbatis-codegen]syn::parse_str: {} fail: {}",
337 args,
338 t.err().expect("codegen_func fail").to_string()
339 )
340 }
341 let t = t.expect("codegen_func fail");
342 let mut result_impl = quote! { {#t} };
343 if serialize_result {
344 result_impl = quote! {rbs::value({#t}).unwrap_or_default()};
345 }
346 if func_name_ident.is_empty() || func_name_ident.eq("\"\"") {
347 quote! {#result_impl}
348 } else {
349 let func_name_ident = Ident::new(&func_name_ident.to_string(), Span::call_site());
350 quote! {
351 pub fn #func_name_ident(arg:&rbs::Value) -> rbs::Value {
352 use rbatis_codegen::ops::*;
353 #result_impl
354 }
355 }
356 }
357}