python_ast/ast/tree/
call.rs

1use proc_macro2::TokenStream;
2use pyo3::{FromPyObject, PyAny, PyResult};
3use quote::quote;
4use serde::{Deserialize, Serialize};
5
6use crate::{Arg, 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<Arg>,
12    pub keywords: Vec<Keyword>,
13}
14
15impl<'a> FromPyObject<'a> for Call {
16    fn extract(ob: &'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
40            .func
41            .to_rust(ctx.clone(), options.clone(), symbols.clone())
42            .expect("Call.func");
43        // XXX - How are we going to figure out the parameter list?
44        //let symbol = symbols.get(&self.func.id).expect(format!("looking up function {}", self.func.id).as_str());
45        //println!("symbol: {:?}", symbol);
46        let mut args = TokenStream::new();
47        for arg in self.args {
48            let arg = arg
49                .clone()
50                .to_rust(ctx.clone(), options.clone(), symbols.clone())
51                .expect(format!("Call.args {:?}", arg).as_str());
52            args.extend(arg);
53            args.extend(quote!(,));
54        }
55        Ok(quote!(#name(#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}