mirror of
https://github.com/RustPython/Parser.git
synced 2025-08-03 18:29:04 +00:00
Separate rustpython_ast_pyo3
This commit is contained in:
parent
b81273e9bc
commit
7d384d88d0
13 changed files with 3209 additions and 3208 deletions
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -41,8 +41,3 @@ pub use visitor::Visitor;
|
|||
mod optimizer;
|
||||
#[cfg(feature = "constant-optimization")]
|
||||
pub use optimizer::ConstantOptimizer;
|
||||
|
||||
#[cfg(feature = "pyo3")]
|
||||
pub mod pyo3;
|
||||
#[cfg(feature = "pyo3-wrapper")]
|
||||
pub mod pyo3_wrapper;
|
||||
|
|
212
ast/src/pyo3.rs
212
ast/src/pyo3.rs
|
@ -1,212 +0,0 @@
|
|||
use crate::{source_code::SourceRange, text_size::TextRange, ConversionFlag, Node};
|
||||
use num_complex::Complex64;
|
||||
use once_cell::sync::OnceCell;
|
||||
use pyo3::{
|
||||
prelude::*,
|
||||
types::{PyBool, PyBytes, PyList, PyString, PyTuple},
|
||||
ToPyObject,
|
||||
};
|
||||
|
||||
pub trait Pyo3Node {
|
||||
fn py_type_cache() -> &'static OnceCell<(Py<PyAny>, Py<PyAny>)> {
|
||||
{
|
||||
static PY_TYPE: OnceCell<(Py<PyAny>, Py<PyAny>)> = OnceCell::new();
|
||||
&PY_TYPE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToPyo3Ast {
|
||||
fn to_pyo3_ast<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny>;
|
||||
}
|
||||
|
||||
impl<T: ToPyo3Ast> ToPyo3Ast for Box<T> {
|
||||
#[inline]
|
||||
fn to_pyo3_ast<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> {
|
||||
(**self).to_pyo3_ast(py)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ToPyo3Ast> ToPyo3Ast for Option<T> {
|
||||
#[inline]
|
||||
fn to_pyo3_ast<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> {
|
||||
match self {
|
||||
Some(ast) => ast.to_pyo3_ast(py),
|
||||
None => Ok(ast_cache().none_ref(py)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ToPyo3Ast> ToPyo3Ast for Vec<T> {
|
||||
fn to_pyo3_ast<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> {
|
||||
let elts = self
|
||||
.iter()
|
||||
.map(|item| item.to_pyo3_ast(py))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let list = PyList::new(py, elts);
|
||||
Ok(list.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyo3Ast for crate::Identifier {
|
||||
#[inline]
|
||||
fn to_pyo3_ast<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> {
|
||||
Ok(PyString::new(py, self.as_str()).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyo3Ast for crate::String {
|
||||
#[inline]
|
||||
fn to_pyo3_ast<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> {
|
||||
Ok(PyString::new(py, self.as_str()).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyo3Ast for bool {
|
||||
#[inline]
|
||||
fn to_pyo3_ast<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> {
|
||||
Ok(ast_cache().bool_int(py, *self))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyo3Ast for ConversionFlag {
|
||||
#[inline]
|
||||
fn to_pyo3_ast<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> {
|
||||
Ok(ast_cache().conversion_flag(py, *self))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyObject for crate::Constant {
|
||||
fn to_object(&self, py: Python) -> PyObject {
|
||||
let cache = ast_cache();
|
||||
match self {
|
||||
crate::Constant::None => cache.none.clone_ref(py),
|
||||
crate::Constant::Bool(bool) => cache.bool(py, *bool).into(),
|
||||
crate::Constant::Str(string) => string.to_object(py),
|
||||
crate::Constant::Bytes(bytes) => PyBytes::new(py, bytes).into(),
|
||||
crate::Constant::Int(int) => int.to_object(py),
|
||||
crate::Constant::Tuple(elts) => {
|
||||
let elts: Vec<_> = elts.iter().map(|c| c.to_object(py)).collect();
|
||||
PyTuple::new(py, elts).into()
|
||||
}
|
||||
crate::Constant::Float(f64) => f64.to_object(py),
|
||||
crate::Constant::Complex { real, imag } => Complex64::new(*real, *imag).to_object(py),
|
||||
crate::Constant::Ellipsis => py.Ellipsis(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl ToPyo3Ast for crate::Constant {
|
||||
// #[inline]
|
||||
// fn to_pyo3_ast<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> {
|
||||
// let cache = ast_cache();
|
||||
// let value = match self {
|
||||
// crate::Constant::None => cache.none_ref(py),
|
||||
// crate::Constant::Bool(bool) => cache.bool_ref(py),
|
||||
// crate::Constant::Str(string) => string.to_object(py),
|
||||
// crate::Constant::Bytes(bytes) => PyBytes::new(py, bytes).into(),
|
||||
// crate::Constant::Int(int) => int.to_object(py),
|
||||
// crate::Constant::Tuple(elts) => {
|
||||
// let elts: PyResult<Vec<_>> = elts.iter().map(|c| c.to_pyo3_ast(py)).collect();
|
||||
// PyTuple::new(py, elts?).into()
|
||||
// }
|
||||
// crate::Constant::Float(f64) => f64.to_object(py),
|
||||
// crate::Constant::Complex { real, imag } => Complex64::new(*real, *imag).to_object(py),
|
||||
// crate::Constant::Ellipsis => py.Ellipsis(),
|
||||
// };
|
||||
// Ok(value)
|
||||
// }
|
||||
// }
|
||||
|
||||
#[pyclass(module = "rustpython_ast", subclass)]
|
||||
pub struct AST;
|
||||
|
||||
#[pymethods]
|
||||
impl AST {
|
||||
#[new]
|
||||
fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
fn cache_py_type<N: Pyo3Node + Node>(ast_module: &PyAny) -> PyResult<()> {
|
||||
let class = ast_module.getattr(N::NAME)?;
|
||||
let base = if std::mem::size_of::<N>() == 0 {
|
||||
class.call0()?
|
||||
} else {
|
||||
class.getattr("__new__")?
|
||||
};
|
||||
N::py_type_cache().get_or_init(|| (class.into(), base.into()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO: This cache must be bound to 'py
|
||||
struct AstCache {
|
||||
lineno: Py<PyString>,
|
||||
col_offset: Py<PyString>,
|
||||
end_lineno: Py<PyString>,
|
||||
end_col_offset: Py<PyString>,
|
||||
none: Py<PyAny>,
|
||||
bool_values: (Py<PyBool>, Py<PyBool>),
|
||||
bool_int_values: (Py<PyAny>, Py<PyAny>),
|
||||
conversion_flags: (Py<PyAny>, Py<PyAny>, Py<PyAny>, Py<PyAny>),
|
||||
}
|
||||
|
||||
impl AstCache {
|
||||
#[inline]
|
||||
fn none_ref<'py>(&'static self, py: Python<'py>) -> &'py PyAny {
|
||||
Py::<PyAny>::as_ref(&self.none, py)
|
||||
}
|
||||
#[inline]
|
||||
fn bool_int<'py>(&'static self, py: Python<'py>, value: bool) -> &'py PyAny {
|
||||
let v = &self.bool_int_values;
|
||||
Py::<PyAny>::as_ref(if value { &v.1 } else { &v.0 }, py)
|
||||
}
|
||||
#[inline]
|
||||
fn bool(&'static self, py: Python, value: bool) -> Py<PyBool> {
|
||||
let v = &self.bool_values;
|
||||
(if value { &v.1 } else { &v.0 }).clone_ref(py)
|
||||
}
|
||||
fn conversion_flag<'py>(&'static self, py: Python<'py>, value: ConversionFlag) -> &'py PyAny {
|
||||
let v = &self.conversion_flags;
|
||||
match value {
|
||||
ConversionFlag::None => v.0.as_ref(py),
|
||||
ConversionFlag::Str => v.1.as_ref(py),
|
||||
ConversionFlag::Ascii => v.2.as_ref(py),
|
||||
ConversionFlag::Repr => v.3.as_ref(py),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ast_cache_cell() -> &'static OnceCell<AstCache> {
|
||||
{
|
||||
static PY_TYPE: OnceCell<AstCache> = OnceCell::new();
|
||||
&PY_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
fn ast_cache() -> &'static AstCache {
|
||||
ast_cache_cell().get().unwrap()
|
||||
}
|
||||
|
||||
pub fn init(py: Python) -> PyResult<()> {
|
||||
ast_cache_cell().get_or_init(|| AstCache {
|
||||
lineno: pyo3::intern!(py, "lineno").into_py(py),
|
||||
col_offset: pyo3::intern!(py, "col_offset").into_py(py),
|
||||
end_lineno: pyo3::intern!(py, "end_lineno").into_py(py),
|
||||
end_col_offset: pyo3::intern!(py, "end_col_offset").into_py(py),
|
||||
none: py.None(),
|
||||
bool_values: (PyBool::new(py, false).into(), PyBool::new(py, true).into()),
|
||||
bool_int_values: ((0).to_object(py), (1).to_object(py)),
|
||||
conversion_flags: (
|
||||
(-1).to_object(py),
|
||||
(b's').to_object(py),
|
||||
(b'a').to_object(py),
|
||||
(b'r').to_object(py),
|
||||
),
|
||||
});
|
||||
|
||||
init_types(py)
|
||||
}
|
||||
|
||||
include!("gen/to_pyo3.rs");
|
|
@ -1,128 +0,0 @@
|
|||
use crate::pyo3::{Pyo3Node, AST};
|
||||
use crate::{source_code::SourceRange, text_size::TextRange, ConversionFlag, Node};
|
||||
use num_complex::Complex64;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyBytes, PyList, PyTuple};
|
||||
|
||||
pub trait ToPyo3Wrapper {
|
||||
fn to_pyo3_wrapper(&'static self, py: Python) -> PyResult<Py<PyAny>>;
|
||||
}
|
||||
|
||||
impl<T: ToPyo3Wrapper> ToPyo3Wrapper for Box<T> {
|
||||
#[inline]
|
||||
fn to_pyo3_wrapper(&'static self, py: Python) -> PyResult<Py<PyAny>> {
|
||||
(**self).to_pyo3_wrapper(py)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ToPyo3Wrapper> ToPyo3Wrapper for Option<T> {
|
||||
#[inline]
|
||||
fn to_pyo3_wrapper(&'static self, py: Python) -> PyResult<Py<PyAny>> {
|
||||
match self {
|
||||
Some(ast) => ast.to_pyo3_wrapper(py),
|
||||
None => Ok(py.None()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyo3Wrapper for crate::Identifier {
|
||||
#[inline]
|
||||
fn to_pyo3_wrapper(&'static self, py: Python) -> PyResult<Py<PyAny>> {
|
||||
Ok(self.as_str().to_object(py))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyo3Wrapper for crate::String {
|
||||
#[inline]
|
||||
fn to_pyo3_wrapper(&'static self, py: Python) -> PyResult<Py<PyAny>> {
|
||||
Ok(self.as_str().to_object(py))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyo3Wrapper for crate::Int {
|
||||
#[inline]
|
||||
fn to_pyo3_wrapper(&'static self, py: Python) -> PyResult<Py<PyAny>> {
|
||||
Ok((self.to_u32()).to_object(py))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyo3Wrapper for bool {
|
||||
#[inline]
|
||||
fn to_pyo3_wrapper(&'static self, py: Python) -> PyResult<Py<PyAny>> {
|
||||
Ok((*self as u32).to_object(py))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyo3Wrapper for ConversionFlag {
|
||||
#[inline]
|
||||
fn to_pyo3_wrapper(&'static self, py: Python) -> PyResult<Py<PyAny>> {
|
||||
Ok((*self as i8).to_object(py))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyo3Wrapper for crate::Constant {
|
||||
fn to_pyo3_wrapper(&'static self, py: Python) -> PyResult<Py<PyAny>> {
|
||||
let value = match self {
|
||||
crate::Constant::None => py.None(),
|
||||
crate::Constant::Bool(bool) => bool.to_object(py),
|
||||
crate::Constant::Str(string) => string.to_object(py),
|
||||
crate::Constant::Bytes(bytes) => PyBytes::new(py, bytes).into(),
|
||||
crate::Constant::Int(int) => int.to_object(py),
|
||||
crate::Constant::Tuple(elts) => {
|
||||
let elts: PyResult<Vec<_>> = elts.iter().map(|c| c.to_pyo3_wrapper(py)).collect();
|
||||
PyTuple::new(py, elts?).into()
|
||||
}
|
||||
crate::Constant::Float(f64) => f64.to_object(py),
|
||||
crate::Constant::Complex { real, imag } => Complex64::new(*real, *imag).to_object(py),
|
||||
crate::Constant::Ellipsis => py.Ellipsis(),
|
||||
};
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ToPyo3Wrapper> ToPyo3Wrapper for Vec<T> {
|
||||
fn to_pyo3_wrapper(&'static self, py: Python) -> PyResult<Py<PyAny>> {
|
||||
let list = PyList::empty(py);
|
||||
for item in self {
|
||||
let py_item = item.to_pyo3_wrapper(py)?;
|
||||
list.append(py_item)?;
|
||||
}
|
||||
Ok(list.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub mod located {
|
||||
use super::*;
|
||||
pub use crate::pyo3::AST;
|
||||
include!("gen/pyo3_wrapper_located.rs");
|
||||
}
|
||||
|
||||
pub mod ranged {
|
||||
use super::*;
|
||||
pub use crate::pyo3::AST;
|
||||
include!("gen/pyo3_wrapper_ranged.rs");
|
||||
}
|
||||
|
||||
fn init_type<P: pyo3::PyClass, N: Pyo3Node + Node>(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<P>()?;
|
||||
let node = m.getattr(P::NAME)?;
|
||||
if P::NAME != N::NAME {
|
||||
// TODO: no idea how to escape rust keyword on #[pyclass]
|
||||
m.setattr(P::NAME, node)?;
|
||||
}
|
||||
let names: Vec<&'static str> = N::FIELD_NAMES.to_vec();
|
||||
let fields = PyTuple::new(py, names);
|
||||
node.setattr("_fields", fields)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A Python module implemented in Rust.
|
||||
fn init_module(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<AST>()?;
|
||||
|
||||
let ast = m.getattr("AST")?;
|
||||
let fields = PyTuple::empty(py);
|
||||
ast.setattr("_fields", fields)?;
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue