python_ast/ast/tree/
assign.rs1use proc_macro2::TokenStream;
2use pyo3::{Bound, FromPyObject, PyAny, PyResult, prelude::PyAnyMethods};
3use quote::quote;
4use serde::{Deserialize, Serialize};
5
6use crate::{
7 CodeGen, CodeGenContext, ExprType, Node, PythonOptions, SymbolTableNode,
8 SymbolTableScopes,
9};
10
11#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
12pub struct Assign {
13 pub targets: Vec<ExprType>,
14 pub value: ExprType,
15 pub type_comment: Option<String>,
16}
17
18impl<'a> FromPyObject<'a> for Assign {
19 fn extract_bound(ob: &Bound<'a, PyAny>) -> PyResult<Self> {
20 let targets: Vec<ExprType> = ob
21 .getattr("targets")
22 .expect(
23 ob.error_message("<unknown>", "error getting assignment targets")
24 .as_str(),
25 )
26 .extract()
27 .expect("extracting assignment targets");
28
29 let python_value = ob.getattr("value").expect(
30 ob.error_message("<unknown>", "assignment statement value not found")
31 .as_str(),
32 );
33
34 let value = python_value.extract().expect(
35 ob.error_message("<unknown>", "error getting value of assignment statement")
36 .as_str(),
37 );
38
39 Ok(Assign {
40 targets: targets,
41 value: value,
42 type_comment: None,
43 })
44 }
45}
46
47impl<'a> CodeGen for Assign {
48 type Context = CodeGenContext;
49 type Options = PythonOptions;
50 type SymbolTable = SymbolTableScopes;
51
52 fn find_symbols(self, symbols: Self::SymbolTable) -> Self::SymbolTable {
53 let mut symbols = symbols;
54 let mut position = 0;
55 for target in self.targets {
56 if let ExprType::Name(name) = target {
58 symbols.insert(
59 name.id,
60 SymbolTableNode::Assign {
61 position: position,
62 value: self.value.clone(),
63 },
64 );
65 }
66 position += 1;
68 }
69 symbols
70 }
71
72 fn to_rust(
73 self,
74 ctx: Self::Context,
75 options: Self::Options,
76 symbols: Self::SymbolTable,
77 ) -> Result<TokenStream, Box<dyn std::error::Error>> {
78 let mut target_streams = Vec::new();
79
80 for target in self.targets {
82 let target_code = target.to_rust(ctx.clone(), options.clone(), symbols.clone())?;
83 target_streams.push(target_code);
84 }
85
86 let value = self.value.to_rust(ctx, options, symbols)?;
87
88 if target_streams.len() == 1 {
90 let target = &target_streams[0];
91 Ok(quote!(let #target = #value;))
94 } else {
95 Ok(quote! {
98 let (#(#target_streams),*) = #value;
99 })
100 }
101 }
102}