mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Add type field to PyObject
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// use std::ops::Deref;
|
||||
use std::io::{self, Write};
|
||||
|
||||
use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult};
|
||||
use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult, PyContext, Executor};
|
||||
|
||||
/*
|
||||
* Original impl:
|
||||
@@ -37,7 +37,7 @@ pub fn print(args: Vec<Rc<NativeType>>) -> NativeType {
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn print(args: Vec<PyObjectRef>) -> Result<PyObjectRef, PyObjectRef> {
|
||||
pub fn print(rt: &mut Executor, args: Vec<PyObjectRef>) -> Result<PyObjectRef, PyObjectRef> {
|
||||
// println!("Woot: {:?}", args);
|
||||
trace!("print called with {:?}", args);
|
||||
for a in args {
|
||||
@@ -45,7 +45,7 @@ pub fn print(args: Vec<PyObjectRef>) -> Result<PyObjectRef, PyObjectRef> {
|
||||
}
|
||||
println!();
|
||||
io::stdout().flush().unwrap();
|
||||
Ok(PyObject::new(PyObjectKind::None))
|
||||
Ok(rt.get_none())
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -64,28 +64,34 @@ pub fn len(args: Vec<Rc<NativeType>>) -> NativeType {
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn make_module() -> PyObjectRef {
|
||||
pub fn make_module(ctx: &PyContext) -> PyObjectRef {
|
||||
// scope[String::from("print")] = print;
|
||||
let obj = PyObject::new(PyObjectKind::Module);
|
||||
let obj = PyObject::new(PyObjectKind::Module, ctx.type_type.clone());
|
||||
obj.borrow_mut().dict.insert(
|
||||
String::from("print"),
|
||||
PyObject::new(PyObjectKind::RustFunction { function: print }),
|
||||
PyObject::new(PyObjectKind::RustFunction { function: print }, ctx.type_type.clone()),
|
||||
);
|
||||
obj.borrow_mut().dict.insert(
|
||||
String::from("type"),
|
||||
ctx.type_type.clone(),
|
||||
);
|
||||
obj.borrow_mut().dict.insert(
|
||||
String::from("all"),
|
||||
PyObject::new(PyObjectKind::RustFunction { function: all }),
|
||||
PyObject::new(PyObjectKind::RustFunction { function: all }, ctx.type_type.clone()),
|
||||
);
|
||||
obj.borrow_mut().dict.insert(
|
||||
String::from("any"),
|
||||
PyObject::new(PyObjectKind::RustFunction { function: any }),
|
||||
PyObject::new(PyObjectKind::RustFunction { function: any }, ctx.type_type.clone()),
|
||||
);
|
||||
obj
|
||||
}
|
||||
|
||||
fn any(args: Vec<PyObjectRef>) -> PyResult {
|
||||
Ok(PyObject::new_bool(true))
|
||||
fn any(rt: &mut Executor, args: Vec<PyObjectRef>) -> PyResult {
|
||||
// TODO
|
||||
Ok(rt.new_bool(true))
|
||||
}
|
||||
|
||||
fn all(args: Vec<PyObjectRef>) -> PyResult {
|
||||
Ok(PyObject::new_bool(true))
|
||||
fn all(rt: &mut Executor, args: Vec<PyObjectRef>) -> PyResult {
|
||||
// TODO
|
||||
Ok(rt.new_bool(true))
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use super::pyobject::{PyObject, PyObjectKind, PyObjectRef};
|
||||
use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, Executor};
|
||||
|
||||
fn str(args: Vec<PyObjectRef>) -> Result<PyObjectRef, PyObjectRef> {
|
||||
Ok(PyObject::new(PyObjectKind::String {
|
||||
value: "todo".to_string(),
|
||||
}))
|
||||
fn str(rt: &mut Executor, args: Vec<PyObjectRef>) -> Result<PyObjectRef, PyObjectRef> {
|
||||
Ok(rt.new_str("todo".to_string()))
|
||||
}
|
||||
|
||||
fn add() {}
|
||||
@@ -14,11 +12,11 @@ fn set_attr(a: &mut PyObjectRef, name: String, b: PyObjectRef) {
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn create_type() -> PyObjectRef {
|
||||
let mut typ = PyObject::new(PyObjectKind::Type);
|
||||
pub fn create_type(type_type: PyObjectRef) -> PyObjectRef {
|
||||
let typ = PyObject::new(PyObjectKind::Type, type_type.clone());
|
||||
typ.borrow_mut().dict.insert(
|
||||
"__str__".to_string(),
|
||||
PyObject::new(PyObjectKind::RustFunction { function: str }),
|
||||
PyObject::new(PyObjectKind::RustFunction { function: str }, type_type.clone()),
|
||||
);
|
||||
typ
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// use std::rc::Rc;
|
||||
// use std::cell::RefCell;
|
||||
|
||||
/*
|
||||
* The magical type type
|
||||
*/
|
||||
@@ -5,7 +8,10 @@
|
||||
use super::pyobject::{PyObject, PyObjectKind, PyObjectRef};
|
||||
|
||||
pub fn create_type() -> PyObjectRef {
|
||||
let mut typ = PyObject::new(PyObjectKind::Type);
|
||||
let typ = PyObject::default().into_ref();
|
||||
(*typ.borrow_mut()).kind = PyObjectKind::Type;
|
||||
(*typ.borrow_mut()).typ = Some(typ.clone());
|
||||
// typ.borrow_mut().dict.insert("__str__".to_string(), PyObject::new(PyObjectKind::RustFunction { function: str }));
|
||||
typ
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::rc::Rc;
|
||||
// use std::fmt;
|
||||
use std::fmt;
|
||||
use super::bytecode;
|
||||
use super::objint;
|
||||
use super::objtype;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::{Add, Mul, Sub};
|
||||
// use super::objtype;
|
||||
|
||||
/* Python objects and references.
|
||||
|
||||
@@ -36,35 +36,66 @@ impl fmt::Display for PyObjectRef {
|
||||
}
|
||||
}*/
|
||||
|
||||
pub struct Context {
|
||||
int_type: PyObjectRef,
|
||||
#[derive(Debug)]
|
||||
pub struct PyContext {
|
||||
pub type_type: PyObjectRef,
|
||||
pub int_type: PyObjectRef,
|
||||
}
|
||||
|
||||
// Basic objects:
|
||||
impl Context {
|
||||
fn new() -> Context {
|
||||
let type_type = objint::create_type();
|
||||
let int_type = objint::create_type();
|
||||
impl PyContext {
|
||||
pub fn new() -> PyContext {
|
||||
let type_type = objtype::create_type();
|
||||
let int_type = objint::create_type(type_type.clone());
|
||||
// let str_type = objstr::make_type();
|
||||
Context {
|
||||
// type_type: type_type,
|
||||
PyContext {
|
||||
type_type: type_type,
|
||||
int_type: int_type,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_int(&self, i: i32) -> PyObjectRef {
|
||||
PyObject::new(PyObjectKind::Integer { value: i }, self.type_type.clone())
|
||||
}
|
||||
|
||||
pub fn new_str(&self, s: String) -> PyObjectRef {
|
||||
PyObject::new(PyObjectKind::String { value: s }, self.type_type.clone())
|
||||
}
|
||||
|
||||
pub fn new_bool(&self, b: bool) -> PyObjectRef {
|
||||
PyObject::new(PyObjectKind::Boolean { value: b }, self.type_type.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Executor {
|
||||
fn call(&self, PyObjectRef) -> PyResult;
|
||||
fn call(&mut self, PyObjectRef) -> PyResult;
|
||||
fn new_str(&self, s: String) -> PyObjectRef;
|
||||
fn new_bool(&self, b: bool) -> PyObjectRef;
|
||||
fn get_none(&self) -> PyObjectRef;
|
||||
fn get_type(&self) -> PyObjectRef;
|
||||
fn context(&self) -> &PyContext;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PyObject {
|
||||
pub kind: PyObjectKind,
|
||||
// typ: PyObjectRef,
|
||||
pub typ: Option<PyObjectRef>,
|
||||
pub dict: HashMap<String, PyObjectRef>, // __dict__ member
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
impl Default for PyObject {
|
||||
fn default() -> PyObject {
|
||||
PyObject {
|
||||
kind: PyObjectKind::None,
|
||||
typ: None,
|
||||
dict: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type RustPyFunc = fn(rt: &mut Executor, Vec<PyObjectRef>) -> PyResult;
|
||||
|
||||
// #[derive(Debug)]
|
||||
pub enum PyObjectKind {
|
||||
String {
|
||||
value: String,
|
||||
@@ -105,22 +136,28 @@ pub enum PyObjectKind {
|
||||
None,
|
||||
Type,
|
||||
RustFunction {
|
||||
function: fn(Vec<PyObjectRef>) -> PyResult,
|
||||
function: RustPyFunc,
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Debug for PyObjectKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Some kind of python obj")
|
||||
}
|
||||
}
|
||||
|
||||
impl PyObject {
|
||||
pub fn new(kind: PyObjectKind) -> PyObjectRef {
|
||||
pub fn new(kind: PyObjectKind, typ: PyObjectRef) -> PyObjectRef {
|
||||
PyObject {
|
||||
kind: kind,
|
||||
// typ: PyO
|
||||
typ: Some(typ),
|
||||
dict: HashMap::new(),
|
||||
}.into_ref()
|
||||
}
|
||||
|
||||
pub fn call(&self, args: Vec<PyObjectRef>) -> Result<PyObjectRef, PyObjectRef> {
|
||||
pub fn call(&self, rt: &mut Executor, args: Vec<PyObjectRef>) -> PyResult {
|
||||
match self.kind {
|
||||
PyObjectKind::RustFunction { ref function } => function(args),
|
||||
PyObjectKind::RustFunction { ref function } => function(rt, args),
|
||||
_ => {
|
||||
println!("Not impl {:?}", self);
|
||||
panic!("Not impl");
|
||||
@@ -190,17 +227,6 @@ impl PyObject {
|
||||
Rc::new(RefCell::new(self))
|
||||
}
|
||||
|
||||
pub fn new_int(i: i32) -> PyObjectRef {
|
||||
PyObject::new(PyObjectKind::Integer { value: i })
|
||||
}
|
||||
|
||||
pub fn new_str(s: String) -> PyObjectRef {
|
||||
PyObject::new(PyObjectKind::String { value: s })
|
||||
}
|
||||
|
||||
pub fn new_bool(b: bool) -> PyObjectRef {
|
||||
PyObject::new(PyObjectKind::Boolean { value: b })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Add<&'a PyObject> for &'a PyObject {
|
||||
@@ -319,12 +345,13 @@ impl PartialEq for PyObject {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{PyObject, PyObjectKind, PyObjectRef};
|
||||
use super::{PyObjectKind, PyContext};
|
||||
|
||||
#[test]
|
||||
fn test_add_py_integers() {
|
||||
let a = PyObject::new_int(33);
|
||||
let b = PyObject::new_int(12);
|
||||
let ctx = PyContext::new();
|
||||
let a = ctx.new_int(33);
|
||||
let b = ctx.new_int(12);
|
||||
let c = &*a.borrow() + &*b.borrow();
|
||||
match c {
|
||||
PyObjectKind::Integer { value } => assert_eq!(value, 45),
|
||||
@@ -334,8 +361,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_multiply_str() {
|
||||
let a = PyObject::new_str(String::from("Hello "));
|
||||
let b = PyObject::new_int(4);
|
||||
let ctx = PyContext::new();
|
||||
let a = ctx.new_str(String::from("Hello "));
|
||||
let b = ctx.new_int(4);
|
||||
let c = &*a.borrow() * &*b.borrow();
|
||||
match c {
|
||||
PyObjectKind::String { value } => {
|
||||
@@ -345,4 +373,8 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_type_type() {
|
||||
let ctx = PyContext::new();
|
||||
}
|
||||
}
|
||||
|
||||
76
vm/src/vm.rs
76
vm/src/vm.rs
@@ -16,7 +16,7 @@ use self::rustpython_parser::parse;
|
||||
use super::builtins;
|
||||
use super::bytecode;
|
||||
use super::compile::compile;
|
||||
use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult};
|
||||
use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult, PyContext, Executor};
|
||||
|
||||
// use objects::objects;
|
||||
|
||||
@@ -44,6 +44,7 @@ struct Frame {
|
||||
pub struct VirtualMachine {
|
||||
frames: Vec<Frame>,
|
||||
builtins: PyObjectRef,
|
||||
ctx: PyContext,
|
||||
}
|
||||
|
||||
fn str_pos(s: &String, p: i32) -> usize {
|
||||
@@ -93,11 +94,41 @@ impl Frame {
|
||||
}
|
||||
}
|
||||
|
||||
impl Executor for VirtualMachine {
|
||||
fn call(&mut self, f: PyObjectRef) -> PyResult {
|
||||
self.invoke(f, Vec::new())
|
||||
}
|
||||
|
||||
fn new_str(&self, s: String) -> PyObjectRef {
|
||||
self.ctx.new_str(s)
|
||||
}
|
||||
|
||||
fn new_bool(&self, b: bool) -> PyObjectRef {
|
||||
self.ctx.new_bool(b)
|
||||
}
|
||||
|
||||
fn get_none(&self) -> PyObjectRef {
|
||||
// TODO
|
||||
self.ctx.new_bool(false)
|
||||
}
|
||||
|
||||
fn get_type(&self) -> PyObjectRef {
|
||||
self.ctx.type_type.clone()
|
||||
}
|
||||
|
||||
fn context(&self) -> &PyContext {
|
||||
&self.ctx
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtualMachine {
|
||||
pub fn new() -> VirtualMachine {
|
||||
let ctx = PyContext::new();
|
||||
let builtins = builtins::make_module(&ctx);
|
||||
VirtualMachine {
|
||||
frames: vec![],
|
||||
builtins: builtins::make_module(),
|
||||
builtins: builtins,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +175,7 @@ impl VirtualMachine {
|
||||
}
|
||||
|
||||
// TODO: read the op codes directly from the internal code object
|
||||
fn run_frame(&mut self, mut frame: Frame) -> (PyResult, Frame) {
|
||||
fn run_frame(&mut self, frame: Frame) -> (PyResult, Frame) {
|
||||
self.frames.push(frame);
|
||||
|
||||
// Execute until return or exception:
|
||||
@@ -231,9 +262,7 @@ impl VirtualMachine {
|
||||
&None => 1 as usize,
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
PyObject::new(PyObjectKind::String {
|
||||
value: value[start2..stop2].to_string(),
|
||||
})
|
||||
self.ctx.new_str(value[start2..stop2].to_string())
|
||||
}
|
||||
// TODO: implement other Slice possibilities
|
||||
_ => panic!(
|
||||
@@ -251,9 +280,9 @@ impl VirtualMachine {
|
||||
// TODO: if the left hand side provides __add__, invoke that function.
|
||||
//
|
||||
let result = match op {
|
||||
&bytecode::BinaryOperator::Subtract => PyObject::new(a - b),
|
||||
&bytecode::BinaryOperator::Add => PyObject::new(a + b),
|
||||
&bytecode::BinaryOperator::Multiply => PyObject::new(a * b),
|
||||
&bytecode::BinaryOperator::Subtract => PyObject::new(a - b, self.get_type()),
|
||||
&bytecode::BinaryOperator::Add => PyObject::new(a + b, self.get_type()),
|
||||
&bytecode::BinaryOperator::Multiply => PyObject::new(a * b, self.get_type()),
|
||||
// &bytecode::BinaryOperator::Div => a / b,
|
||||
&bytecode::BinaryOperator::Subscript => self.subscript(a, b),
|
||||
_ => panic!("NOT IMPL {:?}", op),
|
||||
@@ -270,7 +299,7 @@ impl VirtualMachine {
|
||||
// self.invoke('__neg__'
|
||||
match a.kind {
|
||||
PyObjectKind::Integer { value: ref value1 } => {
|
||||
PyObject::new(PyObjectKind::Integer { value: -*value1 })
|
||||
self.ctx.new_int(-*value1)
|
||||
}
|
||||
_ => panic!("Not impl {:?}", a),
|
||||
}
|
||||
@@ -290,7 +319,7 @@ impl VirtualMachine {
|
||||
&bytecode::ComparisonOperator::NotEqual => (a != b),
|
||||
_ => panic!("NOT IMPL {:?}", op),
|
||||
};
|
||||
let result = PyObject::new(PyObjectKind::Boolean { value: result_bool });
|
||||
let result = self.ctx.new_bool(result_bool);
|
||||
self.push_value(result);
|
||||
}
|
||||
|
||||
@@ -298,7 +327,7 @@ impl VirtualMachine {
|
||||
let f = func_ref.borrow();
|
||||
|
||||
match f.kind {
|
||||
PyObjectKind::RustFunction { ref function } => f.call(args),
|
||||
PyObjectKind::RustFunction { ref function } => f.call(self, args),
|
||||
PyObjectKind::Function { ref code } => {
|
||||
let frame = Frame::new(Rc::new(code.clone()), HashMap::new(), None);
|
||||
self.run_frame(frame).0
|
||||
@@ -320,7 +349,7 @@ impl VirtualMachine {
|
||||
debug!("Got ast: {:?}", program);
|
||||
let bytecode = compile(program);
|
||||
debug!("Code object: {:?}", bytecode);
|
||||
let obj = PyObject::new(PyObjectKind::Module);
|
||||
let obj = PyObject::new(PyObjectKind::Module, self.get_type());
|
||||
|
||||
// As a sort of hack, create a frame and run code in it
|
||||
let frame = Frame::new(Rc::new(bytecode), HashMap::new(), None);
|
||||
@@ -370,17 +399,15 @@ impl VirtualMachine {
|
||||
match &instruction {
|
||||
&bytecode::Instruction::LoadConst { ref value } => {
|
||||
let obj = match value {
|
||||
&bytecode::Constant::Integer { ref value } => PyObject::new_int(*value),
|
||||
&bytecode::Constant::Integer { ref value } => self.ctx.new_int(*value),
|
||||
// &bytecode::Constant::Float
|
||||
&bytecode::Constant::String { ref value } => {
|
||||
PyObject::new(PyObjectKind::String {
|
||||
value: value.clone(),
|
||||
})
|
||||
self.new_str(value.clone())
|
||||
}
|
||||
&bytecode::Constant::Code { ref code } => {
|
||||
PyObject::new(PyObjectKind::Code { code: code.clone() })
|
||||
PyObject::new(PyObjectKind::Code { code: code.clone() }, self.get_type())
|
||||
}
|
||||
&bytecode::Constant::None => PyObject::new(PyObjectKind::None),
|
||||
&bytecode::Constant::None => PyObject::new(PyObjectKind::None, self.get_type()),
|
||||
};
|
||||
self.push_value(obj);
|
||||
None
|
||||
@@ -402,7 +429,7 @@ impl VirtualMachine {
|
||||
} else {
|
||||
let name_error = PyObject::new(PyObjectKind::NameError {
|
||||
name: name.to_string(),
|
||||
});
|
||||
}, self.get_type());
|
||||
Some(Err(name_error))
|
||||
}
|
||||
}
|
||||
@@ -419,13 +446,13 @@ impl VirtualMachine {
|
||||
}
|
||||
&bytecode::Instruction::BuildList { size } => {
|
||||
let elements = self.pop_multiple(size);
|
||||
let list_obj = PyObject::new(PyObjectKind::List { elements: elements });
|
||||
let list_obj = PyObject::new(PyObjectKind::List { elements: elements }, self.get_type());
|
||||
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 });
|
||||
let list_obj = PyObject::new(PyObjectKind::Tuple { elements: elements }, self.get_type());
|
||||
self.push_value(list_obj);
|
||||
None
|
||||
}
|
||||
@@ -457,7 +484,7 @@ impl VirtualMachine {
|
||||
let stop = out[1];
|
||||
let step = if out.len() == 3 { out[2] } else { None };
|
||||
|
||||
let obj = PyObject::new(PyObjectKind::Slice { start, stop, step });
|
||||
let obj = PyObject::new(PyObjectKind::Slice { start, stop, step }, self.ctx.type_type.clone());
|
||||
self.push_value(obj);
|
||||
None
|
||||
}
|
||||
@@ -531,7 +558,8 @@ impl VirtualMachine {
|
||||
};
|
||||
// pop argc arguments
|
||||
// argument: name, args, globals
|
||||
self.push_value(PyObject::new(PyObjectKind::Function { code: code_obj }));
|
||||
let obj = PyObject::new(PyObjectKind::Function { code: code_obj }, self.get_type());
|
||||
self.push_value(obj);
|
||||
None
|
||||
}
|
||||
&bytecode::Instruction::CallFunction { count } => {
|
||||
|
||||
Reference in New Issue
Block a user