mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Rework native function creation a bit
This commit is contained in:
6 files changed
+139
-68
No files matched your search
+10
-4
@@ -271,13 +271,19 @@ where
|
||||
let item_meta = MethodItemMeta::from_attr(ident.clone(), &item_attr)?;
|
||||
|
||||
let py_name = item_meta.method_name()?;
|
||||
let new_func = Ident::new(&format!("new_{}", &self.method_type), args.item.span());
|
||||
let build_func = Ident::new(&format!("build_{}", &self.method_type), args.item.span());
|
||||
let tokens = {
|
||||
let new_func = quote_spanned!(
|
||||
ident.span() => .#new_func(Self::#ident)
|
||||
let doc = args.attrs.doc().map_or_else(
|
||||
TokenStream::new,
|
||||
|doc| quote!(.with_doc(#doc.to_owned(), ctx)),
|
||||
);
|
||||
quote! {
|
||||
class.set_str_attr(#py_name, ctx#new_func);
|
||||
class.set_str_attr(
|
||||
#py_name,
|
||||
ctx.new_function_named(Self::#ident, #py_name.to_owned())
|
||||
#doc
|
||||
.#build_func(ctx),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+10
-2
@@ -257,9 +257,17 @@ impl ModuleItem for FunctionItem {
|
||||
|
||||
let py_name = item_meta.simple_name()?;
|
||||
let item = {
|
||||
let doc = args.attrs.doc().map_or_else(
|
||||
TokenStream::new,
|
||||
|doc| quote!(.with_doc(#doc.to_owned(), &vm.ctx)),
|
||||
);
|
||||
let module = args.module_name();
|
||||
let new_func = quote_spanned!(
|
||||
ident.span() => vm.ctx.new_function_named(#ident, #module.to_owned(), #py_name.to_owned())
|
||||
let new_func = quote_spanned!(ident.span()=>
|
||||
vm.ctx.new_function_named(#ident, #py_name.to_owned())
|
||||
#doc
|
||||
.into_function()
|
||||
.with_module(vm.ctx.new_str(#module.to_owned()))
|
||||
.build(&vm.ctx)
|
||||
);
|
||||
quote! {
|
||||
vm.__module_set_attr(&module, #py_name, #new_func).unwrap();
|
||||
|
||||
@@ -77,3 +77,8 @@ mod vm;
|
||||
pub use self::vm::{InitParameter, Interpreter, PySettings, VirtualMachine};
|
||||
pub use rustpython_bytecode::*;
|
||||
pub use rustpython_common as common;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub mod __exports {
|
||||
pub use paste;
|
||||
}
|
||||
+7
-4
@@ -235,13 +235,16 @@ macro_rules! class_or_notimplemented {
|
||||
#[macro_export]
|
||||
macro_rules! named_function {
|
||||
($ctx:expr, $module:ident, $func:ident) => {{
|
||||
paste::expr! {
|
||||
$crate::pyobject::PyContext::new_function_named(
|
||||
&$ctx,
|
||||
#[allow(unused_variables)] // weird lint, something to do with paste probably
|
||||
let ctx: &$crate::pyobject::PyContext = &$ctx;
|
||||
$crate::__exports::paste::expr! {
|
||||
ctx.new_function_named(
|
||||
[<$module _ $func>],
|
||||
stringify!($module).to_owned(),
|
||||
stringify!($func).to_owned(),
|
||||
)
|
||||
.into_function()
|
||||
.with_module(ctx.new_str(stringify!($func).to_owned()))
|
||||
.build(ctx)
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
@@ -1,17 +1,64 @@
|
||||
use std::fmt;
|
||||
|
||||
use super::objclassmethod::PyClassMethod;
|
||||
use crate::function::{OptionalArg, PyFuncArgs, PyNativeFunc};
|
||||
use crate::obj::objstr::PyStringRef;
|
||||
use crate::obj::objtype::PyClassRef;
|
||||
use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol};
|
||||
use crate::pyobject::{
|
||||
PyClassImpl, PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
|
||||
};
|
||||
use crate::slots::{SlotCall, SlotDescriptor};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub struct PyFuncDef {
|
||||
pub func: PyNativeFunc,
|
||||
pub name: Option<PyStringRef>,
|
||||
pub doc: Option<PyStringRef>,
|
||||
}
|
||||
|
||||
impl From<PyNativeFunc> for PyFuncDef {
|
||||
fn from(func: PyNativeFunc) -> Self {
|
||||
Self {
|
||||
func,
|
||||
name: None,
|
||||
doc: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PyFuncDef {
|
||||
pub fn with_doc(mut self, doc: String, ctx: &PyContext) -> Self {
|
||||
self.doc = Some(ctx.new_stringref(doc));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn into_function(self) -> PyBuiltinFunction {
|
||||
self.into()
|
||||
}
|
||||
pub fn build_function(self, ctx: &PyContext) -> PyObjectRef {
|
||||
self.into_function().build(ctx)
|
||||
}
|
||||
pub fn build_method(self, ctx: &PyContext) -> PyObjectRef {
|
||||
PyObject::new(
|
||||
PyBuiltinMethod::from(self),
|
||||
ctx.types.method_descriptor_type.clone(),
|
||||
None,
|
||||
)
|
||||
}
|
||||
pub fn build_classmethod(self, ctx: &PyContext) -> PyObjectRef {
|
||||
// TODO: classmethod_descriptor
|
||||
PyObject::new(
|
||||
PyClassMethod::from(self.build_method(ctx)),
|
||||
ctx.types.classmethod_type.clone(),
|
||||
None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "builtin_function_or_method", module = false)]
|
||||
pub struct PyBuiltinFunction {
|
||||
value: PyNativeFunc,
|
||||
module: Option<PyStringRef>,
|
||||
name: Option<PyStringRef>,
|
||||
value: PyFuncDef,
|
||||
module: Option<PyObjectRef>,
|
||||
}
|
||||
|
||||
impl PyValue for PyBuiltinFunction {
|
||||
@@ -28,49 +75,62 @@ impl fmt::Debug for PyBuiltinFunction {
|
||||
|
||||
impl From<PyNativeFunc> for PyBuiltinFunction {
|
||||
fn from(value: PyNativeFunc) -> Self {
|
||||
PyFuncDef::from(value).into()
|
||||
}
|
||||
}
|
||||
impl From<PyFuncDef> for PyBuiltinFunction {
|
||||
fn from(value: PyFuncDef) -> Self {
|
||||
Self {
|
||||
value,
|
||||
module: None,
|
||||
name: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PyBuiltinFunction {
|
||||
pub fn new_with_name(value: PyNativeFunc, module: PyStringRef, name: PyStringRef) -> Self {
|
||||
Self {
|
||||
value,
|
||||
module: Some(module),
|
||||
name: Some(name),
|
||||
}
|
||||
pub fn with_module(mut self, module: PyObjectRef) -> Self {
|
||||
self.module = Some(module);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self, ctx: &PyContext) -> PyObjectRef {
|
||||
PyObject::new(
|
||||
self,
|
||||
ctx.types.builtin_function_or_method_type.clone(),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn as_func(&self) -> &PyNativeFunc {
|
||||
&self.value
|
||||
&self.value.func
|
||||
}
|
||||
}
|
||||
|
||||
impl SlotCall for PyBuiltinFunction {
|
||||
fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
(self.value)(vm, args)
|
||||
(self.value.func)(vm, args)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotCall), flags(HAS_DICT))]
|
||||
impl PyBuiltinFunction {
|
||||
#[pyproperty(magic)]
|
||||
fn module(&self) -> Option<PyStringRef> {
|
||||
self.module.clone()
|
||||
fn module(&self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.unwrap_or_none(self.module.clone())
|
||||
}
|
||||
#[pyproperty(magic)]
|
||||
fn name(&self) -> Option<PyStringRef> {
|
||||
self.name.clone()
|
||||
self.value.name.clone()
|
||||
}
|
||||
#[pyproperty(magic)]
|
||||
fn doc(&self) -> Option<PyStringRef> {
|
||||
self.value.doc.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(module = false, name = "method_descriptor")]
|
||||
pub struct PyBuiltinMethod {
|
||||
function: PyBuiltinFunction,
|
||||
value: PyFuncDef,
|
||||
}
|
||||
|
||||
impl PyValue for PyBuiltinMethod {
|
||||
@@ -85,23 +145,25 @@ impl fmt::Debug for PyBuiltinMethod {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PyNativeFunc> for PyBuiltinMethod {
|
||||
fn from(value: PyNativeFunc) -> Self {
|
||||
Self {
|
||||
function: value.into(),
|
||||
}
|
||||
impl From<PyFuncDef> for PyBuiltinMethod {
|
||||
fn from(value: PyFuncDef) -> Self {
|
||||
Self { value }
|
||||
}
|
||||
}
|
||||
|
||||
impl PyBuiltinMethod {
|
||||
pub fn new_with_name(value: PyNativeFunc, module: PyStringRef, name: PyStringRef) -> Self {
|
||||
pub fn new_with_name(func: PyNativeFunc, name: PyStringRef) -> Self {
|
||||
Self {
|
||||
function: PyBuiltinFunction::new_with_name(value, module, name),
|
||||
value: PyFuncDef {
|
||||
func,
|
||||
name: Some(name),
|
||||
doc: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_func(&self) -> &PyNativeFunc {
|
||||
&self.function.value
|
||||
&self.value.func
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,19 +188,19 @@ impl SlotDescriptor for PyBuiltinMethod {
|
||||
|
||||
impl SlotCall for PyBuiltinMethod {
|
||||
fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
(self.function.value)(vm, args)
|
||||
(self.value.func)(vm, args)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotDescriptor, SlotCall))]
|
||||
impl PyBuiltinMethod {
|
||||
#[pyproperty(magic)]
|
||||
fn module(&self) -> Option<PyStringRef> {
|
||||
self.function.module.clone()
|
||||
fn name(&self) -> Option<PyStringRef> {
|
||||
self.value.name.clone()
|
||||
}
|
||||
#[pyproperty(magic)]
|
||||
fn name(&self) -> Option<PyStringRef> {
|
||||
self.function.name.clone()
|
||||
fn doc(&self) -> Option<PyStringRef> {
|
||||
self.value.doc.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-28
@@ -12,10 +12,9 @@ use num_traits::ToPrimitive;
|
||||
use crate::bytecode;
|
||||
use crate::exceptions::{self, PyBaseExceptionRef};
|
||||
use crate::function::{IntoPyNativeFunc, PyFuncArgs};
|
||||
use crate::obj::objbuiltinfunc::{PyBuiltinFunction, PyBuiltinMethod};
|
||||
use crate::obj::objbuiltinfunc::PyFuncDef;
|
||||
use crate::obj::objbytearray;
|
||||
use crate::obj::objbytes;
|
||||
use crate::obj::objclassmethod::PyClassMethod;
|
||||
use crate::obj::objcode;
|
||||
use crate::obj::objcode::PyCodeRef;
|
||||
use crate::obj::objcomplex::PyComplex;
|
||||
@@ -141,7 +140,7 @@ impl PyContext {
|
||||
let empty_tuple = create_object(PyTuple::from(vec![]), &types.tuple_type);
|
||||
|
||||
let tp_new_wrapper = create_object(
|
||||
PyBuiltinFunction::from(objtype::tp_new_wrapper.into_func()),
|
||||
PyFuncDef::from(objtype::tp_new_wrapper.into_func()).into_function(),
|
||||
&types.builtin_function_or_method_type,
|
||||
)
|
||||
.into_object();
|
||||
@@ -213,9 +212,9 @@ impl PyContext {
|
||||
|
||||
pub fn new_str<S>(&self, s: S) -> PyObjectRef
|
||||
where
|
||||
objstr::PyString: std::convert::From<S>,
|
||||
S: Into<objstr::PyString>,
|
||||
{
|
||||
PyObject::new(objstr::PyString::from(s), self.types.str_type.clone(), None)
|
||||
PyObject::new(s.into(), self.types.str_type.clone(), None)
|
||||
}
|
||||
|
||||
pub fn new_bytes(&self, data: Vec<u8>) -> PyObjectRef {
|
||||
@@ -284,46 +283,34 @@ impl PyContext {
|
||||
where
|
||||
F: IntoPyNativeFunc<FKind>,
|
||||
{
|
||||
PyObject::new(
|
||||
PyBuiltinFunction::from(f.into_func()),
|
||||
self.types.builtin_function_or_method_type.clone(),
|
||||
None,
|
||||
)
|
||||
PyFuncDef::from(f.into_func()).build_function(self)
|
||||
}
|
||||
|
||||
pub fn new_function_named<F, FKind>(&self, f: F, module: String, name: String) -> PyObjectRef
|
||||
pub(crate) fn new_stringref(&self, s: String) -> objstr::PyStringRef {
|
||||
PyRef::new_ref(objstr::PyString::from(s), self.types.str_type.clone(), None)
|
||||
}
|
||||
|
||||
pub fn new_function_named<F, FKind>(&self, f: F, name: String) -> PyFuncDef
|
||||
where
|
||||
F: IntoPyNativeFunc<FKind>,
|
||||
{
|
||||
let stringref =
|
||||
|s| PyRef::new_ref(objstr::PyString::from(s), self.types.str_type.clone(), None);
|
||||
PyObject::new(
|
||||
PyBuiltinFunction::new_with_name(f.into_func(), stringref(module), stringref(name)),
|
||||
self.types.builtin_function_or_method_type.clone(),
|
||||
None,
|
||||
)
|
||||
let mut f = PyFuncDef::from(f.into_func());
|
||||
f.name = Some(self.new_stringref(name));
|
||||
f
|
||||
}
|
||||
|
||||
pub fn new_method<F, FKind>(&self, f: F) -> PyObjectRef
|
||||
where
|
||||
F: IntoPyNativeFunc<FKind>,
|
||||
{
|
||||
PyObject::new(
|
||||
PyBuiltinMethod::from(f.into_func()),
|
||||
self.types.method_descriptor_type.clone(),
|
||||
None,
|
||||
)
|
||||
PyFuncDef::from(f.into_func()).build_method(self)
|
||||
}
|
||||
|
||||
pub fn new_classmethod<F, FKind>(&self, f: F) -> PyObjectRef
|
||||
where
|
||||
F: IntoPyNativeFunc<FKind>,
|
||||
{
|
||||
PyObject::new(
|
||||
PyClassMethod::from(self.new_method(f)),
|
||||
self.types.classmethod_type.clone(),
|
||||
None,
|
||||
)
|
||||
PyFuncDef::from(f.into_func()).build_classmethod(self)
|
||||
}
|
||||
pub fn new_staticmethod<F, FKind>(&self, f: F) -> PyObjectRef
|
||||
where
|
||||
|
||||
Reference in new issue
Block a user