Clean up TypeProtocol

This commit is contained in:
Joey Hain
2019-03-25 19:18:01 -07:00
parent 17b816fbf8
commit cc4f3fdb40
20 changed files with 101 additions and 109 deletions

View File

@@ -88,7 +88,7 @@ fn builtin_bin(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
fn builtin_callable(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(obj, None)]);
let is_callable = objtype::class_has_attr(&obj.type_pyref(), "__call__");
let is_callable = objtype::class_has_attr(&obj.class(), "__call__");
Ok(vm.new_bool(is_callable))
}
@@ -240,7 +240,7 @@ fn make_scope(
} else if vm.isinstance(arg, &dict_type)? {
Some(arg)
} else {
let arg_typ = arg.typ();
let arg_typ = arg.class();
let actual_type = vm.to_pystr(&arg_typ)?;
let expected_type_name = vm.to_pystr(&dict_type)?;
return Err(vm.new_type_error(format!(
@@ -368,7 +368,7 @@ fn builtin_len(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(value) => vm.invoke(value, PyFuncArgs::default()),
Err(..) => Err(vm.new_type_error(format!(
"object of type '{}' has no method {:?}",
objtype::get_type_name(&obj.typ()),
objtype::get_type_name(&obj.class()),
len_method_name
))),
}
@@ -607,7 +607,7 @@ fn builtin_reversed(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
// TODO: fallback to using __len__ and __getitem__, if object supports sequence protocol
Err(..) => Err(vm.new_type_error(format!(
"'{}' object is not reversible",
objtype::get_type_name(&obj.typ()),
objtype::get_type_name(&obj.class()),
))),
}
}
@@ -802,9 +802,9 @@ pub fn builtin_build_class_(vm: &VirtualMachine, mut args: PyFuncArgs) -> PyResu
};
for base in bases.clone() {
if objtype::issubclass(&base.type_pyref(), &metaclass) {
metaclass = base.type_pyref();
} else if !objtype::issubclass(&metaclass, &base.type_pyref()) {
if objtype::issubclass(&base.class(), &metaclass) {
metaclass = base.class();
} else if !objtype::issubclass(&metaclass, &base.class()) {
return Err(vm.new_type_error("metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases".to_string()));
}
}

View File

@@ -68,7 +68,7 @@ fn exception_str(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
args,
required = [(exc, Some(vm.ctx.exceptions.exception_type.clone()))]
);
let type_name = objtype::get_type_name(&exc.typ());
let type_name = objtype::get_type_name(&exc.class());
let msg = if let Ok(m) = vm.get_attribute(exc.clone(), "msg") {
match vm.to_pystr(&m) {
Ok(msg) => msg,

View File

@@ -949,7 +949,7 @@ impl Frame {
// let args = PyFuncArgs::default();
// TODO: what happens when we got an error during handling exception?
let args = if let Some(exc) = exc {
let exc_type = exc.typ();
let exc_type = exc.class().into_object();
let exc_val = exc.clone();
let exc_tb = vm.ctx.none(); // TODO: retrieve traceback?
vec![exc_type, exc_val, exc_tb]
@@ -1093,7 +1093,7 @@ impl Frame {
Ok(found) => Ok(found),
Err(_) => Err(vm.new_type_error(format!(
"{} has no __contains__ method",
objtype::get_type_name(&haystack.typ())
objtype::get_type_name(&haystack.class())
))),
}
}
@@ -1103,7 +1103,7 @@ impl Frame {
Ok(found) => Ok(vm.ctx.new_bool(!objbool::get_value(&found))),
Err(_) => Err(vm.new_type_error(format!(
"{} has no __contains__ method",
objtype::get_type_name(&haystack.typ())
objtype::get_type_name(&haystack.class())
))),
}
}

View File

@@ -99,7 +99,7 @@ impl PyFuncArgs {
Ok(Some(kwarg))
} else {
let expected_ty_name = vm.to_pystr(&ty)?;
let actual_ty_name = vm.to_pystr(&kwarg.typ())?;
let actual_ty_name = vm.to_pystr(&kwarg.class())?;
Err(vm.new_type_error(format!(
"argument of type {} is required for named parameter `{}` (got: {})",
expected_ty_name, key, actual_ty_name

View File

@@ -20,7 +20,7 @@ macro_rules! type_check {
let arg = &$args.args[$arg_count];
if !$crate::obj::objtype::isinstance(arg, &expected_type) {
let arg_typ = arg.typ();
let arg_typ = arg.class();
let expected_type_name = $vm.to_pystr(&expected_type)?;
let actual_type = $vm.to_pystr(&arg_typ)?;
return Err($vm.new_type_error(format!(

View File

@@ -190,7 +190,7 @@ impl PyFloatRef {
}
}
} else {
let type_name = objtype::get_type_name(&arg.typ());
let type_name = objtype::get_type_name(&arg.class());
return Err(vm.new_type_error(format!("can't convert {} to float", type_name)));
};
PyFloat { value }.into_ref_with_type(vm, cls)

View File

@@ -76,7 +76,7 @@ fn bind_method(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
required = [(function, None), (obj, None), (cls, None)]
);
if obj.is(&vm.get_none()) && !cls.is(&obj.typ()) {
if obj.is(&vm.get_none()) && !cls.is(&obj.class()) {
Ok(function.clone())
} else {
Ok(vm.ctx.new_bound_method(function.clone(), obj.clone()))

View File

@@ -213,8 +213,8 @@ impl PyIntRef {
if !objtype::isinstance(&other, &vm.ctx.int_type()) {
return Err(vm.new_type_error(format!(
"unsupported operand type(s) for << '{}' and '{}'",
objtype::get_type_name(&self.as_object().typ()),
objtype::get_type_name(&other.typ())
objtype::get_type_name(&self.as_object().class()),
objtype::get_type_name(&other.class())
)));
}
@@ -236,8 +236,8 @@ impl PyIntRef {
if !objtype::isinstance(&other, &vm.ctx.int_type()) {
return Err(vm.new_type_error(format!(
"unsupported operand type(s) for >> '{}' and '{}'",
objtype::get_type_name(&self.as_object().typ()),
objtype::get_type_name(&other.typ())
objtype::get_type_name(&self.as_object().class()),
objtype::get_type_name(&other.class())
)));
}
@@ -420,7 +420,7 @@ pub fn to_int(vm: &VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult<Big
}
}
} else {
let type_name = objtype::get_type_name(&obj.typ());
let type_name = objtype::get_type_name(&obj.class());
return Err(vm.new_type_error(format!(
"int() argument must be a string or a number, not '{}'",
type_name

View File

@@ -21,7 +21,7 @@ use crate::obj::objtype::PyClassRef;
*/
pub fn get_iter(vm: &VirtualMachine, iter_target: &PyObjectRef) -> PyResult {
vm.call_method(iter_target, "__iter__", vec![])
// let type_str = objstr::get_value(&vm.to_str(iter_target.typ()).unwrap());
// let type_str = objstr::get_value(&vm.to_str(iter_target.class()).unwrap());
// let type_error = vm.new_type_error(format!("Cannot iterate over {}", type_str));
// return Err(type_error);
}

View File

@@ -12,7 +12,7 @@ pub type PyNoneRef = PyRef<PyNone>;
impl PyValue for PyNone {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.ctx.none().type_pyref()
vm.ctx.none().class()
}
}
@@ -44,7 +44,7 @@ impl PyNoneRef {
fn get_attribute(self, name: PyStringRef, vm: &VirtualMachine) -> PyResult {
trace!("None.__getattribute__({:?}, {:?})", self, name);
let cls = self.typ();
let cls = self.class();
// Properties use a comparision with None to determine if they are either invoked by am
// instance binding or a class binding. But if the object itself is None then this detection
@@ -69,7 +69,7 @@ impl PyNoneRef {
}
if let Some(attr) = class_get_attr(&cls, &name.value) {
let attr_class = attr.type_pyref();
let attr_class = attr.class();
if class_has_attr(&attr_class, "__set__") {
if let Some(get_func) = class_get_attr(&attr_class, "__get__") {
return call_descriptor(
@@ -88,7 +88,7 @@ impl PyNoneRef {
// Ok(obj_attr)
// } else
if let Some(attr) = class_get_attr(&cls, &name.value) {
let attr_class = attr.type_pyref();
let attr_class = attr.class();
if let Some(get_func) = class_get_attr(&attr_class, "__get__") {
call_descriptor(attr, get_func, self.into_object(), cls.into_object(), vm)
} else {
@@ -107,7 +107,7 @@ fn none_new(_: PyClassRef, vm: &VirtualMachine) -> PyNoneRef {
}
pub fn init(context: &PyContext) {
extend_class!(context, &context.none.typ(), {
extend_class!(context, &context.none.class(), {
"__new__" => context.new_rustfunc(none_new),
"__repr__" => context.new_rustfunc(PyNoneRef::repr),
"__bool__" => context.new_rustfunc(PyNoneRef::bool),

View File

@@ -104,10 +104,10 @@ fn object_setattr(
vm: &VirtualMachine,
) -> PyResult<()> {
trace!("object.__setattr__({:?}, {}, {:?})", obj, attr_name, value);
let cls = obj.type_pyref();
let cls = obj.class();
if let Some(attr) = objtype::class_get_attr(&cls, &attr_name.value) {
if let Some(descriptor) = objtype::class_get_attr(&attr.type_pyref(), "__set__") {
if let Some(descriptor) = objtype::class_get_attr(&attr.class(), "__set__") {
return vm
.invoke(descriptor, vec![attr, obj.clone(), value])
.map(|_| ());
@@ -118,7 +118,7 @@ fn object_setattr(
dict.set_item(&vm.ctx, &attr_name.value, value);
Ok(())
} else {
let type_name = objtype::get_type_name(obj.type_ref());
let type_name = objtype::get_type_name(&obj.class());
Err(vm.new_attribute_error(format!(
"'{}' object has no attribute '{}'",
type_name, &attr_name.value
@@ -127,10 +127,10 @@ fn object_setattr(
}
fn object_delattr(obj: PyObjectRef, attr_name: PyStringRef, vm: &VirtualMachine) -> PyResult<()> {
let cls = obj.type_pyref();
let cls = obj.class();
if let Some(attr) = objtype::class_get_attr(&cls, &attr_name.value) {
if let Some(descriptor) = objtype::class_get_attr(&attr.type_pyref(), "__delete__") {
if let Some(descriptor) = objtype::class_get_attr(&attr.class(), "__delete__") {
return vm.invoke(descriptor, vec![attr, obj.clone()]).map(|_| ());
}
}
@@ -139,7 +139,7 @@ fn object_delattr(obj: PyObjectRef, attr_name: PyStringRef, vm: &VirtualMachine)
dict.del_item(&attr_name.value);
Ok(())
} else {
let type_name = objtype::get_type_name(obj.type_ref());
let type_name = objtype::get_type_name(&obj.class());
Err(vm.new_attribute_error(format!(
"'{}' object has no attribute '{}'",
type_name, &attr_name.value
@@ -154,7 +154,7 @@ fn object_str(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
fn object_repr(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(obj, Some(vm.ctx.object()))]);
let type_name = objtype::get_type_name(&obj.typ());
let type_name = objtype::get_type_name(&obj.class());
let address = obj.get_id();
Ok(vm.new_str(format!("<{} object at 0x{:x}>", type_name, address)))
}
@@ -216,7 +216,7 @@ fn object_init(vm: &VirtualMachine, _args: PyFuncArgs) -> PyResult {
}
fn object_class(obj: PyObjectRef, _vm: &VirtualMachine) -> PyObjectRef {
obj.typ()
obj.class().into_object()
}
fn object_class_setter(
@@ -224,7 +224,7 @@ fn object_class_setter(
_value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult {
let type_repr = vm.to_pystr(&instance.typ())?;
let type_repr = vm.to_pystr(&instance.class())?;
Err(vm.new_type_error(format!("can't change class of type '{}'", type_repr)))
}
@@ -247,10 +247,10 @@ fn object_getattribute(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
);
let name = objstr::get_value(&name_str);
trace!("object.__getattribute__({:?}, {:?})", obj, name);
let cls = obj.type_pyref();
let cls = obj.class();
if let Some(attr) = objtype::class_get_attr(&cls, &name) {
let attr_class = attr.type_pyref();
let attr_class = attr.class();
if objtype::class_has_attr(&attr_class, "__set__") {
if let Some(descriptor) = objtype::class_get_attr(&attr_class, "__get__") {
return vm.invoke(descriptor, vec![attr, obj.clone(), cls.into_object()]);
@@ -279,7 +279,7 @@ fn object_getattr(obj: &PyObjectRef, attr_name: &str) -> Option<PyObjectRef> {
pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes {
// Get class attributes:
let mut attributes = objtype::get_attributes(obj.type_pyref());
let mut attributes = objtype::get_attributes(obj.class());
// Get instance attributes:
if let Some(dict) = &obj.dict {

View File

@@ -6,7 +6,9 @@ use crate::function::IntoPyNativeFunc;
use crate::function::OptionalArg;
use crate::obj::objstr::PyStringRef;
use crate::obj::objtype::PyClassRef;
use crate::pyobject::{IdProtocol, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue};
use crate::pyobject::{
IdProtocol, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::VirtualMachine;
/// Read-only property, doesn't have __set__ or __delete__
@@ -137,7 +139,7 @@ impl PyPropertyRef {
setter: self.setter.clone(),
deleter: self.deleter.clone(),
}
.into_ref_with_type(vm, self.typ())
.into_ref_with_type(vm, TypeProtocol::class(&self))
}
fn setter(self, setter: Option<PyObjectRef>, vm: &VirtualMachine) -> PyResult<Self> {
@@ -146,7 +148,7 @@ impl PyPropertyRef {
setter: setter.or_else(|| self.setter.clone()),
deleter: self.deleter.clone(),
}
.into_ref_with_type(vm, self.typ())
.into_ref_with_type(vm, TypeProtocol::class(&self))
}
fn deleter(self, deleter: Option<PyObjectRef>, vm: &VirtualMachine) -> PyResult<Self> {
@@ -155,7 +157,7 @@ impl PyPropertyRef {
setter: self.setter.clone(),
deleter: deleter.or_else(|| self.deleter.clone()),
}
.into_ref_with_type(vm, self.typ())
.into_ref_with_type(vm, TypeProtocol::class(&self))
}
}

View File

@@ -163,13 +163,13 @@ pub fn get_item(
if sequence.payload::<PyList>().is_some() {
Ok(PyObject::new(
PyList::from(elements.to_vec().get_slice_items(vm, &subscript)?),
sequence.type_pyref(),
sequence.class(),
None,
))
} else if sequence.payload::<PyTuple>().is_some() {
Ok(PyObject::new(
PyTuple::from(elements.to_vec().get_slice_items(vm, &subscript)?),
sequence.type_pyref(),
sequence.class(),
None,
))
} else {

View File

@@ -231,16 +231,16 @@ fn set_new(cls: PyClassRef, iterable: OptionalArg<PyObjectRef>, vm: &VirtualMach
fn set_len(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
trace!("set.len called with: {:?}", args);
arg_check!(vm, args, required = [(s, None)]);
validate_set_or_frozenset(vm, s.type_pyref())?;
validate_set_or_frozenset(vm, s.class())?;
let elements = get_elements(s);
Ok(vm.context().new_int(elements.len()))
}
fn set_copy(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
trace!("set.copy called with: {:?}", obj);
validate_set_or_frozenset(vm, obj.type_pyref())?;
validate_set_or_frozenset(vm, obj.class())?;
let elements = get_elements(&obj).clone();
create_set(vm, elements, obj.type_pyref())
create_set(vm, elements, obj.class())
}
fn set_repr(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -265,7 +265,7 @@ fn set_repr(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
pub fn set_contains(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(set, None), (needle, None)]);
validate_set_or_frozenset(vm, set.type_pyref())?;
validate_set_or_frozenset(vm, set.class())?;
for element in get_elements(set).iter() {
match vm._eq(needle.clone(), element.1.clone()) {
Ok(value) => {
@@ -333,8 +333,8 @@ fn set_compare_inner(
) -> PyResult {
arg_check!(vm, args, required = [(zelf, None), (other, None)]);
validate_set_or_frozenset(vm, zelf.type_pyref())?;
validate_set_or_frozenset(vm, other.type_pyref())?;
validate_set_or_frozenset(vm, zelf.class())?;
validate_set_or_frozenset(vm, other.class())?;
let get_zelf = |swap: bool| -> &PyObjectRef {
if swap {
@@ -370,13 +370,13 @@ fn set_compare_inner(
}
fn set_union(zelf: PyObjectRef, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
validate_set_or_frozenset(vm, zelf.type_pyref())?;
validate_set_or_frozenset(vm, other.type_pyref())?;
validate_set_or_frozenset(vm, zelf.class())?;
validate_set_or_frozenset(vm, other.class())?;
let mut elements = get_elements(&zelf).clone();
elements.extend(get_elements(&other).clone());
create_set(vm, elements, zelf.type_pyref())
create_set(vm, elements, zelf.class())
}
fn set_intersection(zelf: PyObjectRef, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
@@ -392,8 +392,8 @@ fn set_symmetric_difference(
other: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult {
validate_set_or_frozenset(vm, zelf.type_pyref())?;
validate_set_or_frozenset(vm, other.type_pyref())?;
validate_set_or_frozenset(vm, zelf.class())?;
validate_set_or_frozenset(vm, other.class())?;
let mut elements = HashMap::new();
for element in get_elements(&zelf).iter() {
@@ -410,7 +410,7 @@ fn set_symmetric_difference(
}
}
create_set(vm, elements, zelf.type_pyref())
create_set(vm, elements, zelf.class())
}
enum SetCombineOperation {
@@ -424,8 +424,8 @@ fn set_combine_inner(
vm: &VirtualMachine,
op: SetCombineOperation,
) -> PyResult {
validate_set_or_frozenset(vm, zelf.type_pyref())?;
validate_set_or_frozenset(vm, other.type_pyref())?;
validate_set_or_frozenset(vm, zelf.class())?;
validate_set_or_frozenset(vm, other.class())?;
let mut elements = HashMap::new();
for element in get_elements(&zelf).iter() {
@@ -439,7 +439,7 @@ fn set_combine_inner(
}
}
create_set(vm, elements, zelf.type_pyref())
create_set(vm, elements, zelf.class())
}
fn set_pop(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {

View File

@@ -715,7 +715,7 @@ fn str_format(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
let zelf = &args.args[0];
if !objtype::isinstance(&zelf, &vm.ctx.str_type()) {
let zelf_typ = zelf.typ();
let zelf_typ = zelf.class();
let actual_type = vm.to_pystr(&zelf_typ)?;
return Err(vm.new_type_error(format!(
"descriptor 'format' requires a 'str' object but received a '{}'",
@@ -738,7 +738,7 @@ fn call_object_format(vm: &VirtualMachine, argument: PyObjectRef, format_spec: &
let returned_type = vm.ctx.new_str(format_spec.to_string());
let result = vm.call_method(&argument, "__format__", vec![returned_type])?;
if !objtype::isinstance(&result, &vm.ctx.str_type()) {
let result_type = result.typ();
let result_type = result.class();
let actual_type = vm.to_pystr(&result_type)?;
return Err(vm.new_type_error(format!("__format__ must return a str, not {}", actual_type)));
}
@@ -809,7 +809,7 @@ fn str_new(
OptionalArg::Present(ref input) => vm.to_str(input)?.into_object(),
OptionalArg::Missing => vm.new_str("".to_string()),
};
if string.typ().is(&cls) {
if string.class().is(&cls) {
TryFromObject::try_from_object(vm, string)
} else {
let payload = string.payload::<PyString>().unwrap();

View File

@@ -112,7 +112,7 @@ fn super_new(
// Check type argument:
if !objtype::isinstance(py_type.as_object(), &vm.get_type()) {
let type_name = objtype::get_type_name(py_type.as_object().type_ref());
let type_name = objtype::get_type_name(&py_type.as_object().class());
return Err(vm.new_type_error(format!(
"super() argument 1 must be type, not {}",
type_name

View File

@@ -39,12 +39,6 @@ impl PyValue for PyClass {
}
}
impl TypeProtocol for PyClassRef {
fn type_ref(&self) -> &PyObjectRef {
&self.as_object().type_ref()
}
}
struct IterMro<'a> {
cls: &'a PyClassRef,
offset: Option<usize>,
@@ -117,10 +111,10 @@ impl PyClassRef {
fn getattribute(self, name_ref: PyStringRef, vm: &VirtualMachine) -> PyResult {
let name = &name_ref.value;
trace!("type.__getattribute__({:?}, {:?})", self, name);
let mcl = self.type_pyref();
let mcl = self.class();
if let Some(attr) = class_get_attr(&mcl, &name) {
let attr_class = attr.type_pyref();
let attr_class = attr.class();
if class_has_attr(&attr_class, "__set__") {
if let Some(descriptor) = class_get_attr(&attr_class, "__get__") {
return vm.invoke(
@@ -132,7 +126,7 @@ impl PyClassRef {
}
if let Some(attr) = class_get_attr(&self, &name) {
let attr_class = attr.type_pyref();
let attr_class = attr.class();
if let Some(descriptor) = class_get_attr(&attr_class, "__get__") {
let none = vm.get_none();
return vm.invoke(descriptor, vec![attr, none, self.into_object()]);
@@ -156,8 +150,8 @@ impl PyClassRef {
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<()> {
if let Some(attr) = class_get_attr(&self.type_pyref(), &attr_name.value) {
if let Some(descriptor) = class_get_attr(&attr.type_pyref(), "__set__") {
if let Some(attr) = class_get_attr(&self.class(), &attr_name.value) {
if let Some(descriptor) = class_get_attr(&attr.class(), "__set__") {
vm.invoke(descriptor, vec![attr, self.into_object(), value])?;
return Ok(());
}
@@ -218,7 +212,7 @@ fn _mro(cls: &PyClassRef) -> Vec<PyClassRef> {
/// Determines if `obj` actually an instance of `cls`, this doesn't call __instancecheck__, so only
/// use this if `cls` is known to have not overridden the base __instancecheck__ magic method.
pub fn isinstance(obj: &PyObjectRef, cls: &PyClassRef) -> bool {
issubclass(&obj.type_pyref(), &cls)
issubclass(&obj.class(), &cls)
}
/// Determines if `subclass` is actually a subclass of `cls`, this doesn't call __subclasscheck__,
@@ -229,18 +223,14 @@ pub fn issubclass(subclass: &PyClassRef, cls: &PyClassRef) -> bool {
subclass.is(cls) || mro.iter().any(|c| c.is(cls.as_object()))
}
pub fn get_type_name(typ: &PyObjectRef) -> String {
if let Some(PyClass { name, .. }) = &typ.payload::<PyClass>() {
name.clone()
} else {
panic!("Cannot get type_name of non-type type {:?}", typ);
}
pub fn get_type_name(typ: &PyClassRef) -> String {
typ.name.clone()
}
pub fn type_new(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
debug!("type.__new__ {:?}", args);
if args.args.len() == 2 {
Ok(args.args[1].typ())
Ok(args.args[1].class().into_object())
} else if args.args.len() == 4 {
let (typ, name, bases, dict) = args.bind(vm)?;
type_new_class(vm, typ, name, bases, dict).map(|x| x.into_object())

View File

@@ -88,7 +88,7 @@ impl fmt::Display for PyObject<dyn PyObjectPayload> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::TypeProtocol;
if let Some(PyClass { ref name, .. }) = self.payload::<PyClass>() {
let type_name = objtype::get_type_name(&self.typ());
let type_name = objtype::get_type_name(&self.class());
// We don't have access to a vm, so just assume that if its parent's name
// is type, it's a type
if type_name == "type" {
@@ -101,7 +101,7 @@ impl fmt::Display for PyObject<dyn PyObjectPayload> {
if let Some(PyModule { ref name, .. }) = self.payload::<PyModule>() {
return write!(f, "module '{}'", name);
}
write!(f, "'{}' object", objtype::get_type_name(&self.typ()))
write!(f, "'{}' object", objtype::get_type_name(&self.class()))
}
}
@@ -163,7 +163,7 @@ pub struct PyNotImplemented;
impl PyValue for PyNotImplemented {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.ctx.not_implemented().type_pyref()
vm.ctx.not_implemented().class()
}
}
@@ -772,7 +772,7 @@ impl<T: PyValue> PyRef<T> {
pub fn typ(&self) -> PyClassRef {
PyRef {
obj: self.obj.typ(),
obj: self.obj.class().into_object(),
_payload: PhantomData,
}
}
@@ -802,7 +802,7 @@ where
} else {
let class = T::class(vm);
let expected_type = vm.to_pystr(&class)?;
let actual_type = vm.to_pystr(&obj.typ())?;
let actual_type = vm.to_pystr(&obj.class())?;
Err(vm.new_type_error(format!(
"Expected type {}, not {}",
expected_type, actual_type,
@@ -877,18 +877,12 @@ impl<T: PyObjectPayload> IdProtocol for PyRef<T> {
}
pub trait TypeProtocol {
fn typ(&self) -> PyObjectRef {
self.type_ref().clone()
}
fn type_pyref(&self) -> PyClassRef {
self.typ().downcast().unwrap()
}
fn type_ref(&self) -> &PyObjectRef;
fn class(&self) -> PyClassRef;
}
impl TypeProtocol for PyObjectRef {
fn type_ref(&self) -> &PyObjectRef {
(**self).type_ref()
fn class(&self) -> PyClassRef {
(**self).class()
}
}
@@ -896,8 +890,14 @@ impl<T> TypeProtocol for PyObject<T>
where
T: ?Sized + PyObjectPayload,
{
fn type_ref(&self) -> &PyObjectRef {
self.typ.as_object()
fn class(&self) -> PyClassRef {
self.typ.clone()
}
}
impl<T> TypeProtocol for PyRef<T> {
fn class(&self) -> PyClassRef {
self.obj.typ.clone()
}
}
@@ -956,7 +956,7 @@ pub trait BufferProtocol {
impl BufferProtocol for PyObjectRef {
fn readonly(&self) -> bool {
match objtype::get_type_name(&self.typ()).as_ref() {
match objtype::get_type_name(&self.class()).as_ref() {
"bytes" => false,
"bytearray" | "memoryview" => true,
_ => panic!("Bytes-Like type expected not {:?}", self),
@@ -1249,7 +1249,7 @@ where
"must be {} or {}, not {}",
A::class(vm),
B::class(vm),
obj.type_pyref()
obj.class()
))
})
}

View File

@@ -74,7 +74,7 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
} else {
Err(serde::ser::Error::custom(format!(
"Object of type '{:?}' is not serializable",
self.pyobject.typ()
self.pyobject.class()
)))
}
}

View File

@@ -174,8 +174,8 @@ impl VirtualMachine {
b: PyObjectRef,
op: &str,
) -> PyObjectRef {
let a_type_name = objtype::get_type_name(&a.typ());
let b_type_name = objtype::get_type_name(&b.typ());
let a_type_name = objtype::get_type_name(&a.class());
let b_type_name = objtype::get_type_name(&b.class());
self.new_type_error(format!(
"Unsupported operand types for '{}': '{}' and '{}'",
op, a_type_name, b_type_name
@@ -270,7 +270,7 @@ impl VirtualMachine {
pub fn isinstance(&self, obj: &PyObjectRef, cls: &PyClassRef) -> PyResult<bool> {
// cpython first does an exact check on the type, although documentation doesn't state that
// https://github.com/python/cpython/blob/a24107b04c1277e3c1105f98aff5bfa3a98b33a0/Objects/abstract.c#L2408
if Rc::ptr_eq(&obj.typ(), cls.as_object()) {
if Rc::ptr_eq(&obj.class().into_object(), cls.as_object()) {
Ok(true)
} else {
let ret = self.call_method(cls.as_object(), "__instancecheck__", vec![obj.clone()])?;
@@ -286,10 +286,10 @@ impl VirtualMachine {
}
pub fn call_get_descriptor(&self, attr: PyObjectRef, obj: PyObjectRef) -> PyResult {
let attr_class = attr.type_pyref();
let attr_class = attr.class();
if let Some(descriptor) = objtype::class_get_attr(&attr_class, "__get__") {
let cls = obj.typ();
self.invoke(descriptor, vec![attr, obj.clone(), cls])
let cls = obj.class();
self.invoke(descriptor, vec![attr, obj.clone(), cls.into_object()])
} else {
Ok(attr)
}
@@ -300,7 +300,7 @@ impl VirtualMachine {
T: Into<PyFuncArgs>,
{
// This is only used in the vm for magic methods, which use a greatly simplified attribute lookup.
let cls = obj.type_pyref();
let cls = obj.class();
match objtype::class_get_attr(&cls, method_name) {
Some(func) => {
trace!(
@@ -583,7 +583,7 @@ impl VirtualMachine {
// get_method should be used for internal access to magic methods (by-passing
// the full getattribute look-up.
pub fn get_method(&self, obj: PyObjectRef, method_name: &str) -> PyResult {
let cls = obj.type_pyref();
let cls = obj.class();
match objtype::class_get_attr(&cls, method_name) {
Some(method) => self.call_get_descriptor(method, obj.clone()),
None => Err(self.new_type_error(format!("{} has no method {:?}", obj, method_name))),