Rework native function creation a bit

This commit is contained in:
Noah committed 2020-09-20 22:36:35 -05:00
1 parent 9435f71b1e
commit 6c3e4819ed
6 files changed
+139 -68

No files matched your search

+10 -4
View File
@@ -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
View File
@@ -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();
+5
View File
@@ -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
View File
@@ -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)
}
}};
}
+92 -30
View File
@@ -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
View File
@@ -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