diff --git a/tests/Pipfile b/tests/Pipfile index 4bbae44ef..8ccbddc4d 100644 --- a/tests/Pipfile +++ b/tests/Pipfile @@ -10,4 +10,4 @@ pytest = "*" [dev-packages] [requires] -python_version = "3.6" +python_version = "3" diff --git a/tests/Pipfile.lock b/tests/Pipfile.lock index d19a19e73..78d20f605 100644 --- a/tests/Pipfile.lock +++ b/tests/Pipfile.lock @@ -1,11 +1,11 @@ { "_meta": { "hash": { - "sha256": "ce98de5914393363a8cb86a4753b3964caa53a4659a403a3ef357e2086363ef7" + "sha256": "b2d2d68e7d4330ff8d889816c56b9cee4bf54962c86b2c11382108176a201ec8" }, "pipfile-spec": 6, "requires": { - "python_version": "3.6" + "python_version": "3" }, "sources": [ { @@ -48,36 +48,35 @@ }, "more-itertools": { "hashes": [ - "sha256:2b6b9893337bfd9166bee6a62c2b0c9fe7735dcf85948b387ec8cba30e85d8e8", - "sha256:6703844a52d3588f951883005efcf555e49566a48afd4db4e965d69b883980d3", - "sha256:a18d870ef2ffca2b8463c0070ad17b5978056f403fb64e3f15fe62a52db21cc0" + "sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", + "sha256:c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", + "sha256:fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d" ], - "version": "==4.2.0" + "version": "==4.3.0" }, "pluggy": { "hashes": [ - "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", - "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", - "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" + "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", + "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1" ], - "markers": "python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.1.*' and python_version != '3.3.*' and python_version >= '2.7'", - "version": "==0.6.0" + "markers": "python_version != '3.3.*' and python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.2.*'", + "version": "==0.7.1" }, "py": { "hashes": [ "sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7", "sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e" ], - "markers": "python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.1.*' and python_version != '3.3.*' and python_version >= '2.7'", + "markers": "python_version != '3.3.*' and python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.2.*'", "version": "==1.5.4" }, "pytest": { "hashes": [ - "sha256:0453c8676c2bee6feb0434748b068d5510273a916295fd61d306c4f22fbfd752", - "sha256:4b208614ae6d98195430ad6bde03641c78553acee7c83cec2e85d613c0cd383d" + "sha256:86a8dbf407e437351cef4dba46736e9c5a6e3c3ac71b2e942209748e76ff2086", + "sha256:e74466e97ac14582a8188ff4c53e6cc3810315f342f6096899332ae864c1d432" ], "index": "pypi", - "version": "==3.6.3" + "version": "==3.7.1" }, "six": { "hashes": [ diff --git a/tests/not_yet_working/append.py b/tests/snippets/append.py similarity index 100% rename from tests/not_yet_working/append.py rename to tests/snippets/append.py diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index cd1e589b9..2dd9c4a60 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -30,8 +30,12 @@ fn dir_locals(vm: &mut VirtualMachine) -> PyObjectRef { } fn dir_object(vm: &mut VirtualMachine, _obj: PyObjectRef) -> PyObjectRef { - // TODO: Implement dir for objects let d = vm.new_dict(); + // TODO: loop over dict of instance, next of class? + // TODO: Implement dir for objects + // for i in obj.iter_items() { + // d.set_item(k, v); + // } d } diff --git a/vm/src/objlist.rs b/vm/src/objlist.rs index b3eb90b5a..f359fb2d5 100644 --- a/vm/src/objlist.rs +++ b/vm/src/objlist.rs @@ -1,6 +1,7 @@ use super::objsequence::PySliceableSequence; -use super::pyobject::{PyObjectKind, PyObjectRef, PyResult}; +use super::pyobject::{PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult}; use super::vm::VirtualMachine; +use std::collections::HashMap; // set_item: pub fn set_item( @@ -22,15 +23,61 @@ pub fn set_item( } } -pub fn _append(vm: &mut VirtualMachine, _l: PyObjectRef, _other: PyObjectRef) -> PyResult { - // TODO: Implement objlist::append - Ok(vm.get_none()) +fn append(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + trace!("list.append called with: {:?}", args); + if args.args.len() == 2 { + let l = args.args[0].clone(); + let o = args.args[1].clone(); + let mut list_obj = l.borrow_mut(); + if let PyObjectKind::List { ref mut elements } = list_obj.kind { + elements.push(o); + Ok(vm.get_none()) + } else { + Err(vm.new_exception("list.append is called with no list".to_string())) + } + } else { + Err(vm.new_exception("list.append requires two arguments".to_string())) + } } -/* TODO: -pub fn make_type() -> PyObjectRef { - - // dict.insert("__set_item__".to_string(), set_item); - dict.insert("append".to_string(), _append) +fn reverse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + trace!("list.reverse called with: {:?}", args); + if args.args.len() == 1 { + let l = args.args[0].clone(); + let mut list_obj = l.borrow_mut(); + if let PyObjectKind::List { ref mut elements } = list_obj.kind { + elements.reverse(); + Ok(vm.get_none()) + } else { + Err(vm.new_exception("list.reverse is called with no list".to_string())) + } + } else { + Err(vm.new_exception("list.reverse requires one arguments".to_string())) + } +} + +pub fn create_type(type_type: PyObjectRef, method_type: PyObjectRef) -> PyObjectRef { + let mut dict = HashMap::new(); + dict.insert( + "append".to_string(), + PyObject::new( + PyObjectKind::RustFunction { function: append }, + method_type.clone(), + ), + ); + dict.insert( + "reverse".to_string(), + PyObject::new( + PyObjectKind::RustFunction { function: reverse }, + method_type.clone(), + ), + ); + let typ = PyObject::new( + PyObjectKind::Class { + name: "list".to_string(), + dict: PyObject::new(PyObjectKind::Dict { elements: dict }, type_type.clone()), + }, + type_type.clone(), + ); + typ } -*/ diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 96f4e25f8..19dd36792 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -1,6 +1,7 @@ use super::bytecode; use super::objfunction; use super::objint; +use super::objlist; use super::objtype; use super::vm::VirtualMachine; use std::cell::RefCell; @@ -65,15 +66,17 @@ pub struct Scope { impl PyContext { pub fn new() -> PyContext { let type_type = objtype::create_type(); + let function_type = objfunction::create_type(type_type.clone()); + let bound_method_type = objfunction::create_bound_method_type(type_type.clone()); PyContext { int_type: objint::create_type(type_type.clone()), - list_type: type_type.clone(), + list_type: objlist::create_type(type_type.clone(), function_type.clone()), tuple_type: type_type.clone(), dict_type: type_type.clone(), none: PyObject::new(PyObjectKind::None, type_type.clone()), - function_type: objfunction::create_type(type_type.clone()), - bound_method_type: objfunction::create_bound_method_type(type_type.clone()), + function_type: function_type, + bound_method_type: bound_method_type, type_type: type_type, } } @@ -90,10 +93,10 @@ impl PyContext { PyObject::new(PyObjectKind::Boolean { value: b }, self.type_type.clone()) } - pub fn new_tuple(&self) -> PyObjectRef { + pub fn new_tuple(&self, elements: Option>) -> PyObjectRef { PyObject::new( PyObjectKind::Tuple { - elements: Vec::new(), + elements: elements.unwrap_or(Vec::new()), }, self.type_type.clone(), ) @@ -104,7 +107,7 @@ impl PyContext { PyObjectKind::List { elements: elements.unwrap_or(Vec::new()), }, - self.type_type.clone(), + self.list_type.clone(), ) } @@ -262,7 +265,7 @@ impl AttributeProtocol for PyObjectRef { PyObjectKind::Module { name: _, ref dict } => dict.contains_key(attr_name), PyObjectKind::Class { name: _, ref dict } => dict.contains_key(attr_name), PyObjectKind::Instance { ref dict } => dict.contains_key(attr_name), - ref kind => unimplemented!("load_attr unimplemented for: {:?}", kind), + _ => false, } } @@ -286,7 +289,7 @@ impl DictProtocol for PyObjectRef { PyObjectKind::Dict { ref elements } => elements.contains_key(k), PyObjectKind::Module { name: _, ref dict } => dict.contains_key(k), PyObjectKind::Scope { ref scope } => scope.locals.contains_key(k), - _ => panic!("TODO"), + ref kind => unimplemented!("TODO {:?}", kind), } } @@ -427,7 +430,7 @@ impl fmt::Debug for PyObjectKind { &PyObjectKind::Module { name: _, dict: _ } => write!(f, "module"), &PyObjectKind::Scope { scope: _ } => write!(f, "scope"), &PyObjectKind::None => write!(f, "None"), - &PyObjectKind::Class { name: _, dict: _ } => write!(f, "class"), + &PyObjectKind::Class { ref name, dict: _ } => write!(f, "class {:?}", name), &PyObjectKind::Instance { dict: _ } => write!(f, "instance"), &PyObjectKind::RustFunction { function: _ } => write!(f, "rust function"), } diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 81ceea902..b5bf92556 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -594,15 +594,13 @@ impl VirtualMachine { } bytecode::Instruction::BuildList { size } => { let elements = self.pop_multiple(*size); - let list_obj = - PyObject::new(PyObjectKind::List { elements: elements }, self.get_type()); + let list_obj = self.context().new_list(Some(elements)); self.push_value(list_obj); None } bytecode::Instruction::BuildTuple { size } => { let elements = self.pop_multiple(*size); - let list_obj = - PyObject::new(PyObjectKind::Tuple { elements: elements }, self.get_type()); + let list_obj = self.context().new_tuple(Some(elements)); self.push_value(list_obj); None }