From 51acd6c4b594657c7e973e8c719d22e6b34f8a4c Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Tue, 14 Aug 2018 20:56:14 +0200 Subject: [PATCH 1/5] Register append function to list type --- vm/src/objlist.rs | 33 +++++++++++++++++++++++++-------- vm/src/pyobject.rs | 11 +++++++---- vm/src/vm.rs | 2 +- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/vm/src/objlist.rs b/vm/src/objlist.rs index b3eb90b5a..be714c785 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::{PyObjectKind, PyObjectRef, PyResult, PyObject, PyFuncArgs}; use super::vm::VirtualMachine; +use std::collections::HashMap; // set_item: pub fn set_item( @@ -22,15 +23,31 @@ pub fn set_item( } } -pub fn _append(vm: &mut VirtualMachine, _l: PyObjectRef, _other: PyObjectRef) -> PyResult { +fn append(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { // TODO: Implement objlist::append + // println!("{:?}", args); + // if let PyObjectKind + // Ok(vm.new_bound_method(args.args[0].clone(), args.args[1].clone())) Ok(vm.get_none()) } -/* TODO: -pub fn make_type() -> PyObjectRef { - - // dict.insert("__set_item__".to_string(), set_item); - dict.insert("append".to_string(), _append) +pub fn create_type(type_type: PyObjectRef) -> PyObjectRef { + let mut dict = HashMap::new(); + dict.insert( + "append".to_string(), + PyObject::new( + PyObjectKind::RustFunction { + function: append, + }, + type_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..9cf62d352 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; @@ -68,7 +69,7 @@ impl PyContext { PyContext { int_type: objint::create_type(type_type.clone()), - list_type: type_type.clone(), + list_type: objlist::create_type(type_type.clone()), tuple_type: type_type.clone(), dict_type: type_type.clone(), none: PyObject::new(PyObjectKind::None, type_type.clone()), @@ -104,7 +105,7 @@ impl PyContext { PyObjectKind::List { elements: elements.unwrap_or(Vec::new()), }, - self.type_type.clone(), + self.list_type.clone(), ) } @@ -252,6 +253,7 @@ impl AttributeProtocol for PyObjectRef { PyObjectKind::Module { name: _, ref dict } => dict.get_item(attr_name), PyObjectKind::Class { name: _, ref dict } => dict.get_item(attr_name), PyObjectKind::Instance { ref dict } => dict.get_item(attr_name), + PyObjectKind::List { elements: _ } => self.typ().get_attr(attr_name), ref kind => unimplemented!("load_attr unimplemented for: {:?}", kind), } } @@ -262,6 +264,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), + PyObjectKind::List { elements: _ } => self.typ().has_attr(attr_name), ref kind => unimplemented!("load_attr unimplemented for: {:?}", kind), } } @@ -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..f2e1d0b59 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -595,7 +595,7 @@ impl VirtualMachine { bytecode::Instruction::BuildList { size } => { let elements = self.pop_multiple(*size); let list_obj = - PyObject::new(PyObjectKind::List { elements: elements }, self.get_type()); + self.context().new_list( Some(elements) ); self.push_value(list_obj); None } From 4ada085234a6e83e17d9cb5679949afbefcce1be Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Tue, 14 Aug 2018 21:21:47 +0200 Subject: [PATCH 2/5] Format code properly and try to implement append function --- vm/src/objlist.rs | 18 +++++++++++------- vm/src/pyobject.rs | 4 ++-- vm/src/vm.rs | 6 ++---- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/vm/src/objlist.rs b/vm/src/objlist.rs index be714c785..fbdb1002a 100644 --- a/vm/src/objlist.rs +++ b/vm/src/objlist.rs @@ -1,5 +1,5 @@ use super::objsequence::PySliceableSequence; -use super::pyobject::{PyObjectKind, PyObjectRef, PyResult, PyObject, PyFuncArgs}; +use super::pyobject::{PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult}; use super::vm::VirtualMachine; use std::collections::HashMap; @@ -25,10 +25,16 @@ pub fn set_item( fn append(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { // TODO: Implement objlist::append - // println!("{:?}", args); - // if let PyObjectKind + trace!("list.append called with: {:?}", args); + if let PyObjectKind::List { ref elements } = args.args[0].borrow().kind { + warn!("implement append here: {:?}", elements); + // elements.push(args.args[1].clone()); + Ok(vm.get_none()) + } else { + unimplemented!("Raise error when list.append is called with no list") + // Err() + } // Ok(vm.new_bound_method(args.args[0].clone(), args.args[1].clone())) - Ok(vm.get_none()) } pub fn create_type(type_type: PyObjectRef) -> PyObjectRef { @@ -36,9 +42,7 @@ pub fn create_type(type_type: PyObjectRef) -> PyObjectRef { dict.insert( "append".to_string(), PyObject::new( - PyObjectKind::RustFunction { - function: append, - }, + PyObjectKind::RustFunction { function: append }, type_type.clone(), ), ); diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 9cf62d352..9d77731f4 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -91,10 +91,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(), ) diff --git a/vm/src/vm.rs b/vm/src/vm.rs index f2e1d0b59..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 = - self.context().new_list( Some(elements) ); + 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 } From 34bba7a257c7519b3ff1b194a211dbcd95ad527e Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Tue, 14 Aug 2018 21:52:00 +0200 Subject: [PATCH 3/5] Borrow list object mutably and append item --- vm/src/builtins.rs | 6 +++++- vm/src/objlist.rs | 21 ++++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) 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 fbdb1002a..613c8659e 100644 --- a/vm/src/objlist.rs +++ b/vm/src/objlist.rs @@ -24,17 +24,20 @@ pub fn set_item( } fn append(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - // TODO: Implement objlist::append - trace!("list.append called with: {:?}", args); - if let PyObjectKind::List { ref elements } = args.args[0].borrow().kind { - warn!("implement append here: {:?}", elements); - // elements.push(args.args[1].clone()); - Ok(vm.get_none()) + if args.args.len() == 2 { + let l = args.args[0].clone(); + let o = args.args[1].clone(); + trace!("list.append called with: {:?}", args); + 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 { - unimplemented!("Raise error when list.append is called with no list") - // Err() + Err(vm.new_exception("list.append requires two arguments".to_string())) } - // Ok(vm.new_bound_method(args.args[0].clone(), args.args[1].clone())) } pub fn create_type(type_type: PyObjectRef) -> PyObjectRef { From 919b7f631d6197a82db9490983064b31e248651d Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Tue, 14 Aug 2018 22:01:40 +0200 Subject: [PATCH 4/5] Add reverse function to list --- vm/src/objlist.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/vm/src/objlist.rs b/vm/src/objlist.rs index 613c8659e..61aa14aad 100644 --- a/vm/src/objlist.rs +++ b/vm/src/objlist.rs @@ -24,10 +24,10 @@ pub fn set_item( } 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(); - trace!("list.append called with: {:?}", args); let mut list_obj = l.borrow_mut(); if let PyObjectKind::List { ref mut elements } = list_obj.kind { elements.push(o); @@ -40,6 +40,22 @@ fn append(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } +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) -> PyObjectRef { let mut dict = HashMap::new(); dict.insert( @@ -49,6 +65,13 @@ pub fn create_type(type_type: PyObjectRef) -> PyObjectRef { type_type.clone(), ), ); + dict.insert( + "reverse".to_string(), + PyObject::new( + PyObjectKind::RustFunction { function: reverse }, + type_type.clone(), + ), + ); let typ = PyObject::new( PyObjectKind::Class { name: "list".to_string(), From c9816c37de8ddaa0549bd92142a0190487b95ff7 Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Tue, 14 Aug 2018 22:44:55 +0200 Subject: [PATCH 5/5] Fix append snippet --- tests/Pipfile | 2 +- tests/Pipfile.lock | 29 +++++++++---------- tests/{not_yet_working => snippets}/append.py | 0 vm/src/objlist.rs | 6 ++-- vm/src/pyobject.rs | 12 ++++---- 5 files changed, 24 insertions(+), 25 deletions(-) rename tests/{not_yet_working => snippets}/append.py (100%) 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/objlist.rs b/vm/src/objlist.rs index 61aa14aad..f359fb2d5 100644 --- a/vm/src/objlist.rs +++ b/vm/src/objlist.rs @@ -56,20 +56,20 @@ fn reverse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } -pub fn create_type(type_type: PyObjectRef) -> PyObjectRef { +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 }, - type_type.clone(), + method_type.clone(), ), ); dict.insert( "reverse".to_string(), PyObject::new( PyObjectKind::RustFunction { function: reverse }, - type_type.clone(), + method_type.clone(), ), ); let typ = PyObject::new( diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 9d77731f4..19dd36792 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -66,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: objlist::create_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, } } @@ -253,7 +255,6 @@ impl AttributeProtocol for PyObjectRef { PyObjectKind::Module { name: _, ref dict } => dict.get_item(attr_name), PyObjectKind::Class { name: _, ref dict } => dict.get_item(attr_name), PyObjectKind::Instance { ref dict } => dict.get_item(attr_name), - PyObjectKind::List { elements: _ } => self.typ().get_attr(attr_name), ref kind => unimplemented!("load_attr unimplemented for: {:?}", kind), } } @@ -264,8 +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), - PyObjectKind::List { elements: _ } => self.typ().has_attr(attr_name), - ref kind => unimplemented!("load_attr unimplemented for: {:?}", kind), + _ => false, } }