diff --git a/tests/snippets/basic_types.py b/tests/snippets/basic_types.py index 8944b1355..b9dc22b27 100644 --- a/tests/snippets/basic_types.py +++ b/tests/snippets/basic_types.py @@ -25,3 +25,11 @@ assert type(2 / 3) is float x = 1 assert type(x) is int assert type(x - 1) is int + +a = bytes([1, 2, 3]) +print(a) +try: + bytes([object()]) +except TypeError: + pass + diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 13c794d45..d52ae44a9 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -322,6 +322,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef { dict.insert(String::from("all"), ctx.new_rustfunc(builtin_all)); dict.insert(String::from("any"), ctx.new_rustfunc(builtin_any)); dict.insert(String::from("bool"), ctx.bool_type()); + dict.insert(String::from("bytes"), ctx.bytes_type()); dict.insert(String::from("chr"), ctx.new_rustfunc(builtin_chr)); dict.insert(String::from("compile"), ctx.new_rustfunc(builtin_compile)); dict.insert(String::from("dict"), ctx.dict_type()); diff --git a/vm/src/lib.rs b/vm/src/lib.rs index b979ac9b0..a6d8f61de 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -22,9 +22,6 @@ mod frame; mod import; mod obj; mod objbool; -mod objfunction; -mod objobject; -mod objsequence; pub mod pyobject; pub mod stdlib; mod sysmodule; diff --git a/vm/src/obj/mod.rs b/vm/src/obj/mod.rs index 65fd8ee9b..8dfa798ec 100644 --- a/vm/src/obj/mod.rs +++ b/vm/src/obj/mod.rs @@ -1,7 +1,11 @@ +pub mod objbytes; pub mod objdict; pub mod objfloat; +pub mod objfunction; pub mod objint; pub mod objlist; +pub mod objobject; +pub mod objsequence; pub mod objstr; pub mod objtuple; pub mod objtype; diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs new file mode 100644 index 000000000..9ab541425 --- /dev/null +++ b/vm/src/obj/objbytes.rs @@ -0,0 +1,59 @@ +use super::super::pyobject::{ + AttributeProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol, +}; +use super::super::vm::VirtualMachine; +use super::objint; +use super::objlist; +use super::objtype; +// Binary data support + +// Fill bytes class methods: +pub fn init(context: &PyContext) { + let ref bytes_type = context.bytes_type; + bytes_type.set_attr("__init__", context.new_rustfunc(bytes_init)); + bytes_type.set_attr("__str__", context.new_rustfunc(bytes_str)); +} + +// __init__ (store value into objectkind) +fn bytes_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [(zelf, Some(vm.ctx.bytes_type())), (arg, None)] + ); + let val = if objtype::isinstance(arg.clone(), vm.ctx.list_type()) { + let mut data_bytes = vec![]; + for elem in objlist::get_elements(arg) { + let v = match objint::to_int(vm, &elem) { + Ok(int_ref) => int_ref, + Err(err) => return Err(err), + }; + data_bytes.push(v as u8); + } + data_bytes + } else { + return Err(vm.new_type_error("Cannot construct bytes".to_string())); + }; + set_value(zelf, val); + Ok(vm.get_none()) +} + +pub fn get_value(obj: &PyObjectRef) -> Vec { + if let PyObjectKind::Bytes { value } = &obj.borrow().kind { + value.clone() + } else { + panic!("Inner error getting int {:?}", obj); + } +} + +fn set_value(obj: &PyObjectRef, value: Vec) { + obj.borrow_mut().kind = PyObjectKind::Bytes { value }; +} + +fn bytes_str(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!(vm, args, required = [(obj, Some(vm.ctx.bytes_type()))]); + let data = get_value(obj); + let data: Vec = data.into_iter().map(|b| format!("\\x{:02x}", b)).collect(); + let data = data.join(""); + Ok(vm.new_str(format!("b'{}'", data))) +} diff --git a/vm/src/objfunction.rs b/vm/src/obj/objfunction.rs similarity index 87% rename from vm/src/objfunction.rs rename to vm/src/obj/objfunction.rs index 355754ec3..e6c165559 100644 --- a/vm/src/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -1,5 +1,5 @@ -use super::pyobject::{AttributeProtocol, PyContext, PyFuncArgs, PyResult}; -use super::vm::VirtualMachine; +use super::super::pyobject::{AttributeProtocol, PyContext, PyFuncArgs, PyResult}; +use super::super::vm::VirtualMachine; pub fn init(context: &PyContext) { let ref function_type = context.function_type; diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index c6b3044a7..4b3df926a 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -19,15 +19,27 @@ fn int_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { args, required = [(zelf, Some(vm.ctx.int_type())), (arg, None)] ); - let val = if objtype::isinstance(arg.clone(), vm.ctx.int_type()) { - get_value(arg) - } else if objtype::isinstance(arg.clone(), vm.ctx.float_type()) { - objfloat::get_value(arg) as i32 + + // Try to cast to int: + let val = match to_int(vm, arg) { + Ok(val) => val, + Err(err) => return Err(err), + }; + + set_value(zelf, val); + Ok(vm.get_none()) +} + +// Casting function: +pub fn to_int(vm: &mut VirtualMachine, obj: &PyObjectRef) -> Result { + let val = if objtype::isinstance(obj.clone(), vm.ctx.int_type()) { + get_value(obj) + } else if objtype::isinstance(obj.clone(), vm.ctx.float_type()) { + objfloat::get_value(obj) as i32 } else { return Err(vm.new_type_error("Cannot construct int".to_string())); }; - set_value(zelf, val); - Ok(vm.get_none()) + Ok(val) } // Retrieve inner int value: @@ -162,16 +174,64 @@ fn int_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } +fn int_xor(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [(i, Some(vm.ctx.int_type())), (i2, None)] + ); + let v1 = get_value(i); + if objtype::isinstance(i2.clone(), vm.ctx.int_type()) { + let v2 = get_value(i2); + Ok(vm.ctx.new_int(v1 ^ v2)) + } else { + Err(vm.new_type_error(format!("Cannot xor {:?} and {:?}", i, i2))) + } +} + +fn int_or(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [(i, Some(vm.ctx.int_type())), (i2, None)] + ); + let v1 = get_value(i); + if objtype::isinstance(i2.clone(), vm.ctx.int_type()) { + let v2 = get_value(i2); + Ok(vm.ctx.new_int(v1 | v2)) + } else { + Err(vm.new_type_error(format!("Cannot or {:?} and {:?}", i, i2))) + } +} + +fn int_and(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [(i, Some(vm.ctx.int_type())), (i2, None)] + ); + let v1 = get_value(i); + if objtype::isinstance(i2.clone(), vm.ctx.int_type()) { + let v2 = get_value(i2); + Ok(vm.ctx.new_int(v1 & v2)) + } else { + Err(vm.new_type_error(format!("Cannot and {:?} and {:?}", i, i2))) + } +} + pub fn init(context: &PyContext) { let ref int_type = context.int_type; int_type.set_attr("__eq__", context.new_rustfunc(int_eq)); int_type.set_attr("__add__", context.new_rustfunc(int_add)); + int_type.set_attr("__and__", context.new_rustfunc(int_and)); int_type.set_attr("__init__", context.new_rustfunc(int_init)); int_type.set_attr("__mod__", context.new_rustfunc(int_mod)); int_type.set_attr("__mul__", context.new_rustfunc(int_mul)); + int_type.set_attr("__or__", context.new_rustfunc(int_or)); int_type.set_attr("__pow__", context.new_rustfunc(int_pow)); int_type.set_attr("__repr__", context.new_rustfunc(str)); int_type.set_attr("__str__", context.new_rustfunc(str)); int_type.set_attr("__sub__", context.new_rustfunc(int_sub)); int_type.set_attr("__truediv__", context.new_rustfunc(int_truediv)); + int_type.set_attr("__xor__", context.new_rustfunc(int_xor)); } diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index a642f0a48..f85c3c78c 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -1,8 +1,8 @@ -use super::super::objsequence::{seq_equal, PySliceableSequence}; use super::super::pyobject::{ AttributeProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol, }; use super::super::vm::VirtualMachine; +use super::objsequence::{seq_equal, PySliceableSequence}; use super::objstr; use super::objtype; @@ -26,7 +26,7 @@ pub fn set_item( } } -pub fn get_elements(obj: PyObjectRef) -> Vec { +pub fn get_elements(obj: &PyObjectRef) -> Vec { if let PyObjectKind::List { elements } = &obj.borrow().kind { elements.to_vec() } else { @@ -42,8 +42,8 @@ fn list_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { ); let result = if objtype::isinstance(other.clone(), vm.ctx.list_type()) { - let zelf = get_elements(zelf.clone()); - let other = get_elements(other.clone()); + let zelf = get_elements(zelf); + let other = get_elements(other); seq_equal(vm, zelf, other)? } else { false @@ -59,8 +59,8 @@ fn list_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { ); if objtype::isinstance(o2.clone(), vm.ctx.list_type()) { - let e1 = get_elements(o.clone()); - let e2 = get_elements(o2.clone()); + let e1 = get_elements(o); + let e2 = get_elements(o2); let elements = e1.iter().chain(e2.iter()).map(|e| e.clone()).collect(); Ok(vm.ctx.new_list(elements)) } else { @@ -71,7 +71,7 @@ fn list_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn list_str(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(o, Some(vm.ctx.list_type()))]); - let elements = get_elements(o.clone()); + let elements = get_elements(o); let mut str_parts = vec![]; for elem in elements { match vm.to_str(elem) { @@ -115,12 +115,8 @@ fn clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn list_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { trace!("list.len called with: {:?}", args); arg_check!(vm, args, required = [(list, Some(vm.ctx.list_type()))]); - let list_obj = list.borrow(); - if let PyObjectKind::List { ref elements } = list_obj.kind { - Ok(vm.context().new_int(elements.len() as i32)) - } else { - Err(vm.new_type_error("list.len is called with no list".to_string())) - } + let elements = get_elements(list); + Ok(vm.context().new_int(elements.len() as i32)) } fn reverse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { diff --git a/vm/src/objobject.rs b/vm/src/obj/objobject.rs similarity index 95% rename from vm/src/objobject.rs rename to vm/src/obj/objobject.rs index 554d3444f..08fd1a620 100644 --- a/vm/src/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -1,10 +1,10 @@ -use super::obj::objdict; -use super::obj::objtype; -use super::pyobject::{ +use super::super::pyobject::{ AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult, TypeProtocol, }; -use super::vm::VirtualMachine; +use super::super::vm::VirtualMachine; +use super::objdict; +use super::objtype; pub fn new_instance(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult { // more or less __new__ operator diff --git a/vm/src/objsequence.rs b/vm/src/obj/objsequence.rs similarity index 91% rename from vm/src/objsequence.rs rename to vm/src/obj/objsequence.rs index cc348ca0b..dc7e39fb1 100644 --- a/vm/src/objsequence.rs +++ b/vm/src/obj/objsequence.rs @@ -1,6 +1,6 @@ -use super::objbool; -use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult, TypeProtocol}; -use super::vm::VirtualMachine; +use super::super::objbool; +use super::super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult, TypeProtocol}; +use super::super::vm::VirtualMachine; use std::marker::Sized; pub trait PySliceableSequence { @@ -100,14 +100,6 @@ pub fn get_item( } } -pub fn get_elements(obj: PyObjectRef) -> Vec { - if let PyObjectKind::Tuple { elements } = &obj.borrow().kind { - elements.to_vec() - } else { - panic!("Cannot extract list elements from non-list"); - } -} - pub fn seq_equal( vm: &mut VirtualMachine, zelf: Vec, diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index 15f404685..4e4c1092f 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -1,9 +1,9 @@ -use super::super::objsequence::PySliceableSequence; use super::super::pyobject::{ AttributeProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol, }; use super::super::vm::VirtualMachine; use super::objint; +use super::objsequence::PySliceableSequence; use super::objtype; pub fn init(context: &PyContext) { diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index 3608b6012..126bb8c45 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -1,8 +1,8 @@ -use super::super::objsequence::{get_elements, seq_equal}; use super::super::pyobject::{ - AttributeProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol, + AttributeProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol, }; use super::super::vm::VirtualMachine; +use super::objsequence::seq_equal; use super::objstr; use super::objtype; @@ -14,8 +14,8 @@ fn tuple_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { ); let result = if objtype::isinstance(other.clone(), vm.ctx.tuple_type()) { - let zelf = get_elements(zelf.clone()); - let other = get_elements(other.clone()); + let zelf = get_elements(zelf); + let other = get_elements(other); seq_equal(vm, zelf, other)? } else { false @@ -24,21 +24,16 @@ fn tuple_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } fn tuple_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("tuple.len called with: {:?}", args); arg_check!(vm, args, required = [(zelf, Some(vm.ctx.tuple_type()))]); - let elements = get_elements(zelf.clone()); + let elements = get_elements(zelf); Ok(vm.context().new_int(elements.len() as i32)) } fn tuple_str(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(zelf, Some(vm.ctx.tuple_type()))]); - let elements = get_elements(zelf.clone()); - if elements.len() == 1 { - let ref part = vm.to_str(elements[0].clone())?; - let s = format!("({},)", objstr::get_value(part)); - return Ok(vm.new_str(s)); - } + let elements = get_elements(zelf); + let mut str_parts = vec![]; for elem in elements { match vm.to_str(elem) { @@ -47,10 +42,22 @@ fn tuple_str(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } - let s = format!("({})", str_parts.join(", ")); + let s = if str_parts.len() == 1 { + format!("({},)", str_parts[0]) + } else { + format!("({})", str_parts.join(", ")) + }; Ok(vm.new_str(s)) } +pub fn get_elements(obj: &PyObjectRef) -> Vec { + if let PyObjectKind::Tuple { elements } = &obj.borrow().kind { + elements.to_vec() + } else { + panic!("Cannot extract elements from non-tuple"); + } +} + pub fn init(context: &PyContext) { let ref tuple_type = context.tuple_type; tuple_type.set_attr("__eq__", context.new_rustfunc(tuple_eq)); diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 68311f12b..ced9d3117 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -112,10 +112,22 @@ pub fn type_call(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult { debug!("type_call: {:?}", args); let typ = args.shift(); let new = typ.get_attr("__new__").unwrap(); - let obj = vm.invoke(new, args.insert(typ.clone()))?; + let obj = match vm.invoke(new, args.insert(typ.clone())) { + Ok(res) => res, + Err(err) => return Err(err), + }; if let Some(init) = obj.typ().get_attr("__init__") { - let _ = vm.invoke(init, args.insert(obj.clone())).unwrap(); + match vm.invoke(init, args.insert(obj.clone())) { + Ok(res) => { + // TODO: assert that return is none? + if !isinstance(res, vm.get_none()) { + // panic!("__init__ must return none"); + // return Err(vm.new_type_error("__init__ must return None".to_string())); + } + } + Err(err) => return Err(err), + } } Ok(obj) } diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index dddbfc5a8..ca9d0e0c2 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -1,15 +1,16 @@ use super::bytecode; use super::exceptions; +use super::obj::objbytes; use super::obj::objdict; use super::obj::objfloat; +use super::obj::objfunction; use super::obj::objint; use super::obj::objlist; +use super::obj::objobject; use super::obj::objstr; use super::obj::objtuple; use super::obj::objtype; use super::objbool; -use super::objfunction; -use super::objobject; use super::vm::VirtualMachine; use std::cell::RefCell; use std::cmp::Ordering; @@ -53,6 +54,7 @@ pub struct PyContext { pub dict_type: PyObjectRef, pub int_type: PyObjectRef, pub float_type: PyObjectRef, + pub bytes_type: PyObjectRef, pub bool_type: PyObjectRef, pub list_type: PyObjectRef, pub tuple_type: PyObjectRef, @@ -115,6 +117,7 @@ impl PyContext { let list_type = create_type("list", &type_type, &object_type, &dict_type); let int_type = create_type("int", &type_type, &object_type, &dict_type); let float_type = create_type("float", &type_type, &object_type, &dict_type); + let bytes_type = create_type("bytes", &type_type, &object_type, &dict_type); let tuple_type = create_type("tuple", &type_type, &object_type, &dict_type); let bool_type = create_type("bool", &type_type, &object_type, &dict_type); let exceptions = exceptions::ExceptionZoo::new(&type_type, &object_type, &dict_type); @@ -127,6 +130,7 @@ impl PyContext { let context = PyContext { int_type: int_type, float_type: float_type, + bytes_type: bytes_type, list_type: list_type, bool_type: bool_type, tuple_type: tuple_type, @@ -148,11 +152,11 @@ impl PyContext { objfunction::init(&context); objint::init(&context); objfloat::init(&context); + objbytes::init(&context); objstr::init(&context); + objtuple::init(&context); objbool::init(&context); exceptions::init(&context); - // TODO: create exception hierarchy here? - // exceptions::create_zoo(&context); context } @@ -164,6 +168,10 @@ impl PyContext { self.float_type.clone() } + pub fn bytes_type(&self) -> PyObjectRef { + self.bytes_type.clone() + } + pub fn list_type(&self) -> PyObjectRef { self.list_type.clone() } @@ -558,6 +566,9 @@ pub enum PyObjectKind { Boolean { value: bool, }, + Bytes { + value: Vec, + }, List { elements: Vec, }, @@ -615,6 +626,7 @@ impl fmt::Debug for PyObjectKind { &PyObjectKind::String { ref value } => write!(f, "str \"{}\"", value), &PyObjectKind::Integer { ref value } => write!(f, "int {}", value), &PyObjectKind::Float { ref value } => write!(f, "float {}", value), + &PyObjectKind::Bytes { ref value } => write!(f, "bytes {:?}", value), &PyObjectKind::Boolean { ref value } => write!(f, "boolean {}", value), &PyObjectKind::List { elements: _ } => write!(f, "list"), &PyObjectKind::Tuple { elements: _ } => write!(f, "tuple"), @@ -662,6 +674,7 @@ impl PyObject { PyObjectKind::String { ref value } => value.clone(), PyObjectKind::Integer { ref value } => format!("{:?}", value), PyObjectKind::Float { ref value } => format!("{:?}", value), + PyObjectKind::Bytes { ref value } => format!("b'{:?}'", value), PyObjectKind::Boolean { ref value } => format!("{:?}", value), PyObjectKind::List { ref elements } => format!( "[{}]", @@ -773,11 +786,6 @@ impl PartialEq for PyObject { (PyObjectKind::String { value: ref v1i }, PyObjectKind::String { value: ref v2i }) => { *v2i == *v1i } - /* - (&NativeType::Float(ref v1f), &NativeType::Float(ref v2f)) => { - curr_frame.stack.push(Rc::new(NativeType::Boolean(v2f == v1f))); - }, - */ (PyObjectKind::List { elements: ref l1 }, PyObjectKind::List { elements: ref l2 }) | ( PyObjectKind::Tuple { elements: ref l1 }, diff --git a/vm/src/stdlib/json.rs b/vm/src/stdlib/json.rs index c96f82522..6ed1ed224 100644 --- a/vm/src/stdlib/json.rs +++ b/vm/src/stdlib/json.rs @@ -6,13 +6,13 @@ use serde::de::Visitor; use serde::ser::{SerializeMap, SerializeSeq}; use serde_json; -use super::super::obj::{objdict, objfloat, objint, objlist, objstr, objtype}; +use super::super::obj::{objdict, objfloat, objint, objlist, objstr, objtuple, objtype}; +use super::super::objbool; use super::super::pyobject::{ DictProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult, TypeProtocol, }; use super::super::VirtualMachine; -use super::super::{objbool, objsequence}; // We need to have a VM available to serialise a PyObject based on its subclass, so we implement // PyObject serialisation via a proxy object which holds a reference to a VM @@ -52,10 +52,10 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> { } else if objtype::isinstance(self.pyobject.clone(), self.vm.ctx.bool_type()) { serializer.serialize_bool(objbool::get_value(self.pyobject)) } else if objtype::isinstance(self.pyobject.clone(), self.vm.ctx.list_type()) { - let elements = objlist::get_elements(self.pyobject.clone()); + let elements = objlist::get_elements(self.pyobject); serialize_seq_elements(serializer, elements) } else if objtype::isinstance(self.pyobject.clone(), self.vm.ctx.tuple_type()) { - let elements = objsequence::get_elements(self.pyobject.clone()); + let elements = objtuple::get_elements(self.pyobject); serialize_seq_elements(serializer, elements) } else if objtype::isinstance(self.pyobject.clone(), self.vm.ctx.dict_type()) { let elements = objdict::get_elements(self.pyobject); diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 65cf341b1..34f25425b 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -16,10 +16,10 @@ use super::bytecode; use super::frame::{copy_code, Block, Frame}; use super::import::import; use super::obj::objlist; +use super::obj::objobject; use super::obj::objstr; use super::obj::objtype; use super::objbool; -use super::objobject; use super::pyobject::{ AttributeProtocol, DictProtocol, IdProtocol, ParentProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult, ToRust, @@ -296,7 +296,7 @@ impl VirtualMachine { match &a2.kind { PyObjectKind::String { ref value } => objstr::subscript(self, value, b), PyObjectKind::List { ref elements } | PyObjectKind::Tuple { ref elements } => { - super::objsequence::get_item(self, &a, elements, b) + super::obj::objsequence::get_item(self, &a, elements, b) } _ => Err(self.new_type_error(format!( "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", @@ -367,6 +367,18 @@ impl VirtualMachine { self.call_method(a, "__mod__", vec![b]) } + fn _xor(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult { + self.call_method(a, "__xor__", vec![b]) + } + + fn _or(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult { + self.call_method(a, "__or__", vec![b]) + } + + fn _and(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult { + self.call_method(a, "__and__", vec![b]) + } + fn execute_binop(&mut self, op: &bytecode::BinaryOperator) -> Option { let b_ref = self.pop_value(); let a_ref = self.pop_value(); @@ -380,6 +392,9 @@ impl VirtualMachine { &bytecode::BinaryOperator::Divide => self._div(a_ref, b_ref), &bytecode::BinaryOperator::Subscript => self.subscript(a_ref, b_ref), &bytecode::BinaryOperator::Modulo => self._modulo(a_ref, b_ref), + &bytecode::BinaryOperator::Xor => self._xor(a_ref, b_ref), + &bytecode::BinaryOperator::Or => self._or(a_ref, b_ref), + &bytecode::BinaryOperator::And => self._and(a_ref, b_ref), _ => panic!("NOT IMPL {:?}", op), }; match result {