Skip to content

Commit 8424a73

Browse files
committed
type constructor
1 parent 2bf7a4a commit 8424a73

File tree

1 file changed

+103
-98
lines changed

1 file changed

+103
-98
lines changed

vm/src/builtins/type.rs

Lines changed: 103 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ use crate::{
2323
identifier,
2424
object::{Traverse, TraverseFn},
2525
protocol::{PyIterReturn, PyMappingMethods, PyNumberMethods, PySequenceMethods},
26-
types::{AsNumber, Callable, GetAttr, PyTypeFlags, PyTypeSlots, Representable, SetAttr},
26+
types::{
27+
AsNumber, Callable, Constructor, GetAttr, PyTypeFlags, PyTypeSlots, Representable, SetAttr,
28+
},
2729
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
2830
VirtualMachine,
2931
};
@@ -470,7 +472,7 @@ impl Py<PyType> {
470472
}
471473

472474
#[pyclass(
473-
with(Py, GetAttr, SetAttr, Callable, AsNumber, Representable),
475+
with(Py, Constructor, GetAttr, SetAttr, Callable, AsNumber, Representable),
474476
flags(BASETYPE)
475477
)]
476478
impl PyType {
@@ -728,8 +730,66 @@ impl PyType {
728730
or_(zelf, other, vm)
729731
}
730732

731-
#[pyslot]
732-
fn slot_new(metatype: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
733+
#[pygetset(magic)]
734+
fn dict(zelf: PyRef<Self>) -> PyMappingProxy {
735+
PyMappingProxy::from(zelf)
736+
}
737+
738+
#[pygetset(magic, setter)]
739+
fn set_dict(&self, _value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
740+
Err(vm.new_not_implemented_error(
741+
"Setting __dict__ attribute on a type isn't yet implemented".to_owned(),
742+
))
743+
}
744+
745+
fn check_set_special_type_attr(
746+
&self,
747+
_value: &PyObject,
748+
name: &PyStrInterned,
749+
vm: &VirtualMachine,
750+
) -> PyResult<()> {
751+
if self.slots.flags.has_feature(PyTypeFlags::IMMUTABLETYPE) {
752+
return Err(vm.new_type_error(format!(
753+
"cannot set '{}' attribute of immutable type '{}'",
754+
name,
755+
self.slot_name()
756+
)));
757+
}
758+
Ok(())
759+
}
760+
761+
#[pygetset(magic, setter)]
762+
fn set_name(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
763+
self.check_set_special_type_attr(&value, identifier!(vm, __name__), vm)?;
764+
let name = value.downcast::<PyStr>().map_err(|value| {
765+
vm.new_type_error(format!(
766+
"can only assign string to {}.__name__, not '{}'",
767+
self.slot_name(),
768+
value.class().slot_name(),
769+
))
770+
})?;
771+
if name.as_str().as_bytes().contains(&0) {
772+
return Err(vm.new_value_error("type name must not contain null characters".to_owned()));
773+
}
774+
775+
*self.heaptype_ext.as_ref().unwrap().name.write() = name;
776+
777+
Ok(())
778+
}
779+
780+
#[pygetset(magic)]
781+
fn text_signature(&self) -> Option<String> {
782+
self.slots
783+
.doc
784+
.and_then(|doc| get_text_signature_from_internal_doc(&self.name(), doc))
785+
.map(|signature| signature.to_string())
786+
}
787+
}
788+
789+
impl Constructor for PyType {
790+
type Args = FuncArgs;
791+
792+
fn py_new(metatype: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
733793
vm_trace!("type.__new__ {:?}", args);
734794

735795
let is_type_type = metatype.is(vm.ctx.types.type_type);
@@ -976,100 +1036,6 @@ impl PyType {
9761036

9771037
Ok(typ.into())
9781038
}
979-
980-
#[pygetset(magic)]
981-
fn dict(zelf: PyRef<Self>) -> PyMappingProxy {
982-
PyMappingProxy::from(zelf)
983-
}
984-
985-
#[pygetset(magic, setter)]
986-
fn set_dict(&self, _value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
987-
Err(vm.new_not_implemented_error(
988-
"Setting __dict__ attribute on a type isn't yet implemented".to_owned(),
989-
))
990-
}
991-
992-
fn check_set_special_type_attr(
993-
&self,
994-
_value: &PyObject,
995-
name: &PyStrInterned,
996-
vm: &VirtualMachine,
997-
) -> PyResult<()> {
998-
if self.slots.flags.has_feature(PyTypeFlags::IMMUTABLETYPE) {
999-
return Err(vm.new_type_error(format!(
1000-
"cannot set '{}' attribute of immutable type '{}'",
1001-
name,
1002-
self.slot_name()
1003-
)));
1004-
}
1005-
Ok(())
1006-
}
1007-
1008-
#[pygetset(magic, setter)]
1009-
fn set_name(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
1010-
self.check_set_special_type_attr(&value, identifier!(vm, __name__), vm)?;
1011-
let name = value.downcast::<PyStr>().map_err(|value| {
1012-
vm.new_type_error(format!(
1013-
"can only assign string to {}.__name__, not '{}'",
1014-
self.slot_name(),
1015-
value.class().slot_name(),
1016-
))
1017-
})?;
1018-
if name.as_str().as_bytes().contains(&0) {
1019-
return Err(vm.new_value_error("type name must not contain null characters".to_owned()));
1020-
}
1021-
1022-
*self.heaptype_ext.as_ref().unwrap().name.write() = name;
1023-
1024-
Ok(())
1025-
}
1026-
1027-
#[pygetset(magic)]
1028-
fn text_signature(&self) -> Option<String> {
1029-
self.slots
1030-
.doc
1031-
.and_then(|doc| get_text_signature_from_internal_doc(&self.name(), doc))
1032-
.map(|signature| signature.to_string())
1033-
}
1034-
}
1035-
1036-
#[pyclass]
1037-
impl Py<PyType> {
1038-
#[pygetset(name = "__mro__")]
1039-
fn get_mro(&self) -> PyTuple {
1040-
let elements: Vec<PyObjectRef> = self.mro_map_collect(|x| x.as_object().to_owned());
1041-
PyTuple::new_unchecked(elements.into_boxed_slice())
1042-
}
1043-
1044-
#[pymethod(magic)]
1045-
fn dir(&self) -> PyList {
1046-
let attributes: Vec<PyObjectRef> = self
1047-
.get_attributes()
1048-
.into_iter()
1049-
.map(|(k, _)| k.to_object())
1050-
.collect();
1051-
PyList::from(attributes)
1052-
}
1053-
1054-
#[pymethod(magic)]
1055-
fn instancecheck(&self, obj: PyObjectRef) -> bool {
1056-
obj.fast_isinstance(self)
1057-
}
1058-
1059-
#[pymethod(magic)]
1060-
fn subclasscheck(&self, subclass: PyTypeRef) -> bool {
1061-
subclass.fast_issubclass(self)
1062-
}
1063-
1064-
#[pyclassmethod(magic)]
1065-
fn subclasshook(_args: FuncArgs, vm: &VirtualMachine) -> PyObjectRef {
1066-
vm.ctx.not_implemented()
1067-
}
1068-
1069-
#[pymethod]
1070-
fn mro(&self) -> Vec<PyObjectRef> {
1071-
self.mro_map_collect(|cls| cls.to_owned().into())
1072-
}
10731039
}
10741040

10751041
const SIGNATURE_END_MARKER: &str = ")\n--\n\n";
@@ -1143,6 +1109,45 @@ impl GetAttr for PyType {
11431109
}
11441110
}
11451111

1112+
#[pyclass]
1113+
impl Py<PyType> {
1114+
#[pygetset(name = "__mro__")]
1115+
fn get_mro(&self) -> PyTuple {
1116+
let elements: Vec<PyObjectRef> = self.mro_map_collect(|x| x.as_object().to_owned());
1117+
PyTuple::new_unchecked(elements.into_boxed_slice())
1118+
}
1119+
1120+
#[pymethod(magic)]
1121+
fn dir(&self) -> PyList {
1122+
let attributes: Vec<PyObjectRef> = self
1123+
.get_attributes()
1124+
.into_iter()
1125+
.map(|(k, _)| k.to_object())
1126+
.collect();
1127+
PyList::from(attributes)
1128+
}
1129+
1130+
#[pymethod(magic)]
1131+
fn instancecheck(&self, obj: PyObjectRef) -> bool {
1132+
obj.fast_isinstance(self)
1133+
}
1134+
1135+
#[pymethod(magic)]
1136+
fn subclasscheck(&self, subclass: PyTypeRef) -> bool {
1137+
subclass.fast_issubclass(self)
1138+
}
1139+
1140+
#[pyclassmethod(magic)]
1141+
fn subclasshook(_args: FuncArgs, vm: &VirtualMachine) -> PyObjectRef {
1142+
vm.ctx.not_implemented()
1143+
}
1144+
1145+
#[pymethod]
1146+
fn mro(&self) -> Vec<PyObjectRef> {
1147+
self.mro_map_collect(|cls| cls.to_owned().into())
1148+
}
1149+
}
1150+
11461151
impl SetAttr for PyType {
11471152
fn setattro(
11481153
zelf: &Py<Self>,

0 commit comments

Comments
 (0)