Skip to content

Commit c2bbacf

Browse files
committed
Add __name__ and __module__ fields to builtin functions
1 parent 2224650 commit c2bbacf

File tree

5 files changed

+94
-15
lines changed

5 files changed

+94
-15
lines changed

vm/src/macros.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,3 +328,17 @@ macro_rules! class_or_notimplemented {
328328
}
329329
};
330330
}
331+
332+
#[macro_export]
333+
macro_rules! named_function {
334+
($ctx:expr, $module:ident, $func:ident) => {{
335+
paste::expr! {
336+
$crate::pyobject::PyContext::new_function_named(
337+
&$ctx,
338+
[<$module _ $func>],
339+
stringify!($module).to_owned(),
340+
stringify!($func).to_owned(),
341+
)
342+
}
343+
}};
344+
}

vm/src/obj/objbuiltinfunc.rs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::fmt;
22

33
use crate::function::{OptionalArg, PyFuncArgs, PyNativeFunc};
4+
use crate::obj::objstr::PyStringRef;
45
use crate::obj::objtype::PyClassRef;
56
use crate::pyobject::{
67
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol,
@@ -11,12 +12,15 @@ use crate::vm::VirtualMachine;
1112
#[pyclass]
1213
pub struct PyBuiltinFunction {
1314
value: PyNativeFunc,
15+
module: Option<PyStringRef>,
16+
name: Option<PyStringRef>,
1417
}
1518

1619
impl PyValue for PyBuiltinFunction {
1720
fn class(vm: &VirtualMachine) -> PyClassRef {
1821
vm.ctx.builtin_function_or_method_type()
1922
}
23+
const HAVE_DICT: bool = true;
2024
}
2125

2226
impl fmt::Debug for PyBuiltinFunction {
@@ -27,7 +31,19 @@ impl fmt::Debug for PyBuiltinFunction {
2731

2832
impl PyBuiltinFunction {
2933
pub fn new(value: PyNativeFunc) -> Self {
30-
Self { value }
34+
Self {
35+
value,
36+
module: None,
37+
name: None,
38+
}
39+
}
40+
41+
pub fn new_with_name(value: PyNativeFunc, module: PyStringRef, name: PyStringRef) -> Self {
42+
Self {
43+
value,
44+
module: Some(module),
45+
name: Some(name),
46+
}
3147
}
3248

3349
pub fn as_func(&self) -> &PyNativeFunc {
@@ -42,7 +58,16 @@ impl SlotCall for PyBuiltinFunction {
4258
}
4359

4460
#[pyimpl(with(SlotCall))]
45-
impl PyBuiltinFunction {}
61+
impl PyBuiltinFunction {
62+
#[pyproperty(magic)]
63+
fn module(&self) -> Option<PyStringRef> {
64+
self.module.clone()
65+
}
66+
#[pyproperty(magic)]
67+
fn name(&self) -> Option<PyStringRef> {
68+
self.name.clone()
69+
}
70+
}
4671

4772
#[pyclass]
4873
pub struct PyBuiltinMethod {
@@ -64,7 +89,12 @@ impl fmt::Debug for PyBuiltinMethod {
6489
impl PyBuiltinMethod {
6590
pub fn new(value: PyNativeFunc) -> Self {
6691
Self {
67-
function: PyBuiltinFunction { value },
92+
function: PyBuiltinFunction::new(value),
93+
}
94+
}
95+
pub fn new_with_name(value: PyNativeFunc, module: PyStringRef, name: PyStringRef) -> Self {
96+
Self {
97+
function: PyBuiltinFunction::new_with_name(value, module, name),
6898
}
6999
}
70100

@@ -100,9 +130,14 @@ impl SlotCall for PyBuiltinMethod {
100130

101131
#[pyimpl(with(SlotDescriptor, SlotCall))]
102132
impl PyBuiltinMethod {
103-
// TODO: give builtin functions names
104133
#[pyproperty(magic)]
105-
fn name(&self) {}
134+
fn module(&self) -> Option<PyStringRef> {
135+
self.function.module.clone()
136+
}
137+
#[pyproperty(magic)]
138+
fn name(&self) -> Option<PyStringRef> {
139+
self.function.name.clone()
140+
}
106141
}
107142

108143
pub fn init(context: &PyContext) {

vm/src/pyobject.rs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ impl PyContext {
138138
let exceptions = exceptions::ExceptionZoo::new(&types.type_type, &types.object_type);
139139

140140
fn create_object<T: PyObjectPayload + PyValue>(payload: T, cls: &PyClassRef) -> PyRef<T> {
141-
PyRef::new_ref_unchecked(PyObject::new(payload, cls.clone(), None))
141+
PyRef::from_obj_unchecked(PyObject::new(payload, cls.clone(), None))
142142
}
143143

144144
let none_type = create_type("NoneType", &types.type_type, &types.object_type);
@@ -492,6 +492,18 @@ impl PyContext {
492492
)
493493
}
494494

495+
pub fn new_function_named<F, T, R, VM>(&self, f: F, module: String, name: String) -> PyObjectRef
496+
where
497+
F: IntoPyNativeFunc<T, R, VM>,
498+
{
499+
let stringref = |s| PyRef::new_ref(objstr::PyString::from(s), self.str_type(), None);
500+
PyObject::new(
501+
PyBuiltinFunction::new_with_name(f.into_func(), stringref(module), stringref(name)),
502+
self.builtin_function_or_method_type(),
503+
None,
504+
)
505+
}
506+
495507
pub fn new_method<F, T, R, VM>(&self, f: F) -> PyObjectRef
496508
where
497509
F: IntoPyNativeFunc<T, R, VM>,
@@ -695,9 +707,14 @@ impl<T> Clone for PyRef<T> {
695707
}
696708

697709
impl<T: PyValue> PyRef<T> {
698-
fn new_ref(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<Self> {
710+
#[allow(clippy::new_ret_no_self)]
711+
pub fn new_ref(payload: T, typ: PyClassRef, dict: Option<PyDictRef>) -> Self {
712+
Self::from_obj_unchecked(PyObject::new(payload, typ, dict))
713+
}
714+
715+
fn from_obj(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<Self> {
699716
if obj.payload_is::<T>() {
700-
Ok(Self::new_ref_unchecked(obj))
717+
Ok(Self::from_obj_unchecked(obj))
701718
} else {
702719
Err(vm.new_runtime_error(format!(
703720
"Unexpected payload for type {:?}",
@@ -706,7 +723,7 @@ impl<T: PyValue> PyRef<T> {
706723
}
707724
}
708725

709-
pub(crate) fn new_ref_unchecked(obj: PyObjectRef) -> Self {
726+
pub(crate) fn from_obj_unchecked(obj: PyObjectRef) -> Self {
710727
PyRef {
711728
obj,
712729
_payload: PhantomData,
@@ -747,7 +764,7 @@ where
747764
{
748765
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
749766
if objtype::isinstance(&obj, &T::class(vm)) {
750-
PyRef::new_ref(obj, vm)
767+
PyRef::from_obj(obj, vm)
751768
} else {
752769
let class = T::class(vm);
753770
let expected_type = vm.to_pystr(&class)?;
@@ -1084,6 +1101,12 @@ impl<T> IntoPyObject for PyRef<T> {
10841101
}
10851102
}
10861103

1104+
impl<T> IntoPyObject for &PyRef<T> {
1105+
fn into_pyobject(self, _vm: &VirtualMachine) -> PyResult {
1106+
Ok(self.obj.clone())
1107+
}
1108+
}
1109+
10871110
impl IntoPyObject for PyCallable {
10881111
fn into_pyobject(self, _vm: &VirtualMachine) -> PyResult {
10891112
Ok(self.into_object())
@@ -1145,7 +1168,7 @@ where
11451168
where
11461169
T: PyValue,
11471170
{
1148-
PyRef::new_ref_unchecked(self as PyObjectRef)
1171+
PyRef::from_obj_unchecked(self as PyObjectRef)
11491172
}
11501173
}
11511174

@@ -1210,7 +1233,7 @@ pub trait PyValue: fmt::Debug + Send + Sync + Sized + 'static {
12101233
} else {
12111234
Some(vm.ctx.new_dict())
12121235
};
1213-
PyRef::new_ref(PyObject::new(self, cls, dict), vm)
1236+
PyRef::from_obj(PyObject::new(self, cls, dict), vm)
12141237
} else {
12151238
let subtype = vm.to_str(&cls.obj)?;
12161239
let basetype = vm.to_str(&class.obj)?;
@@ -1219,7 +1242,7 @@ pub trait PyValue: fmt::Debug + Send + Sync + Sized + 'static {
12191242
}
12201243

12211244
fn into_ref_with_type_unchecked(self, cls: PyClassRef, dict: Option<PyDictRef>) -> PyRef<Self> {
1222-
PyRef::new_ref_unchecked(PyObject::new(self, cls, dict))
1245+
PyRef::from_obj_unchecked(PyObject::new(self, cls, dict))
12231246
}
12241247
}
12251248

vm/src/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,8 @@ fn init_type_hierarchy() -> (PyClassRef, PyClassRef) {
338338
type_type,
339339
);
340340

341-
let type_type = PyClassRef::new_ref_unchecked(Arc::from_raw(type_type_ptr));
342-
let object_type = PyClassRef::new_ref_unchecked(Arc::from_raw(object_type_ptr));
341+
let type_type = PyClassRef::from_obj_unchecked(Arc::from_raw(type_type_ptr));
342+
let object_type = PyClassRef::from_obj_unchecked(Arc::from_raw(object_type_ptr));
343343

344344
(*type_type_ptr).payload.mro = vec![object_type.clone()];
345345
(*type_type_ptr).payload.bases = vec![object_type.clone()];

vm/src/vm.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,13 @@ impl VirtualMachine {
14831483
attr_name: impl TryIntoRef<PyString>,
14841484
attr_value: impl Into<PyObjectRef>,
14851485
) -> PyResult<()> {
1486+
// let attr_name = attr_name.try_into_ref(self)?;
1487+
// let value = attr_value.into();
1488+
// let dict = module.dict().expect("module doesn't have dict");
1489+
// if let Ok(module_name) = dict.get_item("__name__", self) {
1490+
// let _ = self.set_attr(&value, "__module__", module_name);
1491+
// }
1492+
// dict.set_item(&attr_name, value, self)?;
14861493
let val = attr_value.into();
14871494
objobject::setattr(module.clone(), attr_name.try_into_ref(self)?, val, self)
14881495
}

0 commit comments

Comments
 (0)