1use crate::error::Error;
2use proc_macro2::{Ident, Span};
3use quote::quote;
4use quote::ToTokens;
5use syn::{BinOp, Expr, Lit, Member};
6
7pub 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 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 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 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 _ => {
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 Expr::Paren(mut b) => {
258 b.expr = Box::new(translate(context, *b.expr, ignore)?);
259 Ok(Expr::Paren(b))
260 }
261 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 return syn::parse_str::<Expr>(&format!("{}i64", i))
301 .map_err(|e| Error::from(e));
302 }
303 Lit::Float(f) => {
304 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
318pub 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 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}