python_ast/ast/tree/
raise_stmt.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, SymbolTableScopes,
8};
9
10#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
12pub struct Raise {
13 pub exc: Option<ExprType>,
15 pub cause: Option<ExprType>,
17 pub lineno: Option<usize>,
19 pub col_offset: Option<usize>,
20 pub end_lineno: Option<usize>,
21 pub end_col_offset: Option<usize>,
22}
23
24impl<'a> FromPyObject<'a> for Raise {
25 fn extract_bound(ob: &Bound<'a, PyAny>) -> PyResult<Self> {
26 let exc: Option<ExprType> = if let Ok(exc_attr) = ob.getattr("exc") {
28 if exc_attr.is_none() {
29 None
30 } else {
31 Some(exc_attr.extract()?)
32 }
33 } else {
34 None
35 };
36
37 let cause: Option<ExprType> = if let Ok(cause_attr) = ob.getattr("cause") {
39 if cause_attr.is_none() {
40 None
41 } else {
42 Some(cause_attr.extract()?)
43 }
44 } else {
45 None
46 };
47
48 Ok(Raise {
49 exc,
50 cause,
51 lineno: ob.lineno(),
52 col_offset: ob.col_offset(),
53 end_lineno: ob.end_lineno(),
54 end_col_offset: ob.end_col_offset(),
55 })
56 }
57}
58
59impl Node for Raise {
60 fn lineno(&self) -> Option<usize> { self.lineno }
61 fn col_offset(&self) -> Option<usize> { self.col_offset }
62 fn end_lineno(&self) -> Option<usize> { self.end_lineno }
63 fn end_col_offset(&self) -> Option<usize> { self.end_col_offset }
64}
65
66impl CodeGen for Raise {
67 type Context = CodeGenContext;
68 type Options = PythonOptions;
69 type SymbolTable = SymbolTableScopes;
70
71 fn find_symbols(self, symbols: Self::SymbolTable) -> Self::SymbolTable {
72 let symbols = if let Some(exc) = self.exc {
73 exc.find_symbols(symbols)
74 } else {
75 symbols
76 };
77
78 if let Some(cause) = self.cause {
79 cause.find_symbols(symbols)
80 } else {
81 symbols
82 }
83 }
84
85 fn to_rust(
86 self,
87 ctx: Self::Context,
88 options: Self::Options,
89 symbols: Self::SymbolTable,
90 ) -> Result<TokenStream, Box<dyn std::error::Error>> {
91 if let Some(exc) = self.exc {
92 let exc_tokens = exc.to_rust(ctx.clone(), options.clone(), symbols.clone())?;
93
94 if let Some(cause) = self.cause {
95 let cause_tokens = cause.to_rust(ctx, options, symbols)?;
96 Ok(quote! {
98 panic!("Exception: {:?} caused by {:?}", #exc_tokens, #cause_tokens)
99 })
100 } else {
101 Ok(quote! {
102 panic!("Exception: {:?}", #exc_tokens)
103 })
104 }
105 } else {
106 Ok(quote! {
108 panic!("Re-raising current exception")
109 })
110 }
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 }