mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
@@ -1,14 +1,14 @@
|
||||
class Foo:
|
||||
print("Defining class")
|
||||
def __init__(self):
|
||||
print("initing: ", self)
|
||||
self.x = 5
|
||||
def __init__(self, x):
|
||||
self.x = x
|
||||
|
||||
def square(self):
|
||||
return self.x * self.x
|
||||
|
||||
y = 7
|
||||
|
||||
print("Done defining: ", Foo)
|
||||
print("Init: ", Foo.__init__)
|
||||
print("y = ", Foo.y)
|
||||
foo = Foo()
|
||||
print("Done initting: ", foo)
|
||||
print("Foo's x: ", foo.x)
|
||||
foo = Foo(5)
|
||||
|
||||
assert foo.y == Foo.y
|
||||
assert foo.x == 5
|
||||
assert foo.square() == 25
|
||||
|
||||
@@ -12,7 +12,9 @@ pub mod eval;
|
||||
mod frame;
|
||||
mod import;
|
||||
mod objbool;
|
||||
mod objclass;
|
||||
mod objdict;
|
||||
mod objfunction;
|
||||
mod objint;
|
||||
mod objlist;
|
||||
mod objsequence;
|
||||
|
||||
32
vm/src/objclass.rs
Normal file
32
vm/src/objclass.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use super::pyobject::AttributeProtocol;
|
||||
use super::pyobject::{PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use super::vm::VirtualMachine;
|
||||
|
||||
pub fn get_attribute(
|
||||
vm: &mut VirtualMachine,
|
||||
cls: PyObjectRef,
|
||||
obj: PyObjectRef,
|
||||
name: &String,
|
||||
) -> PyResult {
|
||||
if obj.has_attr(name) {
|
||||
Ok(obj.get_attr(name))
|
||||
} else if cls.has_attr(name) {
|
||||
let attr = cls.get_attr(name);
|
||||
let attr_class = attr.typ();
|
||||
if attr_class.has_attr(&String::from("__get__")) {
|
||||
vm.invoke(
|
||||
attr_class.get_attr(&String::from("__get__")),
|
||||
PyFuncArgs {
|
||||
args: vec![attr, obj, cls],
|
||||
},
|
||||
)
|
||||
} else {
|
||||
Ok(attr)
|
||||
}
|
||||
} else {
|
||||
Err(vm.new_exception(format!(
|
||||
"AttributeError: {:?} object has no attribute {}",
|
||||
cls, name
|
||||
)))
|
||||
}
|
||||
}
|
||||
40
vm/src/objfunction.rs
Normal file
40
vm/src/objfunction.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use super::pyobject::{PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult};
|
||||
use super::vm::VirtualMachine;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn create_type(type_type: PyObjectRef) -> PyObjectRef {
|
||||
let mut dict = HashMap::new();
|
||||
dict.insert(
|
||||
"__get__".to_string(),
|
||||
PyObject::new(
|
||||
PyObjectKind::RustFunction {
|
||||
function: bind_method,
|
||||
},
|
||||
type_type.clone(),
|
||||
),
|
||||
);
|
||||
let typ = PyObject::new(
|
||||
PyObjectKind::Class {
|
||||
name: "function".to_string(),
|
||||
dict: PyObject::new(PyObjectKind::Dict { elements: dict }, type_type.clone()),
|
||||
},
|
||||
type_type.clone(),
|
||||
);
|
||||
typ
|
||||
}
|
||||
|
||||
pub fn create_bound_method_type(type_type: PyObjectRef) -> PyObjectRef {
|
||||
let dict = HashMap::new();
|
||||
let typ = PyObject::new(
|
||||
PyObjectKind::Class {
|
||||
name: "method".to_string(),
|
||||
dict: PyObject::new(PyObjectKind::Dict { elements: dict }, type_type.clone()),
|
||||
},
|
||||
type_type.clone(),
|
||||
);
|
||||
typ
|
||||
}
|
||||
|
||||
fn bind_method(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok(vm.new_bound_method(args.args[0].clone(), args.args[1].clone()))
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
use super::bytecode;
|
||||
use super::objfunction;
|
||||
use super::objint;
|
||||
use super::objtype;
|
||||
use super::vm::VirtualMachine;
|
||||
@@ -45,6 +46,8 @@ pub struct PyContext {
|
||||
pub list_type: PyObjectRef,
|
||||
pub tuple_type: PyObjectRef,
|
||||
pub dict_type: PyObjectRef,
|
||||
pub function_type: PyObjectRef,
|
||||
pub bound_method_type: PyObjectRef,
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -61,18 +64,15 @@ pub struct Scope {
|
||||
impl PyContext {
|
||||
pub fn new() -> PyContext {
|
||||
let type_type = objtype::create_type();
|
||||
let int_type = objint::create_type(type_type.clone());
|
||||
// TODO: How to represent builtin types?
|
||||
let list_type = type_type.clone();
|
||||
let tuple_type = type_type.clone();
|
||||
let dict_type = type_type.clone();
|
||||
// let str_type = objstr::make_type();
|
||||
|
||||
PyContext {
|
||||
int_type: objint::create_type(type_type.clone()),
|
||||
list_type: type_type.clone(),
|
||||
tuple_type: type_type.clone(),
|
||||
dict_type: type_type.clone(),
|
||||
function_type: objfunction::create_type(type_type.clone()),
|
||||
bound_method_type: objfunction::create_bound_method_type(type_type.clone()),
|
||||
type_type: type_type,
|
||||
int_type: int_type,
|
||||
list_type: list_type,
|
||||
tuple_type: tuple_type,
|
||||
dict_type: dict_type,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +154,26 @@ impl PyContext {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_function(&self, code_obj: PyObjectRef, scope: PyObjectRef) -> PyObjectRef {
|
||||
PyObject::new(
|
||||
PyObjectKind::Function {
|
||||
code: code_obj,
|
||||
scope: scope,
|
||||
},
|
||||
self.function_type.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_bound_method(&self, function: PyObjectRef, object: PyObjectRef) -> PyObjectRef {
|
||||
PyObject::new(
|
||||
PyObjectKind::BoundMethod {
|
||||
function: function,
|
||||
object: object,
|
||||
},
|
||||
self.bound_method_type.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
/* TODO: something like this?
|
||||
pub fn new_instance(&self, name: String) -> PyObjectRef {
|
||||
PyObject::new(PyObjectKind::Class { name: name }, self.type_type.clone())
|
||||
@@ -187,6 +207,19 @@ impl IdProtocol for PyObjectRef {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TypeProtocol {
|
||||
fn typ(&self) -> PyObjectRef;
|
||||
}
|
||||
|
||||
impl TypeProtocol for PyObjectRef {
|
||||
fn typ(&self) -> PyObjectRef {
|
||||
match self.borrow().typ {
|
||||
Some(ref typ) => typ.clone(),
|
||||
None => panic!("Object doesn't have a type!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ParentProtocol {
|
||||
fn has_parent(&self) -> bool;
|
||||
fn get_parent(&self) -> PyObjectRef;
|
||||
@@ -217,11 +250,13 @@ 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 has_attr(&self, attr_name: &String) -> bool;
|
||||
}
|
||||
|
||||
impl AttributeProtocol for PyObjectRef {
|
||||
fn get_attr(&self, attr_name: &String) -> PyObjectRef {
|
||||
match self.borrow().kind {
|
||||
let obj = self.borrow();
|
||||
match obj.kind {
|
||||
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),
|
||||
@@ -229,6 +264,16 @@ impl AttributeProtocol for PyObjectRef {
|
||||
}
|
||||
}
|
||||
|
||||
fn has_attr(&self, attr_name: &String) -> bool {
|
||||
let obj = self.borrow();
|
||||
match obj.kind {
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_attr(&self, attr_name: &String, value: PyObjectRef) {
|
||||
match self.borrow_mut().kind {
|
||||
PyObjectKind::Instance { ref mut dict } => dict.set_item(attr_name, value),
|
||||
@@ -337,6 +382,10 @@ pub enum PyObjectKind {
|
||||
code: PyObjectRef,
|
||||
scope: PyObjectRef,
|
||||
},
|
||||
BoundMethod {
|
||||
function: PyObjectRef,
|
||||
object: PyObjectRef,
|
||||
},
|
||||
Scope {
|
||||
scope: Scope,
|
||||
},
|
||||
@@ -379,6 +428,10 @@ impl fmt::Debug for PyObjectKind {
|
||||
&PyObjectKind::NameError { name: _ } => write!(f, "NameError"),
|
||||
&PyObjectKind::Code { ref code } => write!(f, "code: {:?}", code),
|
||||
&PyObjectKind::Function { code: _, scope: _ } => write!(f, "function"),
|
||||
&PyObjectKind::BoundMethod {
|
||||
function: _,
|
||||
object: _,
|
||||
} => write!(f, "bound-method"),
|
||||
&PyObjectKind::Module { name: _, dict: _ } => write!(f, "module"),
|
||||
&PyObjectKind::Scope { scope: _ } => write!(f, "scope"),
|
||||
&PyObjectKind::None => write!(f, "None"),
|
||||
@@ -449,6 +502,7 @@ impl PyObject {
|
||||
PyObjectKind::Instance { dict: _ } => format!("<instance>"),
|
||||
PyObjectKind::Code { code: _ } => format!("<code>"),
|
||||
PyObjectKind::Function { code: _, scope: _ } => format!("<func>"),
|
||||
PyObjectKind::BoundMethod { .. } => format!("<bound-method>"),
|
||||
PyObjectKind::RustFunction { function: _ } => format!("<rustfunc>"),
|
||||
PyObjectKind::Module { ref name, dict: _ } => format!("<module '{}'>", name),
|
||||
PyObjectKind::Scope { ref scope } => format!("<scope '{:?}'>", scope),
|
||||
|
||||
52
vm/src/vm.rs
52
vm/src/vm.rs
@@ -12,12 +12,13 @@ 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::objstr;
|
||||
use super::objtype;
|
||||
use super::pyobject::{
|
||||
AttributeProtocol, DictProtocol, IdProtocol, ParentProtocol, PyContext, PyFuncArgs, PyObject,
|
||||
PyObjectKind, PyObjectRef, PyResult,
|
||||
PyObjectKind, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::sysmodule;
|
||||
|
||||
@@ -68,6 +69,10 @@ impl VirtualMachine {
|
||||
self.ctx.new_bool(false)
|
||||
}
|
||||
|
||||
pub fn new_bound_method(&self, function: PyObjectRef, object: PyObjectRef) -> PyObjectRef {
|
||||
self.ctx.new_bound_method(function, object)
|
||||
}
|
||||
|
||||
pub fn get_type(&self) -> PyObjectRef {
|
||||
self.ctx.type_type.clone()
|
||||
}
|
||||
@@ -464,10 +469,8 @@ impl VirtualMachine {
|
||||
// more or less __new__ operator
|
||||
let dict = self.new_dict();
|
||||
let obj = PyObject::new(PyObjectKind::Instance { dict: dict }, type_ref.clone());
|
||||
let init = type_ref.get_attr(&String::from("__init__"));
|
||||
let mut self_args = PyFuncArgs { args: args.args };
|
||||
self_args.args.insert(0, obj.clone());
|
||||
self.invoke(init, self_args)?;
|
||||
let init = objclass::get_attribute(self, type_ref, obj.clone(), &String::from("__init__"))?;
|
||||
self.invoke(init, args)?;
|
||||
// TODO Raise TypeError if init returns not None.
|
||||
Ok(obj)
|
||||
}
|
||||
@@ -490,6 +493,16 @@ impl VirtualMachine {
|
||||
self.run_frame(frame)
|
||||
}
|
||||
PyObjectKind::Class { name: _, dict: _ } => self.new_instance(func_ref.clone(), args),
|
||||
PyObjectKind::BoundMethod {
|
||||
ref function,
|
||||
ref object,
|
||||
} => {
|
||||
let mut self_args = PyFuncArgs {
|
||||
args: args.args.clone(),
|
||||
};
|
||||
self_args.args.insert(0, object.clone());
|
||||
self.invoke(function.clone(), self_args)
|
||||
}
|
||||
ref kind => {
|
||||
unimplemented!("invoke unimplemented for: {:?}", kind);
|
||||
}
|
||||
@@ -507,11 +520,26 @@ impl VirtualMachine {
|
||||
None
|
||||
}
|
||||
|
||||
fn get_attribute(&mut self, obj: PyObjectRef, attr_name: &String) -> PyResult {
|
||||
let typ = obj.typ();
|
||||
let typ_ref = typ.borrow();
|
||||
match typ_ref.kind {
|
||||
PyObjectKind::Class { .. } => {
|
||||
objclass::get_attribute(self, typ.clone(), obj.clone(), attr_name)
|
||||
}
|
||||
_ => panic!("It's not a class: {:?}", typ),
|
||||
}
|
||||
}
|
||||
|
||||
fn load_attr(&mut self, attr_name: &String) -> Option<PyResult> {
|
||||
let parent = self.pop_value();
|
||||
let obj = parent.get_attr(attr_name);
|
||||
self.push_value(obj);
|
||||
None
|
||||
match self.get_attribute(parent, attr_name) {
|
||||
Ok(obj) => {
|
||||
self.push_value(obj);
|
||||
None
|
||||
}
|
||||
Err(err) => Some(Err(err)),
|
||||
}
|
||||
}
|
||||
|
||||
fn store_attr(&mut self, attr_name: &String) -> Option<PyResult> {
|
||||
@@ -692,13 +720,7 @@ impl VirtualMachine {
|
||||
// pop argc arguments
|
||||
// argument: name, args, globals
|
||||
let scope = self.current_frame().locals.clone();
|
||||
let obj = PyObject::new(
|
||||
PyObjectKind::Function {
|
||||
code: code_obj,
|
||||
scope: scope,
|
||||
},
|
||||
self.get_type(),
|
||||
);
|
||||
let obj = self.ctx.new_function(code_obj, scope);
|
||||
self.push_value(obj);
|
||||
None
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user