Skip to content

Commit c1d5ce7

Browse files
committed
Change isinstance/issubclass to accept PyClassRef instead of PyCObject.
Also changed PyValue::class to return a PyClassRef.
1 parent b7fa08e commit c1d5ce7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+371
-362
lines changed

vm/src/builtins.rs

Lines changed: 47 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ use crate::obj::objdict;
1515
use crate::obj::objint;
1616
use crate::obj::objiter;
1717
use crate::obj::objstr::{self, PyStringRef};
18-
use crate::obj::objtype;
18+
use crate::obj::objtype::{self, PyClassRef};
1919

2020
use crate::frame::Scope;
2121
use crate::function::{Args, OptionalArg, PyFuncArgs};
22-
use crate::pyobject::{DictProtocol, IdProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol};
22+
use crate::pyobject::{
23+
DictProtocol, IdProtocol, PyContext, PyObjectRef, PyResult, TryFromObject, TypeProtocol,
24+
};
2325
use crate::vm::VirtualMachine;
2426

2527
#[cfg(not(target_arch = "wasm32"))]
@@ -295,7 +297,7 @@ fn builtin_format(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
295297
}
296298

297299
fn catch_attr_exception<T>(ex: PyObjectRef, default: T, vm: &VirtualMachine) -> PyResult<T> {
298-
if objtype::isinstance(&ex, vm.ctx.exceptions.attribute_error.as_object()) {
300+
if objtype::isinstance(&ex, &vm.ctx.exceptions.attribute_error) {
299301
Ok(default)
300302
} else {
301303
Err(ex)
@@ -357,15 +359,8 @@ fn builtin_id(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
357359

358360
// builtin_input
359361

360-
fn builtin_isinstance(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
361-
arg_check!(
362-
vm,
363-
args,
364-
required = [(obj, None), (typ, Some(vm.get_type()))]
365-
);
366-
367-
let isinstance = vm.isinstance(obj, typ)?;
368-
Ok(vm.new_bool(isinstance))
362+
fn builtin_isinstance(obj: PyObjectRef, typ: PyClassRef, vm: &VirtualMachine) -> PyResult<bool> {
363+
vm.isinstance(&obj, &typ)
369364
}
370365

371366
fn builtin_issubclass(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -510,7 +505,7 @@ fn builtin_next(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
510505
match vm.call_method(iterator, "__next__", vec![]) {
511506
Ok(value) => Ok(value),
512507
Err(value) => {
513-
if objtype::isinstance(&value, vm.ctx.exceptions.stop_iteration.as_object()) {
508+
if objtype::isinstance(&value, &vm.ctx.exceptions.stop_iteration) {
514509
match default_value {
515510
None => Err(value),
516511
Some(value) => Ok(value.clone()),
@@ -719,64 +714,64 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
719714
"all" => ctx.new_rustfunc(builtin_all),
720715
"any" => ctx.new_rustfunc(builtin_any),
721716
"bin" => ctx.new_rustfunc(builtin_bin),
722-
"bool" => ctx.bool_type(),
723-
"bytearray" => ctx.bytearray_type(),
724-
"bytes" => ctx.bytes_type(),
717+
"bool" => ctx.bool_type().into_object(),
718+
"bytearray" => ctx.bytearray_type().into_object(),
719+
"bytes" => ctx.bytes_type().into_object(),
725720
"callable" => ctx.new_rustfunc(builtin_callable),
726721
"chr" => ctx.new_rustfunc(builtin_chr),
727-
"classmethod" => ctx.classmethod_type(),
722+
"classmethod" => ctx.classmethod_type().into_object(),
728723
"compile" => ctx.new_rustfunc(builtin_compile),
729-
"complex" => ctx.complex_type(),
724+
"complex" => ctx.complex_type().into_object(),
730725
"delattr" => ctx.new_rustfunc(builtin_delattr),
731-
"dict" => ctx.dict_type(),
726+
"dict" => ctx.dict_type().into_object(),
732727
"divmod" => ctx.new_rustfunc(builtin_divmod),
733728
"dir" => ctx.new_rustfunc(builtin_dir),
734-
"enumerate" => ctx.enumerate_type(),
729+
"enumerate" => ctx.enumerate_type().into_object(),
735730
"eval" => ctx.new_rustfunc(builtin_eval),
736731
"exec" => ctx.new_rustfunc(builtin_exec),
737-
"float" => ctx.float_type(),
738-
"frozenset" => ctx.frozenset_type(),
739-
"filter" => ctx.filter_type(),
732+
"float" => ctx.float_type().into_object(),
733+
"frozenset" => ctx.frozenset_type().into_object(),
734+
"filter" => ctx.filter_type().into_object(),
740735
"format" => ctx.new_rustfunc(builtin_format),
741736
"getattr" => ctx.new_rustfunc(builtin_getattr),
742737
"globals" => ctx.new_rustfunc(builtin_globals),
743738
"hasattr" => ctx.new_rustfunc(builtin_hasattr),
744739
"hash" => ctx.new_rustfunc(builtin_hash),
745740
"hex" => ctx.new_rustfunc(builtin_hex),
746741
"id" => ctx.new_rustfunc(builtin_id),
747-
"int" => ctx.int_type(),
742+
"int" => ctx.int_type().into_object(),
748743
"isinstance" => ctx.new_rustfunc(builtin_isinstance),
749744
"issubclass" => ctx.new_rustfunc(builtin_issubclass),
750745
"iter" => ctx.new_rustfunc(builtin_iter),
751746
"len" => ctx.new_rustfunc(builtin_len),
752-
"list" => ctx.list_type(),
747+
"list" => ctx.list_type().into_object(),
753748
"locals" => ctx.new_rustfunc(builtin_locals),
754-
"map" => ctx.map_type(),
749+
"map" => ctx.map_type().into_object(),
755750
"max" => ctx.new_rustfunc(builtin_max),
756-
"memoryview" => ctx.memoryview_type(),
751+
"memoryview" => ctx.memoryview_type().into_object(),
757752
"min" => ctx.new_rustfunc(builtin_min),
758-
"object" => ctx.object(),
753+
"object" => ctx.object().into_object(),
759754
"oct" => ctx.new_rustfunc(builtin_oct),
760755
"ord" => ctx.new_rustfunc(builtin_ord),
761756
"next" => ctx.new_rustfunc(builtin_next),
762757
"pow" => ctx.new_rustfunc(builtin_pow),
763758
"print" => ctx.new_rustfunc(builtin_print),
764-
"property" => ctx.property_type(),
765-
"range" => ctx.range_type(),
759+
"property" => ctx.property_type().into_object(),
760+
"range" => ctx.range_type().into_object(),
766761
"repr" => ctx.new_rustfunc(builtin_repr),
767762
"reversed" => ctx.new_rustfunc(builtin_reversed),
768763
"round" => ctx.new_rustfunc(builtin_round),
769-
"set" => ctx.set_type(),
764+
"set" => ctx.set_type().into_object(),
770765
"setattr" => ctx.new_rustfunc(builtin_setattr),
771766
"sorted" => ctx.new_rustfunc(builtin_sorted),
772-
"slice" => ctx.slice_type(),
773-
"staticmethod" => ctx.staticmethod_type(),
774-
"str" => ctx.str_type(),
767+
"slice" => ctx.slice_type().into_object(),
768+
"staticmethod" => ctx.staticmethod_type().into_object(),
769+
"str" => ctx.str_type().into_object(),
775770
"sum" => ctx.new_rustfunc(builtin_sum),
776-
"super" => ctx.super_type(),
777-
"tuple" => ctx.tuple_type(),
778-
"type" => ctx.type_type(),
779-
"zip" => ctx.zip_type(),
771+
"super" => ctx.super_type().into_object(),
772+
"tuple" => ctx.tuple_type().into_object(),
773+
"type" => ctx.type_type().into_object(),
774+
"zip" => ctx.zip_type().into_object(),
780775
"__import__" => ctx.new_rustfunc(builtin_import),
781776

782777
// Constants
@@ -813,26 +808,34 @@ pub fn builtin_build_class_(vm: &VirtualMachine, mut args: PyFuncArgs) -> PyResu
813808
let function = args.shift();
814809
let name_arg = args.shift();
815810
let bases = args.args.clone();
816-
let mut metaclass = args.get_kwarg("metaclass", vm.get_type());
811+
let mut metaclass = if let Some(metaclass) = args.get_optional_kwarg("metaclass") {
812+
PyClassRef::try_from_object(vm, metaclass)?
813+
} else {
814+
vm.get_type()
815+
};
817816

818817
for base in bases.clone() {
819-
if objtype::issubclass(&base.typ(), &metaclass) {
820-
metaclass = base.typ();
821-
} else if !objtype::issubclass(&metaclass, &base.typ()) {
818+
if objtype::issubclass(&base.type_pyref(), &metaclass) {
819+
metaclass = base.type_pyref();
820+
} else if !objtype::issubclass(&metaclass, &base.type_pyref()) {
822821
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()));
823822
}
824823
}
825824

826825
let bases = vm.context().new_tuple(bases);
827826

828827
// Prepare uses full __getattribute__ resolution chain.
829-
let prepare = vm.get_attribute(metaclass.clone(), "__prepare__")?;
828+
let prepare = vm.get_attribute(metaclass.clone().into_object(), "__prepare__")?;
830829
let namespace = vm.invoke(prepare, vec![name_arg.clone(), bases.clone()])?;
831830

832831
let cells = vm.new_dict();
833832

834833
vm.invoke_with_locals(function, cells.clone(), namespace.clone())?;
835-
let class = vm.call_method(&metaclass, "__call__", vec![name_arg, bases, namespace])?;
834+
let class = vm.call_method(
835+
metaclass.as_object(),
836+
"__call__",
837+
vec![name_arg, bases, namespace],
838+
)?;
836839
cells.set_item(&vm.ctx, "__class__", class.clone());
837840
Ok(class)
838841
}

vm/src/compile.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use crate::bytecode::{self, CallType, CodeObject, Instruction, Varargs};
99
use crate::error::CompileError;
1010
use crate::obj::objcode;
11+
use crate::obj::objtype::PyClassRef;
1112
use crate::pyobject::{PyObject, PyObjectRef};
1213
use num_complex::Complex64;
1314
use rustpython_parser::{ast, parser};
@@ -26,7 +27,7 @@ pub fn compile(
2627
source: &str,
2728
mode: &Mode,
2829
source_path: String,
29-
code_type: PyObjectRef,
30+
code_type: PyClassRef,
3031
) -> Result<PyObjectRef, CompileError> {
3132
let mut compiler = Compiler::new();
3233
compiler.source_path = Some(source_path);
@@ -49,7 +50,10 @@ pub fn compile(
4950

5051
let code = compiler.pop_code_object();
5152
trace!("Compilation completed: {:?}", code);
52-
Ok(PyObject::new(objcode::PyCode::new(code), code_type))
53+
Ok(PyObject::new(
54+
objcode::PyCode::new(code),
55+
code_type.into_object(),
56+
))
5357
}
5458

5559
pub enum Mode {

vm/src/exceptions.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,7 @@ fn exception_str(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
6666
arg_check!(
6767
vm,
6868
args,
69-
required = [(
70-
exc,
71-
Some(vm.ctx.exceptions.exception_type.clone().into_object())
72-
)]
69+
required = [(exc, Some(vm.ctx.exceptions.exception_type.clone()))]
7370
);
7471
let type_name = objtype::get_type_name(&exc.typ());
7572
let msg = if let Ok(m) = vm.get_attribute(exc.clone(), "msg") {

vm/src/frame.rs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::obj::objlist;
2020
use crate::obj::objslice::PySlice;
2121
use crate::obj::objstr;
2222
use crate::obj::objtype;
23+
use crate::obj::objtype::PyClassRef;
2324
use crate::pyobject::{
2425
DictProtocol, IdProtocol, PyContext, PyObjectRef, PyResult, PyValue, TryFromObject,
2526
TypeProtocol,
@@ -195,7 +196,7 @@ pub struct Frame {
195196
}
196197

197198
impl PyValue for Frame {
198-
fn class(vm: &VirtualMachine) -> PyObjectRef {
199+
fn class(vm: &VirtualMachine) -> PyClassRef {
199200
vm.ctx.frame_type()
200201
}
201202
}
@@ -253,7 +254,7 @@ impl Frame {
253254
// Add an entry in the traceback:
254255
assert!(objtype::isinstance(
255256
&exception,
256-
vm.ctx.exceptions.base_exception_type.as_object()
257+
&vm.ctx.exceptions.base_exception_type
257258
));
258259
let traceback = vm
259260
.get_attribute(exception.clone(), "__traceback__")
@@ -656,29 +657,25 @@ impl Frame {
656657
0 | 2 | 3 => panic!("Not implemented!"),
657658
_ => panic!("Invalid parameter for RAISE_VARARGS, must be between 0 to 3"),
658659
};
659-
if objtype::isinstance(
660-
&exception,
661-
vm.ctx.exceptions.base_exception_type.as_object(),
662-
) {
663-
info!("Exception raised: {:?}", exception);
664-
Err(exception)
665-
} else if objtype::isinstance(&exception, &vm.ctx.type_type())
666-
&& objtype::issubclass(
667-
&exception,
668-
vm.ctx.exceptions.base_exception_type.as_object(),
669-
)
670-
{
671-
let exception = vm.new_empty_exception(exception)?;
660+
if objtype::isinstance(&exception, &vm.ctx.exceptions.base_exception_type) {
672661
info!("Exception raised: {:?}", exception);
673662
Err(exception)
663+
} else if let Ok(exception) = PyClassRef::try_from_object(vm, exception) {
664+
if objtype::issubclass(&exception, &vm.ctx.exceptions.base_exception_type) {
665+
let exception = vm.new_empty_exception(exception)?;
666+
info!("Exception raised: {:?}", exception);
667+
Err(exception)
668+
} else {
669+
let msg = format!(
670+
"Can only raise BaseException derived types, not {}",
671+
exception
672+
);
673+
let type_error_type = vm.ctx.exceptions.type_error.clone();
674+
let type_error = vm.new_exception(type_error_type, msg);
675+
Err(type_error)
676+
}
674677
} else {
675-
let msg = format!(
676-
"Can only raise BaseException derived types, not {}",
677-
exception
678-
);
679-
let type_error_type = vm.ctx.exceptions.type_error.clone();
680-
let type_error = vm.new_exception(type_error_type, msg);
681-
Err(type_error)
678+
Err(vm.new_type_error("exceptions must derive from BaseException".to_string()))
682679
}
683680
}
684681

vm/src/function.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::pyobject::{IntoPyObject, PyObjectRef, PyResult, TryFromObject, TypePr
66
use crate::vm::VirtualMachine;
77

88
use self::OptionalArg::*;
9+
use crate::obj::objtype::PyClassRef;
910

1011
/// The `PyFuncArgs` struct is one of the most used structs then creating
1112
/// a rust function that can be called from python. It holds both positional
@@ -89,7 +90,7 @@ impl PyFuncArgs {
8990
pub fn get_optional_kwarg_with_type(
9091
&self,
9192
key: &str,
92-
ty: PyObjectRef,
93+
ty: PyClassRef,
9394
vm: &VirtualMachine,
9495
) -> Result<Option<PyObjectRef>, PyObjectRef> {
9596
match self.get_optional_kwarg(key) {

vm/src/obj/objbuiltinfunc.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use std::fmt;
22

33
use crate::function::PyNativeFunc;
4-
use crate::pyobject::{PyObjectRef, PyValue};
4+
use crate::obj::objtype::PyClassRef;
5+
use crate::pyobject::PyValue;
56
use crate::vm::VirtualMachine;
67

78
pub struct PyBuiltinFunction {
@@ -10,7 +11,7 @@ pub struct PyBuiltinFunction {
1011
}
1112

1213
impl PyValue for PyBuiltinFunction {
13-
fn class(vm: &VirtualMachine) -> PyObjectRef {
14+
fn class(vm: &VirtualMachine) -> PyClassRef {
1415
vm.ctx.builtin_function_or_method_type()
1516
}
1617
}

vm/src/obj/objbytearray.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ impl PyByteArray {
2929
}
3030

3131
impl PyValue for PyByteArray {
32-
fn class(vm: &VirtualMachine) -> PyObjectRef {
32+
fn class(vm: &VirtualMachine) -> PyClassRef {
3333
vm.ctx.bytearray_type()
3434
}
3535
}

vm/src/obj/objbytes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl Deref for PyBytes {
3434
}
3535

3636
impl PyValue for PyBytes {
37-
fn class(vm: &VirtualMachine) -> PyObjectRef {
37+
fn class(vm: &VirtualMachine) -> PyClassRef {
3838
vm.ctx.bytes_type()
3939
}
4040
}

vm/src/obj/objclassmethod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub struct PyClassMethod {
99
pub type PyClassMethodRef = PyRef<PyClassMethod>;
1010

1111
impl PyValue for PyClassMethod {
12-
fn class(vm: &VirtualMachine) -> PyObjectRef {
12+
fn class(vm: &VirtualMachine) -> PyClassRef {
1313
vm.ctx.classmethod_type()
1414
}
1515
}

vm/src/obj/objcode.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::fmt;
66

77
use crate::bytecode;
88
use crate::function::PyFuncArgs;
9+
use crate::obj::objtype::PyClassRef;
910
use crate::pyobject::{IdProtocol, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol};
1011
use crate::vm::VirtualMachine;
1112

@@ -26,7 +27,7 @@ impl fmt::Debug for PyCode {
2627
}
2728

2829
impl PyValue for PyCode {
29-
fn class(vm: &VirtualMachine) -> PyObjectRef {
30+
fn class(vm: &VirtualMachine) -> PyClassRef {
3031
vm.ctx.code_type()
3132
}
3233
}

0 commit comments

Comments
 (0)