Merge pull request #68 from RustPython/pyobject

Pyobject
This commit is contained in:
Windel Bouwman
2018-08-21 21:16:30 +02:00
committed by GitHub
10 changed files with 151 additions and 174 deletions

View File

@@ -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));
@@ -375,8 +368,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();

View File

@@ -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;

View File

@@ -1,48 +0,0 @@
use super::objtype;
use super::pyobject::{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
let type_ref = args.shift();
let dict = vm.new_dict();
let obj = PyObject::new(PyObjectKind::Instance { dict: dict }, type_ref.clone());
Ok(obj)
}
pub fn call(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
let instance = args.shift();
let function = objtype::get_attribute(vm, instance, &String::from("__call__"))?;
vm.invoke(function, args)
}
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(
type_type.clone(),
String::from("object"),
vec![],
PyObject::new(PyObjectKind::Dict { elements: dict }, type_type.clone()),
).unwrap()
}

View File

@@ -1,5 +1,8 @@
use super::pyobject::{PyObjectRef, PyResult};
use super::pyobject::{
AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult,
};
use super::vm::VirtualMachine;
use std::collections::HashMap;
pub fn _set_item(
vm: &mut VirtualMachine,
@@ -11,9 +14,29 @@ pub fn _set_item(
Ok(vm.get_none())
}
/* TODO:
pub fn make_type() -> PyObjectRef {
// dict.insert("__set_item__".to_string(), _set_item);
pub fn new(dict_type: PyObjectRef) -> PyObjectRef {
PyObject::new(
PyObjectKind::Dict {
elements: HashMap::new(),
},
dict_type.clone(),
)
}
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("dict"),
dict: new(dict_type.clone()),
mro: vec![object_type],
};
(*dict_type.borrow_mut()).typ = Some(type_type.clone());
}
pub fn init(context: &PyContext) {
let ref dict_type = context.dict_type;
dict_type.set_attr("__new__", context.new_rustfunc(dict_new));
}
*/

View File

@@ -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(
@@ -59,10 +59,10 @@ 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()),
)
).unwrap()
}
fn member_get(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {

View File

@@ -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) -> PyObjectRef {
let dict = PyObject::new(
PyObjectKind::Dict {
elements: HashMap::new(),
},
type_type.clone(),
);
typ
objtype::new(type_type.clone(), "list", vec![object.clone()], dict).unwrap()
}
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));
list_type.set_attr("clear", context.new_rustfunc(clear));
list_type.set_attr("reverse", context.new_rustfunc(reverse));
}

39
vm/src/objobject.rs Normal file
View File

@@ -0,0 +1,39 @@
use super::objdict;
use super::objtype;
use super::pyobject::{
AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult,
};
use super::vm::VirtualMachine;
pub fn new_instance(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
// more or less __new__ operator
let type_ref = args.shift();
let dict = vm.new_dict();
let obj = PyObject::new(PyObjectKind::Instance { dict: dict }, type_ref.clone());
Ok(obj)
}
pub fn call(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
let instance = args.shift();
let function = objtype::get_attribute(vm, instance, &String::from("__call__"))?;
vm.invoke(function, args)
}
fn noop(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult {
Ok(vm.get_none())
}
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) {
let ref object = context.object;
object.set_attr("__new__", context.new_rustfunc(new_instance));
object.set_attr("__init__", context.new_rustfunc(noop));
}

View File

@@ -1,55 +1,30 @@
use super::objdict;
use super::pyobject::{
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef,
PyResult, ToRust, TypeProtocol,
};
use super::vm::VirtualMachine;
use std::collections::HashMap;
/*
* 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: &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),
);
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));
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 +62,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)))
}
@@ -99,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)
}
@@ -184,12 +156,12 @@ fn linearise_mro(mut bases: Vec<Vec<PyObjectRef>>) -> Option<Vec<PyObjectRef>> {
Some(result)
}
pub fn new(typ: PyObjectRef, name: String, bases: Vec<PyObjectRef>, dict: PyObjectRef) -> PyResult {
pub fn new(typ: PyObjectRef, name: &str, bases: Vec<PyObjectRef>, 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,
},
@@ -204,7 +176,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<Vec<PyObjectRef>>) -> Option<Vec<usize>> {
@@ -218,17 +190,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();

View File

@@ -1,8 +1,9 @@
use super::bytecode;
use super::objclass;
use super::objdict;
use super::objfunction;
use super::objint;
use super::objlist;
use super::objobject;
use super::objtype;
use super::vm::VirtualMachine;
use std::cell::RefCell;
@@ -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,
@@ -65,29 +66,45 @@ pub struct Scope {
pub parent: Option<PyObjectRef>, // 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 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 object = objclass::create_object(type_type.clone(), function_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_type.clone());
let mut context = PyContext {
let 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_type.clone()),
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,
object: object_type,
function_type: function_type,
bound_method_type: bound_method_type,
member_descriptor_type: member_descriptor_type,
type_type: type_type,
};
objtype::init(&mut context);
objtype::init(&context);
objlist::init(&context);
objobject::init(&context);
objdict::init(&context);
context
}
@@ -122,7 +139,7 @@ impl PyContext {
PyObjectKind::Dict {
elements: HashMap::new(),
},
self.type_type.clone(),
self.dict_type.clone(),
)
}
@@ -244,7 +261,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 +320,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),
};
}

View File

@@ -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);
}
@@ -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