Add type field to PyObject

This commit is contained in:
Windel Bouwman
2018-07-14 00:00:23 +02:00
parent cafc9edf35
commit 66ff3f0bc3
5 changed files with 149 additions and 79 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 } => {