python_ast/ast/tree/
call.rs1use proc_macro2::TokenStream;
2use pyo3::{Bound, FromPyObject, PyAny, PyResult, prelude::PyAnyMethods};
3use quote::quote;
4use serde::{Deserialize, Serialize};
5
6use crate::{CodeGen, CodeGenContext, ExprType, Keyword, PythonOptions, SymbolTableScopes};
7
8#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
9pub struct Call {
10 pub func: Box<ExprType>,
11 pub args: Vec<ExprType>,
12 pub keywords: Vec<Keyword>,
13}
14
15impl<'a> FromPyObject<'a> for Call {
16 fn extract_bound(ob: &Bound<'a, PyAny>) -> PyResult<Self> {
17 let func = ob.getattr("func").expect("Call.func");
18 let args = ob.getattr("args").expect("Call.args");
19 let keywords = ob.getattr("keywords").expect("Call.keywords");
20 Ok(Call {
21 func: Box::new(func.extract().expect("Call.func")),
22 args: args.extract().expect("Call.args"),
23 keywords: keywords.extract().expect("Call.keywords"),
24 })
25 }
26}
27
28impl<'a> CodeGen for Call {
29 type Context = CodeGenContext;
30 type Options = PythonOptions;
31 type SymbolTable = SymbolTableScopes;
32
33 fn to_rust(
34 self,
35 ctx: Self::Context,
36 options: Self::Options,
37 symbols: Self::SymbolTable,
38 ) -> Result<TokenStream, Box<dyn std::error::Error>> {
39 let name = self.func.to_rust(ctx.clone(), options.clone(), symbols.clone())?;
40
41 let mut all_args = Vec::new();
42
43 for arg in self.args {
45 let rust_arg = arg.to_rust(ctx.clone(), options.clone(), symbols.clone())?;
46 all_args.push(rust_arg);
47 }
48
49 for keyword in self.keywords {
51 let rust_kw = keyword.to_rust(ctx.clone(), options.clone(), symbols.clone())?;
52 all_args.push(rust_kw);
53 }
54
55 Ok(quote!(#name(#(#all_args),*)))
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn test_lookup_of_function() {
65 let options = PythonOptions::default();
66 let result = crate::parse(
67 "def foo(a = 7):
68 pass
69
70foo(b=9)",
71 "test.py",
72 )
73 .unwrap();
74 println!("Python tree: {:#?}", result);
75 let code = result
76 .to_rust(
77 CodeGenContext::Module("test".to_string()),
78 options,
79 SymbolTableScopes::new(),
80 )
81 .unwrap();
82 println!("Rust code: {}", code);
83 }
84}