python_ast/ast/tree/
expression.rs

1use proc_macro2::TokenStream;
2use pyo3::{Bound, FromPyObject, PyAny, PyResult, prelude::PyAnyMethods, types::PyTypeMethods};
3use quote::quote;
4use serde::{Deserialize, Serialize};
5
6use crate::{
7    dump, Attribute, Await, BinOp, BoolOp, Call, CodeGen, CodeGenContext, Compare, Constant, Error,
8    Name, NamedExpr, Node, PythonOptions, SymbolTableScopes, UnaryOp, Lambda, IfExp, Dict, Set, Tuple, Subscript, Starred, ListComp, DictComp, SetComp, GeneratorExp, Yield, YieldFrom, JoinedStr, FormattedValue,
9};
10
11/// Mostly this shouldn't be used, but it exists so that we don't have to manually implement FromPyObject on all of ExprType
12#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
13#[repr(transparent)]
14pub struct Container<T>(pub T);
15
16impl<'a> FromPyObject<'a> for Container<crate::pytypes::List<ExprType>> {
17    fn extract_bound(ob: &Bound<'a, PyAny>) -> PyResult<Self> {
18        let list = crate::pytypes::List::<ExprType>::new();
19
20        log::debug!("pylist: {}", dump(ob, Some(4))?);
21        let _converted_list: Vec<Bound<PyAny>> = ob.extract()?;
22        for item in _converted_list.iter() {
23            log::debug!("item: {:?}", item);
24        }
25
26        Ok(Self(list))
27    }
28}
29
30#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
31pub enum ExprType {
32    BoolOp(BoolOp),
33    NamedExpr(NamedExpr),
34    BinOp(BinOp),
35    UnaryOp(UnaryOp),
36    Lambda(Lambda),
37    IfExp(IfExp),
38    Dict(Dict),
39    Set(Set),
40    ListComp(ListComp),
41    DictComp(DictComp),
42    SetComp(SetComp),
43    GeneratorExp(GeneratorExp),
44    Await(Await),
45    Yield(Yield),
46    YieldFrom(YieldFrom),
47    Compare(Compare),
48    Call(Call),
49    FormattedValue(FormattedValue),
50    JoinedStr(JoinedStr),
51    Constant(Constant),
52
53    /// These can appear in a few places, such as the left side of an assignment.
54    Attribute(Attribute),
55    Subscript(Subscript),
56    Starred(Starred),
57    Name(Name),
58    List(Vec<ExprType>),
59    Tuple(Tuple),
60    /*Slice(),*/
61    NoneType(Constant),
62
63    Unimplemented(String),
64    #[default]
65    Unknown,
66}
67
68impl<'a> FromPyObject<'a> for ExprType {
69    fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<Self> {
70        log::debug!("exprtype ob: {}", dump(ob, Some(4))?);
71
72        let expr_type = ob.get_type().name().expect(
73            ob.error_message(
74                "<unknown>",
75                format!("extracting type name {:?} in expression", dump(ob, None)),
76            )
77            .as_str(),
78        );
79        log::debug!("expression type: {}, value: {}", expr_type, dump(ob, None)?);
80
81        let r = match expr_type.extract::<String>()?.as_str() {
82            "Attribute" => {
83                let a = ob.extract().expect(
84                    ob.error_message(
85                        "<unknown>",
86                        format!("extracting Attribute in expression {}", dump(ob, None)?),
87                    )
88                    .as_str(),
89                );
90                Ok(Self::Attribute(a))
91            }
92            "Await" => {
93                //println!("await: {}", dump(ob, None)?);
94                let a = ob.extract().expect(
95                    ob.error_message(
96                        "<unknown>",
97                        format!("extracting await value in expression {}", dump(ob, None)?),
98                    )
99                    .as_str(),
100                );
101                Ok(Self::Await(a))
102            }
103            "BoolOp" => {
104                let b = ob.extract().expect(
105                    ob.error_message(
106                        "<unknown>",
107                        format!("extracting BoolOp in expression {}", dump(ob, None)?),
108                    )
109                    .as_str(),
110                );
111                Ok(Self::BoolOp(b))
112            }
113            "Call" => {
114                let et = ob.extract().expect(
115                    ob.error_message(
116                        "<unknown>",
117                        format!("parsing Call expression {}", dump(ob, None)?),
118                    )
119                    .as_str(),
120                );
121                Ok(Self::Call(et))
122            }
123            "Compare" => {
124                let c = ob.extract().expect(
125                    ob.error_message(
126                        "<unknown>",
127                        format!("extracting Compare in expression {}", dump(ob, None)?),
128                    )
129                    .as_str(),
130                );
131                Ok(Self::Compare(c))
132            }
133            "Constant" => {
134                log::debug!("constant: {}", dump(ob, None)?);
135                let c = ob.extract().expect(
136                    ob.error_message(
137                        "<unknown>",
138                        format!("extracting Constant in expression {}", dump(ob, None)?),
139                    )
140                    .as_str(),
141                );
142                Ok(Self::Constant(c))
143            }
144            "List" => {
145                // Extract the list elements using the 'elts' attribute
146                let elts_attr = ob.getattr("elts")
147                    .expect(format!("getting elts attribute from List {}", dump(ob, None)?).as_str());
148                let elts_vec: Vec<Bound<PyAny>> = elts_attr.extract()
149                    .expect(format!("extracting elts as Vec<Bound<PyAny>> from List {}", dump(ob, None)?).as_str());
150                
151                // Convert each element to ExprType
152                let mut expr_list = Vec::new();
153                for elt in elts_vec {
154                    let expr: ExprType = elt.extract()
155                        .expect(format!("extracting list element {}", dump(&elt, None)?).as_str());
156                    expr_list.push(expr);
157                }
158                
159                Ok(Self::List(expr_list))
160            }
161            "ListComp" => {
162                let lc = ob.extract().expect(
163                    ob.error_message(
164                        "<unknown>",
165                        format!("extracting ListComp in expression {}", dump(ob, None)?),
166                    )
167                    .as_str(),
168                );
169                Ok(Self::ListComp(lc))
170            }
171            "DictComp" => {
172                let dc = ob.extract().expect(
173                    ob.error_message(
174                        "<unknown>",
175                        format!("extracting DictComp in expression {}", dump(ob, None)?),
176                    )
177                    .as_str(),
178                );
179                Ok(Self::DictComp(dc))
180            }
181            "SetComp" => {
182                let sc = ob.extract().expect(
183                    ob.error_message(
184                        "<unknown>",
185                        format!("extracting SetComp in expression {}", dump(ob, None)?),
186                    )
187                    .as_str(),
188                );
189                Ok(Self::SetComp(sc))
190            }
191            "GeneratorExp" => {
192                let ge = ob.extract().expect(
193                    ob.error_message(
194                        "<unknown>",
195                        format!("extracting GeneratorExp in expression {}", dump(ob, None)?),
196                    )
197                    .as_str(),
198                );
199                Ok(Self::GeneratorExp(ge))
200            }
201            "Name" => {
202                let name = ob.extract().expect(
203                    ob.error_message(
204                        "<unknown>",
205                        format!("parsing Name expression {}", dump(ob, None)?),
206                    )
207                    .as_str(),
208                );
209                Ok(Self::Name(name))
210            }
211            "UnaryOp" => {
212                let c = ob.extract().expect(
213                    ob.error_message(
214                        "<unknown>",
215                        format!("extracting UnaryOp in expression {}", dump(ob, None)?),
216                    )
217                    .as_str(),
218                );
219                Ok(Self::UnaryOp(c))
220            }
221            "BinOp" => {
222                let c = ob.extract().expect(
223                    ob.error_message(
224                        "<unknown>",
225                        format!("extracting BinOp in expression {}", dump(ob, None)?),
226                    )
227                    .as_str(),
228                );
229                Ok(Self::BinOp(c))
230            }
231            "Lambda" => {
232                let l = ob.extract().expect(
233                    ob.error_message(
234                        "<unknown>",
235                        format!("extracting Lambda in expression {}", dump(ob, None)?),
236                    )
237                    .as_str(),
238                );
239                Ok(Self::Lambda(l))
240            }
241            "IfExp" => {
242                let i = ob.extract().expect(
243                    ob.error_message(
244                        "<unknown>",
245                        format!("extracting IfExp in expression {}", dump(ob, None)?),
246                    )
247                    .as_str(),
248                );
249                Ok(Self::IfExp(i))
250            }
251            "Dict" => {
252                let d = ob.extract().expect(
253                    ob.error_message(
254                        "<unknown>",
255                        format!("extracting Dict in expression {}", dump(ob, None)?),
256                    )
257                    .as_str(),
258                );
259                Ok(Self::Dict(d))
260            }
261            "Set" => {
262                let s = ob.extract().expect(
263                    ob.error_message(
264                        "<unknown>",
265                        format!("extracting Set in expression {}", dump(ob, None)?),
266                    )
267                    .as_str(),
268                );
269                Ok(Self::Set(s))
270            }
271            "Tuple" => {
272                let t = ob.extract().expect(
273                    ob.error_message(
274                        "<unknown>",
275                        format!("extracting Tuple in expression {}", dump(ob, None)?),
276                    )
277                    .as_str(),
278                );
279                Ok(Self::Tuple(t))
280            }
281            "Subscript" => {
282                let s = ob.extract().expect(
283                    ob.error_message(
284                        "<unknown>",
285                        format!("extracting Subscript in expression {}", dump(ob, None)?),
286                    )
287                    .as_str(),
288                );
289                Ok(Self::Subscript(s))
290            }
291            "Starred" => {
292                let s = ob.extract().expect(
293                    ob.error_message(
294                        "<unknown>",
295                        format!("extracting Starred in expression {}", dump(ob, None)?),
296                    )
297                    .as_str(),
298                );
299                Ok(Self::Starred(s))
300            }
301            "Yield" => {
302                let y = ob.extract().expect(
303                    ob.error_message(
304                        "<unknown>",
305                        format!("extracting Yield in expression {}", dump(ob, None)?),
306                    )
307                    .as_str(),
308                );
309                Ok(Self::Yield(y))
310            }
311            "YieldFrom" => {
312                let yf = ob.extract().expect(
313                    ob.error_message(
314                        "<unknown>",
315                        format!("extracting YieldFrom in expression {}", dump(ob, None)?),
316                    )
317                    .as_str(),
318                );
319                Ok(Self::YieldFrom(yf))
320            }
321            "JoinedStr" => {
322                let js = ob.extract().expect(
323                    ob.error_message(
324                        "<unknown>",
325                        format!("extracting JoinedStr in expression {}", dump(ob, None)?),
326                    )
327                    .as_str(),
328                );
329                Ok(Self::JoinedStr(js))
330            }
331            "FormattedValue" => {
332                let fv = ob.extract().expect(
333                    ob.error_message(
334                        "<unknown>",
335                        format!("extracting FormattedValue in expression {}", dump(ob, None)?),
336                    )
337                    .as_str(),
338                );
339                Ok(Self::FormattedValue(fv))
340            }
341            _ => {
342                let err_msg = format!(
343                    "Unimplemented expression type {}, {}",
344                    expr_type,
345                    dump(ob, None)?
346                );
347                Err(pyo3::exceptions::PyValueError::new_err(
348                    ob.error_message("<unknown>", err_msg.as_str()),
349                ))
350            }
351        };
352        r
353    }
354}
355
356impl<'a> CodeGen for ExprType {
357    type Context = CodeGenContext;
358    type Options = PythonOptions;
359    type SymbolTable = SymbolTableScopes;
360
361    fn to_rust(
362        self,
363        ctx: Self::Context,
364        options: Self::Options,
365        symbols: Self::SymbolTable,
366    ) -> std::result::Result<TokenStream, Box<dyn std::error::Error>> {
367        match self {
368            ExprType::Attribute(attribute) => attribute.to_rust(ctx, options, symbols),
369            ExprType::Await(func) => func.to_rust(ctx, options, symbols),
370            ExprType::BinOp(binop) => binop.to_rust(ctx, options, symbols),
371            ExprType::BoolOp(boolop) => boolop.to_rust(ctx, options, symbols),
372            ExprType::Call(call) => call.to_rust(ctx, options, symbols),
373            ExprType::Compare(c) => c.to_rust(ctx, options, symbols),
374            ExprType::Constant(c) => c.to_rust(ctx, options, symbols),
375            ExprType::Lambda(l) => l.to_rust(ctx, options, symbols),
376            ExprType::IfExp(i) => i.to_rust(ctx, options, symbols),
377            ExprType::Dict(d) => d.to_rust(ctx, options, symbols),
378            ExprType::Set(s) => s.to_rust(ctx, options, symbols),
379            ExprType::ListComp(lc) => lc.to_rust(ctx, options, symbols),
380            ExprType::DictComp(dc) => dc.to_rust(ctx, options, symbols),
381            ExprType::SetComp(sc) => sc.to_rust(ctx, options, symbols),
382            ExprType::GeneratorExp(ge) => ge.to_rust(ctx, options, symbols),
383            ExprType::Tuple(t) => t.to_rust(ctx, options, symbols),
384            ExprType::Subscript(s) => s.to_rust(ctx, options, symbols),
385            ExprType::Starred(s) => s.to_rust(ctx, options, symbols),
386            ExprType::Yield(y) => y.to_rust(ctx, options, symbols),
387            ExprType::YieldFrom(yf) => yf.to_rust(ctx, options, symbols),
388            ExprType::JoinedStr(js) => js.to_rust(ctx, options, symbols),
389            ExprType::FormattedValue(fv) => fv.to_rust(ctx, options, symbols),
390            ExprType::List(l) => {
391                let mut elements = Vec::new();
392                let mut has_starred = false;
393                
394                for li in l {
395                    let code = li
396                        .clone()
397                        .to_rust(ctx.clone(), options.clone(), symbols.clone())
398                        .expect(format!("Extracting list item {:?}", li).as_str());
399                    
400                    // Check if this is a starred expression
401                    if matches!(li, ExprType::Starred(_)) {
402                        has_starred = true;
403                        let code_str = code.to_string();
404                        // Special handling for sys::argv unpacking
405                        if code_str.contains("sys :: argv") {
406                            // Mark that we need special sys::argv handling with a unique marker
407                            elements.push(quote! { __STARRED_ARGV_MARKER__ });
408                        } else {
409                            elements.push(code);
410                        }
411                    } else {
412                        elements.push(code);
413                    }
414                }
415                
416                // If we have starred expressions, handle them specially
417                if has_starred {
418                    let mut final_elements = Vec::new();
419                    let mut has_argv_starred = false;
420                    
421                    for element in elements {
422                        let elem_str = element.to_string();
423                        if elem_str.contains("__STARRED_ARGV_MARKER__") {
424                            has_argv_starred = true;
425                            continue; // Skip the placeholder
426                        } else {
427                            final_elements.push(element);
428                        }
429                    }
430                    
431                    // Build the vector with proper unpacking
432                    if has_argv_starred {
433                        if final_elements.is_empty() {
434                            // Only sys::argv unpacking
435                            Ok(quote! {
436                                (*sys::argv).clone()
437                            })
438                        } else {
439                            // Mix of regular elements and sys::argv unpacking
440                            // Clone each element to avoid ownership issues
441                            Ok(quote! {
442                                {
443                                    let mut vec = Vec::new();
444                                    #(vec.push((#final_elements).clone().to_string());)*
445                                    vec.extend((*sys::argv).iter().cloned());
446                                    vec
447                                }
448                            })
449                        }
450                    } else {
451                        // Other starred expressions (not sys::argv)
452                        Ok(quote! {
453                            vec![#(#final_elements.to_string()),*]
454                        })
455                    }
456                } else {
457                    // For regular vector creation, ensure all elements are strings
458                    // Always convert to String for consistency and compatibility
459                    // Clone to avoid ownership issues
460                    Ok(quote! {
461                        vec![#((#elements).clone().to_string()),*]
462                    })
463                }
464            }
465            ExprType::Name(name) => name.to_rust(ctx, options, symbols),
466            ExprType::NoneType(c) => c.to_rust(ctx, options, symbols),
467            ExprType::UnaryOp(operand) => operand.to_rust(ctx, options, symbols),
468
469            _ => {
470                let error = Error::ExprTypeNotYetImplemented(self);
471                Err(error.into())
472            }
473        }
474    }
475}
476
477/// An Expr only contains a single value key, which leads to the actual expression,
478/// which is one of several types.
479#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
480pub struct Expr {
481    pub value: ExprType,
482    pub ctx: Option<String>,
483    pub lineno: Option<usize>,
484    pub col_offset: Option<usize>,
485    pub end_lineno: Option<usize>,
486    pub end_col_offset: Option<usize>,
487}
488
489impl<'a> FromPyObject<'a> for Expr {
490    fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<Self> {
491        let err_msg = format!("extracting object value {} in expression", dump(ob, None)?);
492
493        let ob_value = ob
494            .getattr("value")
495            .expect(ob.error_message("<unknown>", err_msg.as_str()).as_str());
496        log::debug!("ob_value: {}", dump(&ob_value, None)?);
497
498        // The context is Load, Store, etc. For some types of expressions such as Constants, it does not exist.
499        let ctx: Option<String> = if let Ok(pyany) = ob_value.getattr("ctx") {
500            pyany.get_type().extract().unwrap_or_default()
501        } else {
502            None
503        };
504
505        let mut r = Self {
506            value: ExprType::Unknown,
507            ctx: ctx,
508            lineno: ob.lineno(),
509            col_offset: ob.col_offset(),
510            end_lineno: ob.end_lineno(),
511            end_col_offset: ob.end_col_offset(),
512        };
513
514        let expr_type = ob_value.get_type().name().expect(
515            ob.error_message(
516                "<unknown>",
517                format!("extracting type name {:?} in expression", ob_value),
518            )
519            .as_str(),
520        );
521        log::debug!(
522            "expression type: {}, value: {}",
523            expr_type,
524            dump(&ob_value, None)?
525        );
526        match expr_type.extract::<String>()?.as_str() {
527            "Atribute" => {
528                let a = ob_value.extract().expect(
529                    ob.error_message(
530                        "<unknown>",
531                        format!("extracting BinOp in expression {:?}", dump(&ob_value, None)?),
532                    )
533                    .as_str(),
534                );
535                r.value = ExprType::Attribute(a);
536                Ok(r)
537            }
538            "Await" => {
539                let a = ob_value.extract().expect(
540                    ob.error_message(
541                        "<unknown>",
542                        format!("extracting BinOp in expression {:?}", dump(&ob_value, None)?),
543                    )
544                    .as_str(),
545                );
546                r.value = ExprType::Await(a);
547                Ok(r)
548            }
549            "BinOp" => {
550                let c = ob_value.extract().expect(
551                    ob.error_message(
552                        "<unknown>",
553                        format!("extracting BinOp in expression {:?}", dump(&ob_value, None)?),
554                    )
555                    .as_str(),
556                );
557                r.value = ExprType::BinOp(c);
558                Ok(r)
559            }
560            "BoolOp" => {
561                let c = ob_value.extract().expect(
562                    ob.error_message(
563                        "<unknown>",
564                        format!("extracting BinOp in expression {:?}", dump(&ob_value, None)?),
565                    )
566                    .as_str(),
567                );
568                r.value = ExprType::BoolOp(c);
569                Ok(r)
570            }
571            "Call" => {
572                let et = ob_value.extract().expect(
573                    ob.error_message(
574                        "<unknown>",
575                        format!("parsing Call expression {:?}", ob_value),
576                    )
577                    .as_str(),
578                );
579                r.value = ExprType::Call(et);
580                Ok(r)
581            }
582            "Constant" => {
583                let c = ob_value.extract().expect(
584                    ob.error_message(
585                        "<unknown>",
586                        format!(
587                            "extracting Constant in expression {:?}",
588                            dump(&ob_value, None)?
589                        ),
590                    )
591                    .as_str(),
592                );
593                r.value = ExprType::Constant(c);
594                Ok(r)
595            }
596            "Compare" => {
597                let c = ob_value.extract().expect(
598                    ob.error_message(
599                        "<unknown>",
600                        format!(
601                            "extracting Compare in expression {:?}",
602                            dump(&ob_value, None)?
603                        ),
604                    )
605                    .as_str(),
606                );
607                r.value = ExprType::Compare(c);
608                Ok(r)
609            }
610            "List" => {
611                // Extract the list elements using the 'elts' attribute
612                let elts_attr = ob_value.getattr("elts")
613                    .expect("getting elts attribute from List");
614                let elts_vec: Vec<Bound<PyAny>> = elts_attr.extract()
615                    .expect("extracting elts as Vec<Bound<PyAny>> from List");
616                
617                // Convert each element to ExprType
618                let mut expr_list = Vec::new();
619                for elt in elts_vec {
620                    let expr: ExprType = elt.extract()
621                        .expect(&format!("extracting list element {}", dump(&elt, None).unwrap_or_else(|_| "unknown".to_string())));
622                    expr_list.push(expr);
623                }
624                
625                r.value = ExprType::List(expr_list);
626                Ok(r)
627            }
628            "Name" => {
629                let name = ob_value.extract().expect(
630                    ob.error_message(
631                        "<unknown>",
632                        format!("parsing Call expression {:?}", ob_value),
633                    )
634                    .as_str(),
635                );
636                r.value = ExprType::Name(name);
637                Ok(r)
638            }
639            "UnaryOp" => {
640                let c = ob_value.extract().expect(
641                    ob.error_message(
642                        "<unknown>",
643                        format!(
644                            "extracting UnaryOp in expression {:?}",
645                            dump(&ob_value, None)?
646                        ),
647                    )
648                    .as_str(),
649                );
650                r.value = ExprType::UnaryOp(c);
651                Ok(r)
652            }
653            "Lambda" => {
654                let l = ob_value.extract().expect(
655                    ob.error_message(
656                        "<unknown>",
657                        format!(
658                            "extracting Lambda in expression {:?}",
659                            dump(&ob_value, None)?
660                        ),
661                    )
662                    .as_str(),
663                );
664                r.value = ExprType::Lambda(l);
665                Ok(r)
666            }
667            "IfExp" => {
668                let i = ob_value.extract().expect(
669                    ob.error_message(
670                        "<unknown>",
671                        format!(
672                            "extracting IfExp in expression {:?}",
673                            dump(&ob_value, None)?
674                        ),
675                    )
676                    .as_str(),
677                );
678                r.value = ExprType::IfExp(i);
679                Ok(r)
680            }
681            "Dict" => {
682                let d = ob_value.extract().expect(
683                    ob.error_message(
684                        "<unknown>",
685                        format!(
686                            "extracting Dict in expression {:?}",
687                            dump(&ob_value, None)?
688                        ),
689                    )
690                    .as_str(),
691                );
692                r.value = ExprType::Dict(d);
693                Ok(r)
694            }
695            "Set" => {
696                let s = ob_value.extract().expect(
697                    ob.error_message(
698                        "<unknown>",
699                        format!(
700                            "extracting Set in expression {:?}",
701                            dump(&ob_value, None)?
702                        ),
703                    )
704                    .as_str(),
705                );
706                r.value = ExprType::Set(s);
707                Ok(r)
708            }
709            "Tuple" => {
710                let t = ob_value.extract().expect(
711                    ob.error_message(
712                        "<unknown>",
713                        format!(
714                            "extracting Tuple in expression {:?}",
715                            dump(&ob_value, None)?
716                        ),
717                    )
718                    .as_str(),
719                );
720                r.value = ExprType::Tuple(t);
721                Ok(r)
722            }
723            "Subscript" => {
724                let s = ob_value.extract().expect(
725                    ob.error_message(
726                        "<unknown>",
727                        format!(
728                            "extracting Subscript in expression {:?}",
729                            dump(&ob_value, None)?
730                        ),
731                    )
732                    .as_str(),
733                );
734                r.value = ExprType::Subscript(s);
735                Ok(r)
736            }
737            "Yield" => {
738                let y = ob_value.extract().expect(
739                    ob.error_message(
740                        "<unknown>",
741                        format!(
742                            "extracting Yield in expression {:?}",
743                            dump(&ob_value, None)?
744                        ),
745                    )
746                    .as_str(),
747                );
748                r.value = ExprType::Yield(y);
749                Ok(r)
750            }
751            "YieldFrom" => {
752                let yf = ob_value.extract().expect(
753                    ob.error_message(
754                        "<unknown>",
755                        format!(
756                            "extracting YieldFrom in expression {:?}",
757                            dump(&ob_value, None)?
758                        ),
759                    )
760                    .as_str(),
761                );
762                r.value = ExprType::YieldFrom(yf);
763                Ok(r)
764            }
765            "JoinedStr" => {
766                let js = ob_value.extract().expect(
767                    ob.error_message(
768                        "<unknown>",
769                        format!(
770                            "extracting JoinedStr in expression {:?}",
771                            dump(&ob_value, None)?
772                        ),
773                    )
774                    .as_str(),
775                );
776                r.value = ExprType::JoinedStr(js);
777                Ok(r)
778            }
779            "FormattedValue" => {
780                let fv = ob_value.extract().expect(
781                    ob.error_message(
782                        "<unknown>",
783                        format!(
784                            "extracting FormattedValue in expression {:?}",
785                            dump(&ob_value, None)?
786                        ),
787                    )
788                    .as_str(),
789                );
790                r.value = ExprType::FormattedValue(fv);
791                Ok(r)
792            }
793            "GeneratorExp" => {
794                let ge = ob_value.extract().expect(
795                    ob.error_message(
796                        "<unknown>",
797                        format!(
798                            "extracting GeneratorExp in expression {:?}",
799                            dump(&ob_value, None)?
800                        ),
801                    )
802                    .as_str(),
803                );
804                r.value = ExprType::GeneratorExp(ge);
805                Ok(r)
806            }
807            // In sitations where an expression is optional, we may see a NoneType expressions.
808            "NoneType" => {
809                r.value = ExprType::NoneType(Constant(None));
810                Ok(r)
811            }
812            _ => {
813                let err_msg = format!(
814                    "Unimplemented expression type {}, {}",
815                    expr_type,
816                    dump(ob, None)?
817                );
818                Err(pyo3::exceptions::PyValueError::new_err(
819                    ob.error_message("<unknown>", err_msg.as_str()),
820                ))
821            }
822        }
823    }
824}
825
826impl CodeGen for Expr {
827    type Context = CodeGenContext;
828    type Options = PythonOptions;
829    type SymbolTable = SymbolTableScopes;
830
831    fn to_rust(
832        self,
833        ctx: Self::Context,
834        options: Self::Options,
835        symbols: Self::SymbolTable,
836    ) -> std::result::Result<TokenStream, Box<dyn std::error::Error>> {
837        let _module_name = match ctx.clone() {
838            CodeGenContext::Module(name) => name,
839            _ => "unknown".to_string(),
840        };
841
842        match self.value.clone() {
843            ExprType::Await(a) => a.to_rust(ctx.clone(), options, symbols),
844            ExprType::BinOp(binop) => binop.to_rust(ctx.clone(), options, symbols),
845            ExprType::BoolOp(boolop) => boolop.to_rust(ctx.clone(), options, symbols),
846            ExprType::Call(call) => call.to_rust(ctx.clone(), options, symbols),
847            ExprType::Constant(constant) => constant.to_rust(ctx, options, symbols),
848            ExprType::Compare(compare) => compare.to_rust(ctx, options, symbols),
849            ExprType::Lambda(l) => l.to_rust(ctx, options, symbols),
850            ExprType::IfExp(i) => i.to_rust(ctx, options, symbols),
851            ExprType::Dict(d) => d.to_rust(ctx, options, symbols),
852            ExprType::Set(s) => s.to_rust(ctx, options, symbols),
853            ExprType::GeneratorExp(ge) => ge.to_rust(ctx, options, symbols),
854            ExprType::Tuple(t) => t.to_rust(ctx, options, symbols),
855            ExprType::Subscript(s) => s.to_rust(ctx, options, symbols),
856            ExprType::UnaryOp(operand) => operand.to_rust(ctx, options, symbols),
857            ExprType::List(l) => {
858                // Use the same logic as ExprType::List in the main match above
859                let expr_type = ExprType::List(l);
860                expr_type.to_rust(ctx, options, symbols)
861            }
862            ExprType::Name(name) => name.to_rust(ctx, options, symbols),
863            ExprType::Yield(y) => y.to_rust(ctx, options, symbols),
864            ExprType::YieldFrom(yf) => yf.to_rust(ctx, options, symbols),
865            ExprType::JoinedStr(js) => js.to_rust(ctx, options, symbols),
866            ExprType::FormattedValue(fv) => fv.to_rust(ctx, options, symbols),
867            // NoneType expressions generate no code.
868            ExprType::NoneType(_c) => Ok(quote!()),
869            _ => {
870                let error = Error::ExprTypeNotYetImplemented(self.value);
871                Err(error.into())
872            }
873        }
874    }
875}
876
877impl Node for Expr {
878    fn lineno(&self) -> Option<usize> {
879        self.lineno
880    }
881
882    fn col_offset(&self) -> Option<usize> {
883        self.col_offset
884    }
885
886    fn end_lineno(&self) -> Option<usize> {
887        self.end_lineno
888    }
889
890    fn end_col_offset(&self) -> Option<usize> {
891        self.end_col_offset
892    }
893}
894
895#[cfg(test)]
896mod tests {
897    use super::*;
898
899    #[test]
900    fn check_call_expression() {
901        let expression = crate::parse("test()", "test.py").unwrap();
902        let mut options = PythonOptions::default();
903        options.with_std_python = false;
904        let symbols = SymbolTableScopes::new();
905        let tokens = expression
906            .clone()
907            .to_rust(CodeGenContext::Module("test".to_string()), options, symbols)
908            .unwrap();
909        assert_eq!(tokens.to_string(), "fn __module_init__ () { test () } fn main () { __module_init__ () ; }");
910    }
911}