Skip to main content

python_ast/ast/tree/
keyword.rs

1use proc_macro2::TokenStream;
2use pyo3::{Borrowed, FromPyObject, PyAny, PyResult, prelude::PyAnyMethods};
3// Keyword arguments are now handled by just passing values
4use serde::{Deserialize, Serialize};
5
6use crate::{CodeGen, CodeGenContext, ExprType, PythonOptions, SymbolTableScopes, Node};
7
8/// A keyword argument in a function call.
9#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
10pub struct Keyword {
11    /// Keyword name (None for **kwargs unpacking)
12    pub arg: Option<String>,
13    /// Argument value
14    pub value: ExprType,
15    /// Position information
16    pub lineno: Option<usize>,
17    pub col_offset: Option<usize>,
18    pub end_lineno: Option<usize>,
19    pub end_col_offset: Option<usize>,
20}
21
22impl<'a, 'py> FromPyObject<'a, 'py> for Keyword {
23    type Error = pyo3::PyErr;
24    fn extract(ob: Borrowed<'a, 'py, PyAny>) -> PyResult<Self> {
25        let arg = if let Ok(arg_attr) = ob.getattr("arg") {
26            if arg_attr.is_none() {
27                None
28            } else {
29                Some(arg_attr.extract()?)
30            }
31        } else {
32            None
33        };
34        
35        let value: ExprType = ob.getattr("value")?.extract()?;
36        
37        Ok(Self {
38            arg,
39            value,
40            lineno: ob.lineno(),
41            col_offset: ob.col_offset(),
42            end_lineno: ob.end_lineno(),
43            end_col_offset: ob.end_col_offset(),
44        })
45    }
46}
47
48impl CodeGen for Keyword {
49    type Context = CodeGenContext;
50    type Options = PythonOptions;
51    type SymbolTable = SymbolTableScopes;
52
53    fn to_rust(
54        self,
55        ctx: Self::Context,
56        options: Self::Options,
57        symbols: Self::SymbolTable,
58    ) -> Result<TokenStream, Box<dyn std::error::Error>> {
59        let value = self.value.to_rust(ctx, options, symbols)?;
60        
61        if let Some(_keyword) = self.arg {
62            // Named keyword argument: In Python this is keyword=value,
63            // but in Rust we typically pass just the value
64            // For now, just pass the value - this could be enhanced to handle
65            // struct initialization syntax or builder patterns in the future
66            Ok(value)
67        } else {
68            // **kwargs unpacking: **dict_expr
69            // This is complex in Rust and would need special handling
70            // For now, just pass the value
71            Ok(value)
72        }
73    }
74}
75
76impl Node for Keyword {
77    fn lineno(&self) -> Option<usize> { self.lineno }
78    fn col_offset(&self) -> Option<usize> { self.col_offset }
79    fn end_lineno(&self) -> Option<usize> { self.end_lineno }
80    fn end_col_offset(&self) -> Option<usize> { self.end_col_offset }
81}