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