python_ast/ast/tree/
named_expression.rs

1use proc_macro2::TokenStream;
2use pyo3::FromPyObject;
3use quote::quote;
4use serde::{Deserialize, Serialize};
5
6use crate::{CodeGen, CodeGenContext, ExprType, PythonOptions, SymbolTableScopes};
7
8/// A keyword argument, gnerally used in function calls.
9#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
10pub struct NamedExpr {
11    left: Box<ExprType>,
12    right: Box<ExprType>,
13}
14
15impl<'a> FromPyObject<'a> for NamedExpr {
16    fn extract(ob: &pyo3::PyAny) -> pyo3::PyResult<Self> {
17        let left = ob.getattr("left")?.extract::<ExprType>()?;
18        let right = ob.getattr("right")?.extract::<ExprType>()?;
19        Ok(NamedExpr {
20            left: Box::new(left),
21            right: Box::new(right),
22        })
23    }
24}
25
26impl CodeGen for NamedExpr {
27    type Context = CodeGenContext;
28    type Options = PythonOptions;
29    type SymbolTable = SymbolTableScopes;
30
31    fn to_rust(
32        self,
33        ctx: Self::Context,
34        options: Self::Options,
35        symbols: Self::SymbolTable,
36    ) -> Result<TokenStream, Box<dyn std::error::Error>> {
37        let left = self
38            .left
39            .clone()
40            .to_rust(ctx.clone(), options.clone(), symbols.clone())
41            .expect(format!("parsing left side of named expression {:?}", self.left).as_str());
42        let right =
43            self.right.clone().to_rust(ctx, options, symbols).expect(
44                format!("parsing right side of named expression {:?}", self.right).as_str(),
45            );
46        Ok(quote!(#left = #right))
47    }
48}
49
50#[cfg(test)]
51mod test {
52    use super::*;
53    use crate::{Constant, ExprType, Name};
54    use litrs::*;
55
56    #[test]
57    fn test_named_expression() {
58        let named_expression = NamedExpr {
59            left: Box::new(ExprType::Name(Name {
60                id: "a".to_string(),
61            })),
62            right: Box::new(ExprType::Constant(Constant(Some(Literal::Integer(
63                IntegerLit::parse("1".to_string()).unwrap(),
64            ))))),
65        };
66        let rust = named_expression
67            .to_rust(
68                CodeGenContext::Module("test".to_string()),
69                PythonOptions::default(),
70                SymbolTableScopes::new(),
71            )
72            .unwrap();
73        assert_eq!(rust.to_string(), "a = 1");
74    }
75}