python_ast/ast/tree/
yield_expr.rs1use proc_macro2::TokenStream;
2use pyo3::{Borrowed, FromPyObject, PyAny, PyResult, prelude::PyAnyMethods};
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 CodeGen, CodeGenContext, ExprType, Node, PythonOptions, SymbolTableScopes,
7};
8
9#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
11pub struct Yield {
12 pub value: Option<Box<ExprType>>,
14 pub lineno: Option<usize>,
16 pub col_offset: Option<usize>,
17 pub end_lineno: Option<usize>,
18 pub end_col_offset: Option<usize>,
19}
20
21#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
23pub struct YieldFrom {
24 pub value: Box<ExprType>,
26 pub lineno: Option<usize>,
28 pub col_offset: Option<usize>,
29 pub end_lineno: Option<usize>,
30 pub end_col_offset: Option<usize>,
31}
32
33impl<'a, 'py> FromPyObject<'a, 'py> for Yield {
34 type Error = pyo3::PyErr;
35 fn extract(ob: Borrowed<'a, 'py, PyAny>) -> PyResult<Self> {
36 let value: Option<Box<ExprType>> = if let Ok(value_attr) = ob.getattr("value") {
38 if value_attr.is_none() {
39 None
40 } else {
41 Some(Box::new(value_attr.extract()?))
42 }
43 } else {
44 None
45 };
46
47 Ok(Yield {
48 value,
49 lineno: ob.lineno(),
50 col_offset: ob.col_offset(),
51 end_lineno: ob.end_lineno(),
52 end_col_offset: ob.end_col_offset(),
53 })
54 }
55}
56
57impl<'a, 'py> FromPyObject<'a, 'py> for YieldFrom {
58 type Error = pyo3::PyErr;
59 fn extract(ob: Borrowed<'a, 'py, PyAny>) -> PyResult<Self> {
60 let value: ExprType = ob.getattr("value")?.extract()?;
62
63 Ok(YieldFrom {
64 value: Box::new(value),
65 lineno: ob.lineno(),
66 col_offset: ob.col_offset(),
67 end_lineno: ob.end_lineno(),
68 end_col_offset: ob.end_col_offset(),
69 })
70 }
71}
72
73impl Node for Yield {
74 fn lineno(&self) -> Option<usize> { self.lineno }
75 fn col_offset(&self) -> Option<usize> { self.col_offset }
76 fn end_lineno(&self) -> Option<usize> { self.end_lineno }
77 fn end_col_offset(&self) -> Option<usize> { self.end_col_offset }
78}
79
80impl Node for YieldFrom {
81 fn lineno(&self) -> Option<usize> { self.lineno }
82 fn col_offset(&self) -> Option<usize> { self.col_offset }
83 fn end_lineno(&self) -> Option<usize> { self.end_lineno }
84 fn end_col_offset(&self) -> Option<usize> { self.end_col_offset }
85}
86
87impl CodeGen for Yield {
88 type Context = CodeGenContext;
89 type Options = PythonOptions;
90 type SymbolTable = SymbolTableScopes;
91
92 fn find_symbols(self, symbols: Self::SymbolTable) -> Self::SymbolTable {
93 if let Some(value) = self.value {
94 (*value).find_symbols(symbols)
95 } else {
96 symbols
97 }
98 }
99
100 fn to_rust(
101 self,
102 _ctx: Self::Context,
103 _options: Self::Options,
104 _symbols: Self::SymbolTable,
105 ) -> Result<TokenStream, Box<dyn std::error::Error>> {
106 Err(
109 "generators (`yield`) are not supported yet: the function would \
110 silently evaluate a single value instead of producing a \
111 generator. Rewrite it to build and return a list."
112 .to_string()
113 .into(),
114 )
115 }
116}
117
118impl CodeGen for YieldFrom {
119 type Context = CodeGenContext;
120 type Options = PythonOptions;
121 type SymbolTable = SymbolTableScopes;
122
123 fn find_symbols(self, symbols: Self::SymbolTable) -> Self::SymbolTable {
124 (*self.value).find_symbols(symbols)
125 }
126
127 fn to_rust(
128 self,
129 _ctx: Self::Context,
130 _options: Self::Options,
131 _symbols: Self::SymbolTable,
132 ) -> Result<TokenStream, Box<dyn std::error::Error>> {
133 Err(
134 "generators (`yield from`) are not supported yet: the function \
135 would silently evaluate the iterable once instead of delegating \
136 to it. Rewrite it to build and return a list."
137 .to_string()
138 .into(),
139 )
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 }