From 61d7c26787a4ecc3de6d369534ad9cf310cba473 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Mon, 20 Aug 2018 06:55:27 +0100 Subject: [PATCH 1/8] Simplify construction of list and type. --- vm/src/builtins.rs | 5 ++-- vm/src/objclass.rs | 2 +- vm/src/objfunction.rs | 2 +- vm/src/objlist.rs | 54 ++++++++++++++----------------------------- vm/src/objtype.rs | 31 ++++++++----------------- vm/src/pyobject.rs | 11 +++++---- 6 files changed, 37 insertions(+), 68 deletions(-) diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 54f20a7ea..dfa503802 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -375,8 +375,9 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef { pub fn builtin_build_class_(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult { let function = args.shift(); let name_arg = args.shift(); - let name = match name_arg.borrow().kind { - PyObjectKind::String { ref value } => value.to_string(), + let name_arg_ref = name_arg.borrow(); + let name = match name_arg_ref.kind { + PyObjectKind::String { ref value } => value, _ => panic!("Class name must by a string!"), }; let mut bases = args.args.clone(); diff --git a/vm/src/objclass.rs b/vm/src/objclass.rs index 87ef66172..a1d6c98b5 100644 --- a/vm/src/objclass.rs +++ b/vm/src/objclass.rs @@ -41,7 +41,7 @@ pub fn create_object(type_type: PyObjectRef, function_type: PyObjectRef) -> PyOb ); objtype::new( type_type.clone(), - String::from("object"), + "object", vec![], PyObject::new(PyObjectKind::Dict { elements: dict }, type_type.clone()), ).unwrap() diff --git a/vm/src/objfunction.rs b/vm/src/objfunction.rs index 95f52f1ff..21aa959ad 100644 --- a/vm/src/objfunction.rs +++ b/vm/src/objfunction.rs @@ -59,7 +59,7 @@ pub fn create_member_descriptor_type(type_type: PyObjectRef, object: PyObjectRef objtype::new( type_type.clone(), - String::from("member_descriptor"), + "member_descriptor", vec![object], PyObject::new(PyObjectKind::Dict { elements: dict }, type_type.clone()), ) diff --git a/vm/src/objlist.rs b/vm/src/objlist.rs index ac99e5567..9c77ac6cf 100644 --- a/vm/src/objlist.rs +++ b/vm/src/objlist.rs @@ -1,5 +1,8 @@ use super::objsequence::PySliceableSequence; -use super::pyobject::{PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult}; +use super::objtype; +use super::pyobject::{ + AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult, +}; use super::vm::VirtualMachine; use std::collections::HashMap; @@ -88,43 +91,20 @@ fn reverse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } -pub fn create_type(type_type: PyObjectRef, method_type: PyObjectRef) -> PyObjectRef { - let mut dict = HashMap::new(); - dict.insert( - "__len__".to_string(), - PyObject::new( - PyObjectKind::RustFunction { function: len }, - method_type.clone(), - ), - ); - dict.insert( - "append".to_string(), - PyObject::new( - PyObjectKind::RustFunction { function: append }, - method_type.clone(), - ), - ); - dict.insert( - "clear".to_string(), - PyObject::new( - PyObjectKind::RustFunction { function: clear }, - 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()), - mro: vec![], +pub fn create_type(type_type: PyObjectRef, object: PyObjectRef) -> PyResult { + let dict = PyObject::new( + PyObjectKind::Dict { + elements: HashMap::new(), }, type_type.clone(), ); - typ + objtype::new(type_type.clone(), "list", vec![object.clone()], dict) +} + +pub fn init(context: &mut PyContext) { + let ref list_type = context.list_type; + list_type.set_attr("__len__", context.new_rustfunc(len)); + list_type.set_attr("append", context.new_rustfunc(append)); + list_type.set_attr("clear", context.new_rustfunc(clear)); + list_type.set_attr("reverse", context.new_rustfunc(reverse)); } diff --git a/vm/src/objtype.rs b/vm/src/objtype.rs index bc52aefaa..29d486a66 100644 --- a/vm/src/objtype.rs +++ b/vm/src/objtype.rs @@ -31,25 +31,12 @@ pub fn create_type() -> PyObjectRef { } pub fn init(context: &mut PyContext) { - context - .type_type - .set_attr(&String::from("__call__"), context.new_rustfunc(type_call)); - context - .type_type - .set_attr(&String::from("__new__"), context.new_rustfunc(type_new)); - - context.type_type.set_attr( - &String::from("__mro__"), - context.new_member_descriptor(type_mro), - ); - context.type_type.set_attr( - &String::from("__class__"), - context.new_member_descriptor(type_new), - ); - context.type_type.set_attr( - &String::from("__dict__"), - context.new_member_descriptor(type_dict), - ); + let ref type_type = context.type_type; + type_type.set_attr("__call__", context.new_rustfunc(type_call)); + type_type.set_attr("__new__", context.new_rustfunc(type_new)); + type_type.set_attr("__mro__", context.new_member_descriptor(type_mro)); + type_type.set_attr("__class__", context.new_member_descriptor(type_new)); + type_type.set_attr("__dict__", context.new_member_descriptor(type_dict)); } fn type_mro(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -87,7 +74,7 @@ pub fn type_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let mut bases = args.args[2].to_vec().unwrap(); bases.push(vm.context().object.clone()); let dict = args.args[3].clone(); - new(typ, name, bases, dict) + new(typ, &name, bases, dict) } else { Err(vm.new_exception(format!("TypeError: type_new: {:?}", args))) } @@ -184,12 +171,12 @@ fn linearise_mro(mut bases: Vec>) -> Option> { Some(result) } -pub fn new(typ: PyObjectRef, name: String, bases: Vec, dict: PyObjectRef) -> PyResult { +pub fn new(typ: PyObjectRef, name: &str, bases: Vec, dict: PyObjectRef) -> PyResult { let mros = bases.into_iter().map(|x| _mro(x).unwrap()).collect(); let mro = linearise_mro(mros).unwrap(); Ok(PyObject::new( PyObjectKind::Class { - name: name, + name: String::from(name), dict: dict, mro: mro, }, diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 7b6aa2a71..94fb7910c 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -77,7 +77,7 @@ impl PyContext { let mut context = PyContext { int_type: objint::create_type(type_type.clone()), - list_type: objlist::create_type(type_type.clone(), function_type.clone()), + list_type: objlist::create_type(type_type.clone(), object.clone()).unwrap(), tuple_type: type_type.clone(), dict_type: type_type.clone(), none: PyObject::new(PyObjectKind::None, type_type.clone()), @@ -88,6 +88,7 @@ impl PyContext { type_type: type_type, }; objtype::init(&mut context); + objlist::init(&mut context); context } @@ -244,7 +245,7 @@ impl ParentProtocol for PyObjectRef { pub trait AttributeProtocol { fn get_attr(&self, attr_name: &String) -> PyObjectRef; - fn set_attr(&self, attr_name: &String, value: PyObjectRef); + fn set_attr(&self, attr_name: &str, value: PyObjectRef); fn has_attr(&self, attr_name: &String) -> bool; } @@ -303,14 +304,14 @@ impl AttributeProtocol for PyObjectRef { } } - fn set_attr(&self, attr_name: &String, value: PyObjectRef) { + fn set_attr(&self, attr_name: &str, value: PyObjectRef) { match self.borrow().kind { - PyObjectKind::Instance { ref dict } => dict.set_item(attr_name, value), + PyObjectKind::Instance { ref dict } => dict.set_item(&String::from(attr_name), value), PyObjectKind::Class { name: _, ref dict, mro: _, - } => dict.set_item(attr_name, value), + } => dict.set_item(&String::from(attr_name), value), ref kind => unimplemented!("set_attr unimplemented for: {:?}", kind), }; } From 29133dd299588dce3aa0acaa9a9c78de10c9a40d Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Mon, 20 Aug 2018 06:59:25 +0100 Subject: [PATCH 2/8] Rename objclass -> objobject. --- vm/src/lib.rs | 2 +- vm/src/{objclass.rs => objobject.rs} | 0 vm/src/pyobject.rs | 4 ++-- vm/src/vm.rs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) rename vm/src/{objclass.rs => objobject.rs} (100%) diff --git a/vm/src/lib.rs b/vm/src/lib.rs index a0b396482..78178c91f 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -12,11 +12,11 @@ pub mod eval; mod frame; mod import; mod objbool; -mod objclass; mod objdict; mod objfunction; mod objint; mod objlist; +mod objobject; mod objsequence; mod objstr; mod objtype; diff --git a/vm/src/objclass.rs b/vm/src/objobject.rs similarity index 100% rename from vm/src/objclass.rs rename to vm/src/objobject.rs diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 94fb7910c..44622331d 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -1,8 +1,8 @@ use super::bytecode; -use super::objclass; use super::objfunction; use super::objint; use super::objlist; +use super::objobject; use super::objtype; use super::vm::VirtualMachine; use std::cell::RefCell; @@ -71,7 +71,7 @@ impl 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()); - let object = objclass::create_object(type_type.clone(), function_type.clone()); + let object = objobject::create_object(type_type.clone(), function_type.clone()); let member_descriptor_type = objfunction::create_member_descriptor_type(type_type.clone(), object.clone()).unwrap(); diff --git a/vm/src/vm.rs b/vm/src/vm.rs index e3d254c9a..f3661fa08 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -12,8 +12,8 @@ use super::builtins; use super::bytecode; use super::frame::{copy_code, Block, Frame}; use super::import::import; -use super::objclass; use super::objlist; +use super::objobject; use super::objstr; use super::objtype; use super::pyobject::{ @@ -489,7 +489,7 @@ impl VirtualMachine { ref function, ref object, } => self.invoke(function.clone(), args.insert(object.clone())), - PyObjectKind::Instance { .. } => objclass::call(self, args.insert(func_ref.clone())), + PyObjectKind::Instance { .. } => objobject::call(self, args.insert(func_ref.clone())), ref kind => { unimplemented!("invoke unimplemented for: {:?}", kind); } From 9f2dac74dc120e47d76c39e944d892962206e72a Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Mon, 20 Aug 2018 07:26:09 +0100 Subject: [PATCH 3/8] Create dictionary type --- vm/src/objdict.rs | 21 ++++++++++++++++++++- vm/src/pyobject.rs | 11 +++++++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/vm/src/objdict.rs b/vm/src/objdict.rs index 8781777f8..f17da47a2 100644 --- a/vm/src/objdict.rs +++ b/vm/src/objdict.rs @@ -1,5 +1,7 @@ -use super::pyobject::{PyObjectRef, PyResult}; +use super::objtype; +use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult}; use super::vm::VirtualMachine; +use std::collections::HashMap; pub fn _set_item( vm: &mut VirtualMachine, @@ -11,6 +13,23 @@ pub fn _set_item( Ok(vm.get_none()) } +pub fn create_type(type_type: PyObjectRef, object: PyObjectRef) -> PyObjectRef { + let dict = PyObject { + kind: PyObjectKind::Dict { + elements: HashMap::new(), + }, + typ: None, + }.into_ref(); + let dict_type = objtype::new( + type_type.clone(), + "dict", + vec![object.clone()], + dict.clone(), + ).unwrap(); + (*dict.borrow_mut()).typ = Some(dict_type.clone()); + dict_type +} + /* TODO: pub fn make_type() -> PyObjectRef { diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 44622331d..9f0687325 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -1,4 +1,5 @@ use super::bytecode; +use super::objdict; use super::objfunction; use super::objint; use super::objlist; @@ -45,10 +46,10 @@ impl fmt::Display for PyObjectRef { pub struct PyContext { pub type_type: PyObjectRef, pub none: PyObjectRef, + pub dict_type: PyObjectRef, pub int_type: PyObjectRef, pub list_type: PyObjectRef, pub tuple_type: PyObjectRef, - pub dict_type: PyObjectRef, pub function_type: PyObjectRef, pub bound_method_type: PyObjectRef, pub member_descriptor_type: PyObjectRef, @@ -69,9 +70,11 @@ pub struct Scope { impl PyContext { pub fn new() -> PyContext { let type_type = objtype::create_type(); + let object = objobject::create_object(type_type.clone()); + let dict_type = objdict::create_type(type_type.clone(), object.clone()); + let function_type = objfunction::create_type(type_type.clone()); let bound_method_type = objfunction::create_bound_method_type(type_type.clone()); - let object = objobject::create_object(type_type.clone(), function_type.clone()); let member_descriptor_type = objfunction::create_member_descriptor_type(type_type.clone(), object.clone()).unwrap(); @@ -79,7 +82,7 @@ impl PyContext { int_type: objint::create_type(type_type.clone()), list_type: objlist::create_type(type_type.clone(), object.clone()).unwrap(), tuple_type: type_type.clone(), - dict_type: type_type.clone(), + dict_type: dict_type.clone(), none: PyObject::new(PyObjectKind::None, type_type.clone()), object: object, function_type: function_type, @@ -123,7 +126,7 @@ impl PyContext { PyObjectKind::Dict { elements: HashMap::new(), }, - self.type_type.clone(), + self.dict_type.clone(), ) } From 1884948bb7fc39983b63ab544cbee69cae0acc14 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Mon, 20 Aug 2018 07:27:48 +0100 Subject: [PATCH 4/8] Cleanup object type. --- vm/src/objfunction.rs | 4 ++-- vm/src/objlist.rs | 6 +++--- vm/src/objobject.rs | 40 ++++++++++++++++------------------------ vm/src/objtype.rs | 2 +- vm/src/pyobject.rs | 11 ++++++----- 5 files changed, 28 insertions(+), 35 deletions(-) diff --git a/vm/src/objfunction.rs b/vm/src/objfunction.rs index 21aa959ad..b8d2e7561 100644 --- a/vm/src/objfunction.rs +++ b/vm/src/objfunction.rs @@ -44,7 +44,7 @@ fn bind_method(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.new_bound_method(args.args[0].clone(), args.args[1].clone())) } -pub fn create_member_descriptor_type(type_type: PyObjectRef, object: PyObjectRef) -> PyResult { +pub fn create_member_descriptor_type(type_type: PyObjectRef, object: PyObjectRef) -> PyObjectRef { let mut dict = HashMap::new(); dict.insert( @@ -62,7 +62,7 @@ pub fn create_member_descriptor_type(type_type: PyObjectRef, object: PyObjectRef "member_descriptor", vec![object], PyObject::new(PyObjectKind::Dict { elements: dict }, type_type.clone()), - ) + ).unwrap() } fn member_get(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult { diff --git a/vm/src/objlist.rs b/vm/src/objlist.rs index 9c77ac6cf..891ae563b 100644 --- a/vm/src/objlist.rs +++ b/vm/src/objlist.rs @@ -91,17 +91,17 @@ fn reverse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } -pub fn create_type(type_type: PyObjectRef, object: PyObjectRef) -> PyResult { +pub fn create_type(type_type: PyObjectRef, object: PyObjectRef) -> PyObjectRef { let dict = PyObject::new( PyObjectKind::Dict { elements: HashMap::new(), }, type_type.clone(), ); - objtype::new(type_type.clone(), "list", vec![object.clone()], dict) + objtype::new(type_type.clone(), "list", vec![object.clone()], dict).unwrap() } -pub fn init(context: &mut PyContext) { +pub fn init(context: &PyContext) { let ref list_type = context.list_type; list_type.set_attr("__len__", context.new_rustfunc(len)); list_type.set_attr("append", context.new_rustfunc(append)); diff --git a/vm/src/objobject.rs b/vm/src/objobject.rs index a1d6c98b5..87e317343 100644 --- a/vm/src/objobject.rs +++ b/vm/src/objobject.rs @@ -1,5 +1,7 @@ use super::objtype; -use super::pyobject::{PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult}; +use super::pyobject::{ + AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult, +}; use super::vm::VirtualMachine; use std::collections::HashMap; @@ -21,28 +23,18 @@ fn noop(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult { Ok(vm.get_none()) } -pub fn create_object(type_type: PyObjectRef, function_type: PyObjectRef) -> PyObjectRef { - let mut dict = HashMap::new(); - dict.insert( - "__new__".to_string(), - PyObject::new( - PyObjectKind::RustFunction { - function: new_instance, - }, - function_type.clone(), - ), - ); - dict.insert( - "__init__".to_string(), - PyObject::new( - PyObjectKind::RustFunction { function: noop }, - function_type.clone(), - ), - ); - objtype::new( +pub fn create_object(type_type: PyObjectRef) -> PyObjectRef { + let dict = PyObject::new( + PyObjectKind::Dict { + elements: HashMap::new(), + }, type_type.clone(), - "object", - vec![], - PyObject::new(PyObjectKind::Dict { elements: dict }, type_type.clone()), - ).unwrap() + ); + objtype::new(type_type.clone(), "object", vec![], dict).unwrap() +} + +pub fn init(context: &PyContext) { + let ref object = context.object; + object.set_attr("__new__", context.new_rustfunc(new_instance)); + object.set_attr("__init__", context.new_rustfunc(noop)); } diff --git a/vm/src/objtype.rs b/vm/src/objtype.rs index 29d486a66..5b31f976b 100644 --- a/vm/src/objtype.rs +++ b/vm/src/objtype.rs @@ -30,7 +30,7 @@ pub fn create_type() -> PyObjectRef { typ } -pub fn init(context: &mut PyContext) { +pub fn init(context: &PyContext) { let ref type_type = context.type_type; type_type.set_attr("__call__", context.new_rustfunc(type_call)); type_type.set_attr("__new__", context.new_rustfunc(type_new)); diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 9f0687325..5e0c95f60 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -76,11 +76,11 @@ impl PyContext { let function_type = objfunction::create_type(type_type.clone()); let bound_method_type = objfunction::create_bound_method_type(type_type.clone()); let member_descriptor_type = - objfunction::create_member_descriptor_type(type_type.clone(), object.clone()).unwrap(); + objfunction::create_member_descriptor_type(type_type.clone(), object.clone()); - let mut context = PyContext { + let context = PyContext { int_type: objint::create_type(type_type.clone()), - list_type: objlist::create_type(type_type.clone(), object.clone()).unwrap(), + list_type: objlist::create_type(type_type.clone(), object.clone()), tuple_type: type_type.clone(), dict_type: dict_type.clone(), none: PyObject::new(PyObjectKind::None, type_type.clone()), @@ -90,8 +90,9 @@ impl PyContext { member_descriptor_type: member_descriptor_type, type_type: type_type, }; - objtype::init(&mut context); - objlist::init(&mut context); + objtype::init(&context); + objlist::init(&context); + objobject::init(&context); context } From 483256959ac4eb0c36fb6859ae2685fec0b54992 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Mon, 20 Aug 2018 07:59:15 +0100 Subject: [PATCH 5/8] Trinity of Type, Object and Dict all mutally referential. --- vm/src/objdict.rs | 28 ++++++++++++++-------------- vm/src/objobject.rs | 17 ++++++++--------- vm/src/objtype.rs | 24 ++++++------------------ vm/src/pyobject.rs | 23 +++++++++++++++++------ vm/src/vm.rs | 2 +- 5 files changed, 46 insertions(+), 48 deletions(-) diff --git a/vm/src/objdict.rs b/vm/src/objdict.rs index f17da47a2..23254ff1f 100644 --- a/vm/src/objdict.rs +++ b/vm/src/objdict.rs @@ -1,4 +1,3 @@ -use super::objtype; use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult}; use super::vm::VirtualMachine; use std::collections::HashMap; @@ -13,21 +12,22 @@ pub fn _set_item( Ok(vm.get_none()) } -pub fn create_type(type_type: PyObjectRef, object: PyObjectRef) -> PyObjectRef { - let dict = PyObject { - kind: PyObjectKind::Dict { +pub fn new(dict_type: PyObjectRef) -> PyObjectRef { + PyObject::new( + PyObjectKind::Dict { elements: HashMap::new(), }, - typ: None, - }.into_ref(); - let dict_type = objtype::new( - type_type.clone(), - "dict", - vec![object.clone()], - dict.clone(), - ).unwrap(); - (*dict.borrow_mut()).typ = Some(dict_type.clone()); - dict_type + dict_type.clone(), + ) +} + +pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type: PyObjectRef) { + (*dict_type.borrow_mut()).kind = PyObjectKind::Class { + name: String::from("type"), + dict: new(dict_type.clone()), + mro: vec![object_type], + }; + (*dict_type.borrow_mut()).typ = Some(type_type.clone()); } /* TODO: diff --git a/vm/src/objobject.rs b/vm/src/objobject.rs index 87e317343..0b0aefbda 100644 --- a/vm/src/objobject.rs +++ b/vm/src/objobject.rs @@ -1,9 +1,9 @@ +use super::objdict; use super::objtype; use super::pyobject::{ AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult, }; use super::vm::VirtualMachine; -use std::collections::HashMap; pub fn new_instance(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult { // more or less __new__ operator @@ -23,14 +23,13 @@ fn noop(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult { Ok(vm.get_none()) } -pub fn create_object(type_type: PyObjectRef) -> PyObjectRef { - let dict = PyObject::new( - PyObjectKind::Dict { - elements: HashMap::new(), - }, - type_type.clone(), - ); - objtype::new(type_type.clone(), "object", vec![], dict).unwrap() +pub fn create_object(type_type: PyObjectRef, object_type: PyObjectRef, dict_type: PyObjectRef) { + (*object_type.borrow_mut()).kind = PyObjectKind::Class { + name: String::from("object"), + dict: objdict::new(dict_type), + mro: vec![], + }; + (*object_type.borrow_mut()).typ = Some(type_type.clone()); } pub fn init(context: &PyContext) { diff --git a/vm/src/objtype.rs b/vm/src/objtype.rs index 5b31f976b..a6386f4ca 100644 --- a/vm/src/objtype.rs +++ b/vm/src/objtype.rs @@ -3,31 +3,19 @@ use super::pyobject::{ PyResult, ToRust, TypeProtocol, }; use super::vm::VirtualMachine; -use std::collections::HashMap; +use super::objdict; /* * The magical type type */ -pub fn create_type() -> PyObjectRef { - let typ = PyObject { - kind: PyObjectKind::None, - typ: None, - }.into_ref(); - - let dict = PyObject::new( - PyObjectKind::Dict { - elements: HashMap::new(), - }, - typ.clone(), - ); - (*typ.borrow_mut()).kind = PyObjectKind::Class { +pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type: PyObjectRef) { + (*type_type.borrow_mut()).kind = PyObjectKind::Class { name: String::from("type"), - dict: dict, - mro: vec![], + dict: objdict::new(dict_type), + mro: vec![object_type], }; - (*typ.borrow_mut()).typ = Some(typ.clone()); - typ + (*type_type.borrow_mut()).typ = Some(type_type.clone()); } pub fn init(context: &PyContext) { diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 5e0c95f60..f996493e2 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -66,25 +66,36 @@ pub struct Scope { pub parent: Option, // Parent scope } +fn _nothing() -> PyObjectRef { + PyObject { + kind: PyObjectKind::None, + typ: None, + }.into_ref() +} + // Basic objects: impl PyContext { pub fn new() -> PyContext { - let type_type = objtype::create_type(); - let object = objobject::create_object(type_type.clone()); - let dict_type = objdict::create_type(type_type.clone(), object.clone()); + let type_type = _nothing(); + let object_type = _nothing(); + let dict_type = _nothing(); + + objtype::create_type(type_type.clone(), object_type.clone(), dict_type.clone()); + objobject::create_object(type_type.clone(), object_type.clone(), dict_type.clone()); + objdict::create_type(type_type.clone(), object_type.clone(), dict_type.clone()); let function_type = objfunction::create_type(type_type.clone()); let bound_method_type = objfunction::create_bound_method_type(type_type.clone()); let member_descriptor_type = - objfunction::create_member_descriptor_type(type_type.clone(), object.clone()); + objfunction::create_member_descriptor_type(type_type.clone(), object_type.clone()); let context = PyContext { int_type: objint::create_type(type_type.clone()), - list_type: objlist::create_type(type_type.clone(), object.clone()), + list_type: objlist::create_type(type_type.clone(), object_type.clone()), tuple_type: type_type.clone(), dict_type: dict_type.clone(), none: PyObject::new(PyObjectKind::None, type_type.clone()), - object: object, + object: object_type, function_type: function_type, bound_method_type: bound_method_type, member_descriptor_type: member_descriptor_type, diff --git a/vm/src/vm.rs b/vm/src/vm.rs index f3661fa08..d6bfbe621 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -795,7 +795,7 @@ impl VirtualMachine { PyObjectKind::RustFunction { function: builtins::builtin_build_class_, }, - objtype::create_type(), + self.ctx.type_type.clone(), ); self.push_value(rustfunc); None From 8b0ba28a36e9f5443417ed8be01109126fc40961 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Mon, 20 Aug 2018 19:04:02 +0100 Subject: [PATCH 6/8] dict built-in and dict.__new__. --- vm/src/builtins.rs | 9 +-------- vm/src/objdict.rs | 18 +++++++++++------- vm/src/objtype.rs | 2 +- vm/src/pyobject.rs | 1 + 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index dfa503802..dfead1cc8 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -99,13 +99,6 @@ fn builtin_compile(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { // builtin_complex // builtin_delattr -fn builtin_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - if !args.args.is_empty() { - unimplemented!("only zero-arg version of dict is currently supported") - } - Ok(vm.new_dict()) -} - fn builtin_dir(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { if args.args.is_empty() { Ok(dir_locals(vm)) @@ -335,7 +328,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef { dict.insert(String::from("chr"), ctx.new_rustfunc(builtin_chr)); dict.insert(String::from("compile"), ctx.new_rustfunc(builtin_compile)); // TODO: can we just insert dict here? - dict.insert(String::from("dict"), ctx.new_rustfunc(builtin_dict)); + dict.insert(String::from("dict"), ctx.dict_type.clone()); dict.insert(String::from("dir"), ctx.new_rustfunc(builtin_dir)); dict.insert(String::from("eval"), ctx.new_rustfunc(builtin_eval)); dict.insert(String::from("getattr"), ctx.new_rustfunc(builtin_getattr)); diff --git a/vm/src/objdict.rs b/vm/src/objdict.rs index 23254ff1f..181505fcb 100644 --- a/vm/src/objdict.rs +++ b/vm/src/objdict.rs @@ -1,4 +1,6 @@ -use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult}; +use super::pyobject::{ + AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult, +}; use super::vm::VirtualMachine; use std::collections::HashMap; @@ -21,18 +23,20 @@ pub fn new(dict_type: PyObjectRef) -> PyObjectRef { ) } +fn dict_new(_vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + Ok(new(args.args[0].clone())) +} + pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type: PyObjectRef) { (*dict_type.borrow_mut()).kind = PyObjectKind::Class { - name: String::from("type"), + name: String::from("dict"), dict: new(dict_type.clone()), mro: vec![object_type], }; (*dict_type.borrow_mut()).typ = Some(type_type.clone()); } -/* TODO: -pub fn make_type() -> PyObjectRef { - - // dict.insert("__set_item__".to_string(), _set_item); +pub fn init(context: &PyContext) { + let ref dict_type = context.dict_type; + dict_type.set_attr("__new__", context.new_rustfunc(dict_new)); } -*/ diff --git a/vm/src/objtype.rs b/vm/src/objtype.rs index a6386f4ca..95944e891 100644 --- a/vm/src/objtype.rs +++ b/vm/src/objtype.rs @@ -1,9 +1,9 @@ +use super::objdict; use super::pyobject::{ AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult, ToRust, TypeProtocol, }; use super::vm::VirtualMachine; -use super::objdict; /* * The magical type type diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index f996493e2..f377c518e 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -104,6 +104,7 @@ impl PyContext { objtype::init(&context); objlist::init(&context); objobject::init(&context); + objdict::init(&context); context } From b3b8048cf7eba5c708c67d736840cc5c1a30b5c2 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Mon, 20 Aug 2018 20:00:47 +0100 Subject: [PATCH 7/8] Fix objtype tests. --- vm/src/objtype.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vm/src/objtype.rs b/vm/src/objtype.rs index 95944e891..d7c98a813 100644 --- a/vm/src/objtype.rs +++ b/vm/src/objtype.rs @@ -179,7 +179,7 @@ pub fn call(vm: &mut VirtualMachine, typ: PyObjectRef, args: PyFuncArgs) -> PyRe #[cfg(test)] mod tests { - use super::{create_type, linearise_mro, new}; + use super::{linearise_mro, new}; use super::{IdProtocol, PyContext, PyObjectRef}; fn map_ids(obj: Option>) -> Option> { @@ -193,17 +193,17 @@ mod tests { fn test_linearise() { let context = PyContext::new(); let object = context.object; - let type_type = create_type(); + let type_type = context.type_type; let a = new( type_type.clone(), - String::from("A"), + "A", vec![object.clone()], type_type.clone(), ).unwrap(); let b = new( type_type.clone(), - String::from("B"), + "B", vec![object.clone()], type_type.clone(), ).unwrap(); From 99829d89031d473e92d62823ec0c6a0327455546 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Tue, 21 Aug 2018 08:17:36 +0100 Subject: [PATCH 8/8] Use has_attr rather than getattribute for looking up __init__ --- vm/src/objtype.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/vm/src/objtype.rs b/vm/src/objtype.rs index d7c98a813..449604b42 100644 --- a/vm/src/objtype.rs +++ b/vm/src/objtype.rs @@ -74,13 +74,10 @@ pub fn type_call(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult { let new = typ.get_attr(&String::from("__new__")); let obj = vm.invoke(new, args.insert(typ.clone()))?; - match get_attribute(vm, obj.typ(), &String::from("__init__")) { - Ok(init) => { - vm.invoke(init, args.insert(obj.clone()))?; - } - Err(_) => return Ok(obj), + if obj.typ().has_attr(&String::from("__init__")) { + let init = obj.typ().get_attr(&String::from("__init__")); + vm.invoke(init, args.insert(obj.clone()))?; } - Ok(obj) }