diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 8899c8781..a9458c2e0 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -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>) -> NativeType { } */ -pub fn print(args: Vec) -> Result { +pub fn print(rt: &mut Executor, args: Vec) -> Result { // println!("Woot: {:?}", args); trace!("print called with {:?}", args); for a in args { @@ -45,7 +45,7 @@ pub fn print(args: Vec) -> Result { } println!(); io::stdout().flush().unwrap(); - Ok(PyObject::new(PyObjectKind::None)) + Ok(rt.get_none()) } /* @@ -64,28 +64,34 @@ pub fn len(args: Vec>) -> 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) -> PyResult { - Ok(PyObject::new_bool(true)) +fn any(rt: &mut Executor, args: Vec) -> PyResult { + // TODO + Ok(rt.new_bool(true)) } -fn all(args: Vec) -> PyResult { - Ok(PyObject::new_bool(true)) +fn all(rt: &mut Executor, args: Vec) -> PyResult { + // TODO + Ok(rt.new_bool(true)) } diff --git a/vm/src/objint.rs b/vm/src/objint.rs index 4c2240667..777809e24 100644 --- a/vm/src/objint.rs +++ b/vm/src/objint.rs @@ -1,9 +1,7 @@ -use super::pyobject::{PyObject, PyObjectKind, PyObjectRef}; +use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, Executor}; -fn str(args: Vec) -> Result { - Ok(PyObject::new(PyObjectKind::String { - value: "todo".to_string(), - })) +fn str(rt: &mut Executor, args: Vec) -> Result { + 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 } diff --git a/vm/src/objtype.rs b/vm/src/objtype.rs index fe111e2a5..97e67b3b2 100644 --- a/vm/src/objtype.rs +++ b/vm/src/objtype.rs @@ -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 } + diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 59faf9da5..9e6d47608 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -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, pub dict: HashMap, // __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) -> PyResult; + +// #[derive(Debug)] pub enum PyObjectKind { String { value: String, @@ -105,22 +136,28 @@ pub enum PyObjectKind { None, Type, RustFunction { - function: fn(Vec) -> 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) -> Result { + pub fn call(&self, rt: &mut Executor, args: Vec) -> 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(); + } } diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 60cb67e9c..979666570 100644 --- a/vm/src/vm.rs +++ b/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, 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 } => {