diff --git a/parser/src/lexer.rs b/parser/src/lexer.rs index fd2c6fc3a..25d9ca723 100644 --- a/parser/src/lexer.rs +++ b/parser/src/lexer.rs @@ -1,8 +1,8 @@ -use std::str::FromStr; -use std::str::CharIndices; pub use super::token::Tok; -use std::iter::FromIterator; use std::collections::HashMap; +use std::iter::FromIterator; +use std::str::CharIndices; +use std::str::FromStr; pub struct Lexer<'input> { chars: CharIndices<'input>, @@ -219,7 +219,6 @@ impl<'input> Lexer<'input> { if col == l2 { // TODO: handle wrong indentations } - } } } @@ -270,9 +269,15 @@ impl<'input> Lexer<'input> { match self.chr0 { Some('=') => { self.next_char(); - return Some(Ok((tok_start, Tok::DoubleStarEqual, self.location + 1))); - }, - _ => return Some(Ok((tok_start, Tok::DoubleStar, self.location + 1))), + return Some(Ok(( + tok_start, + Tok::DoubleStarEqual, + self.location + 1, + ))); + } + _ => { + return Some(Ok((tok_start, Tok::DoubleStar, self.location + 1))) + } } } _ => return Some(Ok((tok_start, Tok::Star, self.location + 1))), @@ -382,7 +387,7 @@ impl<'input> Lexer<'input> { Some('=') => { self.next_char(); return Some(Ok((tok_start, Tok::NotEqual, self.location + 1))); - }, + } _ => panic!("Invalid token '!'"), } } @@ -527,10 +532,14 @@ impl<'input> Iterator for Lexer<'input> { // let mut X = HashMap::new(); // X.insert('=', Tok::Equal); let token = self.inner_next(); - trace!("Lex token {:?}, nesting={:?}, indent stack: {:?}", token, self.nesting, self.indentation_stack); + trace!( + "Lex token {:?}, nesting={:?}, indent stack: {:?}", + token, + self.nesting, + self.indentation_stack + ); token } - } #[cfg(test)] diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 2ace33281..614c80a1d 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -1,10 +1,10 @@ #[macro_use] extern crate log; +pub mod ast; +mod lexer; pub mod parser; mod python; -pub mod ast; mod token; -mod lexer; pub use self::parser::parse; diff --git a/parser/src/parser.rs b/parser/src/parser.rs index 86e021dde..47da846ae 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -1,11 +1,11 @@ use std::error::Error; -use std::path::Path; use std::fs::File; use std::io::Read; +use std::path::Path; -use super::python; use super::ast; use super::lexer; +use super::python; pub fn read_file(filename: &Path) -> Result { match File::open(&filename) { @@ -64,8 +64,8 @@ pub fn parse_expression(source: &String) -> Result { #[cfg(test)] mod tests { - use super::parse_program; use super::ast; + use super::parse_program; #[test] fn test_parse_print_hello() { diff --git a/src/main.rs b/src/main.rs index 6f0663ddd..634d2f74d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -58,12 +58,15 @@ fn run_script(script_file: &String) { } fn run_shell() { - println!("Welcome to the magnificent Rust Python {} interpreter", crate_version!()); + println!( + "Welcome to the magnificent Rust Python {} interpreter", + crate_version!() + ); let mut vm = VirtualMachine::new(); // Read a single line: loop { let mut input = String::new(); - print!(">>>>> "); // Use 5 items. pypy has 4, cpython has 3. + print!(">>>>> "); // Use 5 items. pypy has 4, cpython has 3. io::stdout().flush().ok().expect("Could not flush stdout"); io::stdin().read_line(&mut input); // input = input.trim().to_string(); diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index b2378b2fb..904319443 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, PyContext, Executor}; +use super::pyobject::{Executor, PyContext, PyObject, PyObjectKind, PyObjectRef, PyResult}; /* * Original impl: @@ -76,22 +76,35 @@ pub fn len(args: Vec>) -> NativeType { pub fn make_module(ctx: &PyContext) -> PyObjectRef { // scope[String::from("print")] = print; - let obj = PyObject::new(PyObjectKind::Module { name: "__builtins__".to_string() }, ctx.type_type.clone()); - obj.borrow_mut().dict.insert( - String::from("print"), - PyObject::new(PyObjectKind::RustFunction { function: print }, ctx.type_type.clone()), - ); - obj.borrow_mut().dict.insert( - String::from("type"), + let obj = PyObject::new( + PyObjectKind::Module { + name: "__builtins__".to_string(), + }, ctx.type_type.clone(), ); + obj.borrow_mut().dict.insert( + String::from("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 }, ctx.type_type.clone()), + PyObject::new( + PyObjectKind::RustFunction { function: all }, + ctx.type_type.clone(), + ), ); obj.borrow_mut().dict.insert( String::from("any"), - PyObject::new(PyObjectKind::RustFunction { function: any }, ctx.type_type.clone()), + PyObject::new( + PyObjectKind::RustFunction { function: any }, + ctx.type_type.clone(), + ), ); obj } diff --git a/vm/src/bytecode.rs b/vm/src/bytecode.rs index b95521be5..3335df53a 100644 --- a/vm/src/bytecode.rs +++ b/vm/src/bytecode.rs @@ -121,7 +121,8 @@ pub enum BlockType { impl fmt::Debug for CodeObject { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let inst_str = self.instructions.iter() + let inst_str = self.instructions + .iter() .enumerate() .map(|(i, inst)| format!("Inst {}: {:?}", i, inst)) .collect::>() diff --git a/vm/src/compile.rs b/vm/src/compile.rs index 210a4078b..9466a9f22 100644 --- a/vm/src/compile.rs +++ b/vm/src/compile.rs @@ -16,33 +16,31 @@ pub fn compile(source: &String, mode: Mode) -> Result { let mut compiler = Compiler::new(); compiler.push_code_object(CodeObject::new()); match mode { - Mode::Exec => { - match parser::parse_program(source) { - Ok(ast) => { - compiler.compile_program(ast); - Ok(compiler.pop_code_object()) - } - Err(msg) => Err(msg), + Mode::Exec => match parser::parse_program(source) { + Ok(ast) => { + compiler.compile_program(ast); + Ok(compiler.pop_code_object()) } - } - Mode::Eval => { - match parser::parse_statement(source) { - Ok(statement) => { - let need_none = if let &ast::Statement::Expression { expression: _ } = &statement { - false - } else { - true - }; - compiler.compile_statement(statement); - if need_none { - compiler.emit(Instruction::LoadConst { value: bytecode::Constant::None }); - } - compiler.emit(Instruction::ReturnValue); - Ok(compiler.pop_code_object()) + Err(msg) => Err(msg), + }, + Mode::Eval => match parser::parse_statement(source) { + Ok(statement) => { + let need_none = if let &ast::Statement::Expression { expression: _ } = &statement { + false + } else { + true + }; + compiler.compile_statement(statement); + if need_none { + compiler.emit(Instruction::LoadConst { + value: bytecode::Constant::None, + }); } - Err(msg) => Err(msg), + compiler.emit(Instruction::ReturnValue); + Ok(compiler.pop_code_object()) } - } + Err(msg) => Err(msg), + }, } } @@ -270,7 +268,7 @@ impl Compiler { ast::Operator::BitXor => bytecode::BinaryOperator::Xor, ast::Operator::BitAnd => bytecode::BinaryOperator::And, ast::Operator::Subscript => bytecode::BinaryOperator::Subscript, - ast::Operator::And | ast::Operator::Or => { panic!("Not possible") }, + ast::Operator::And | ast::Operator::Or => panic!("Not possible"), }; self.emit(Instruction::BinaryOperation { op: i }); @@ -324,7 +322,9 @@ impl Compiler { ast::Operator::BitXor => bytecode::BinaryOperator::Xor, ast::Operator::BitAnd => bytecode::BinaryOperator::And, ast::Operator::Subscript => bytecode::BinaryOperator::Subscript, - ast::Operator::And | ast::Operator::Or => { panic!("Implement boolean short circuit?") }, + ast::Operator::And | ast::Operator::Or => { + panic!("Implement boolean short circuit?") + } }; let i = Instruction::BinaryOperation { op: i }; self.emit(i); diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 4e7a5fc6e..62bd83188 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -1,14 +1,14 @@ use std::collections::HashMap; -use std::rc::Rc; use std::fmt; +use std::rc::Rc; use super::bytecode; -use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult, PyContext, Executor}; +use super::pyobject::{Executor, PyContext, PyObject, PyObjectKind, PyObjectRef, PyResult}; #[derive(Clone, Debug)] pub struct Block { pub block_type: BlockType, - pub handler: usize, // The destination we should jump to if the block finishes + pub handler: usize, // The destination we should jump to if the block finishes // level? } @@ -18,7 +18,7 @@ pub enum BlockType { start: bytecode::Label, end: bytecode::Label, }, - B + B, } pub struct Frame { @@ -29,7 +29,7 @@ pub struct Frame { blocks: Vec, // Block frames, for controling loops and exceptions pub globals: HashMap, // Variables pub locals: HashMap, // Variables - pub lasti: usize, // index of last instruction ran + pub lasti: usize, // index of last instruction ran // cmp_op: Vec<&'a Fn(NativeType, NativeType) -> bool>, // TODO: change compare to a function list } @@ -97,22 +97,24 @@ impl Frame { impl fmt::Debug for Frame { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let stack_str = self.stack - .iter() - .map(|elem| format!("\n > {}", elem.borrow_mut().str())) - .collect::>() - .join(""); + .iter() + .map(|elem| format!("\n > {}", elem.borrow_mut().str())) + .collect::>() + .join(""); let block_str = self.blocks - .iter() - .map(|elem| format!("\n > {:?}", elem)) - .collect::>() - .join(""); - // + .iter() + .map(|elem| format!("\n > {:?}", elem)) + .collect::>() + .join(""); let local_str = self.locals .iter() .map(|elem| format!("\n {} = {}", elem.0, elem.1.borrow_mut().str())) .collect::>() .join(""); - write!(f, "Frame Object {{ \n Stack:{}\n Blocks:{}\n Locals:{}\n}}", stack_str, block_str, local_str) + write!( + f, + "Frame Object {{ \n Stack:{}\n Blocks:{}\n Locals:{}\n}}", + stack_str, block_str, local_str + ) } } - diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 53629aa98..d9ae932fd 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -9,11 +9,11 @@ mod builtins; pub mod bytecode; pub mod compile; pub mod eval; +mod frame; mod objint; mod objstr; mod objtype; pub mod pyobject; mod vm; -mod frame; pub use self::vm::VirtualMachine; diff --git a/vm/src/objint.rs b/vm/src/objint.rs index 1096acf80..8d4d2f819 100644 --- a/vm/src/objint.rs +++ b/vm/src/objint.rs @@ -1,4 +1,4 @@ -use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, Executor}; +use super::pyobject::{Executor, PyObject, PyObjectKind, PyObjectRef}; fn str(rt: &mut Executor, args: Vec) -> Result { Ok(rt.new_str("todo".to_string())) @@ -13,10 +13,18 @@ fn set_attr(a: &mut PyObjectRef, name: String, b: PyObjectRef) { */ pub fn create_type(type_type: PyObjectRef) -> PyObjectRef { - let typ = PyObject::new(PyObjectKind::Class { name: "int".to_string() }, type_type.clone()); + let typ = PyObject::new( + PyObjectKind::Class { + name: "int".to_string(), + }, + type_type.clone(), + ); typ.borrow_mut().dict.insert( "__str__".to_string(), - PyObject::new(PyObjectKind::RustFunction { function: str }, type_type.clone()), + PyObject::new( + PyObjectKind::RustFunction { function: str }, + type_type.clone(), + ), ); typ } diff --git a/vm/src/objstr.rs b/vm/src/objstr.rs index 7bee4d604..09aea8285 100644 --- a/vm/src/objstr.rs +++ b/vm/src/objstr.rs @@ -1,4 +1,4 @@ -use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, Executor, PyResult}; +use super::pyobject::{Executor, PyObject, PyObjectKind, PyObjectRef, PyResult}; fn str_pos(s: &String, p: i32) -> usize { if p < 0 { @@ -15,8 +15,8 @@ pub fn subscript(rt: &mut Executor, value: &String, b: PyObjectRef) -> PyResult match &(*b.borrow()).kind { &PyObjectKind::Integer { value: ref pos } => { let idx = str_pos(value, *pos); - Ok(rt.new_str(value[idx..idx+1].to_string())) - }, + Ok(rt.new_str(value[idx..idx + 1].to_string())) + } &PyObjectKind::Slice { ref start, ref stop, @@ -38,7 +38,7 @@ pub fn subscript(rt: &mut Executor, value: &String, b: PyObjectRef) -> PyResult _ => unimplemented!(), }; Ok(rt.new_str(value[start2..stop2].to_string())) - }, + } _ => panic!( "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", value, b diff --git a/vm/src/objtype.rs b/vm/src/objtype.rs index 084a5ada9..14a850923 100644 --- a/vm/src/objtype.rs +++ b/vm/src/objtype.rs @@ -9,9 +9,10 @@ use super::pyobject::{PyObject, PyObjectKind, PyObjectRef}; pub fn create_type() -> PyObjectRef { let typ = PyObject::default().into_ref(); - (*typ.borrow_mut()).kind = PyObjectKind::Class { name: "type".to_string() }; + (*typ.borrow_mut()).kind = PyObjectKind::Class { + name: "type".to_string(), + }; (*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 59fdb4b75..fc256e28b 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -1,11 +1,11 @@ -use std::rc::Rc; -use std::fmt; use super::bytecode; use super::objint; use super::objtype; use std::cell::RefCell; use std::collections::HashMap; +use std::fmt; use std::ops::{Add, Mul, Sub}; +use std::rc::Rc; /* Python objects and references. @@ -147,9 +147,13 @@ pub enum PyObjectKind { Function { code: bytecode::CodeObject, }, - Module { name: String }, + Module { + name: String, + }, None, - Class { name: String }, + Class { + name: String, + }, RustFunction { function: RustPyFunc, }, @@ -209,9 +213,14 @@ impl PyObject { PyObjectKind::Code { code: _ } => format!(""), PyObjectKind::Function { code: _ } => format!(""), PyObjectKind::RustFunction { function: _ } => format!(""), - PyObjectKind::Module { ref name }=> format!("", name), - PyObjectKind::Iterator { ref position, ref iterated_obj } => format!( - "", position, iterated_obj.borrow_mut().str() + PyObjectKind::Module { ref name } => format!("", name), + PyObjectKind::Iterator { + ref position, + ref iterated_obj, + } => format!( + "", + position, + iterated_obj.borrow_mut().str() ), _ => { println!("Not impl {:?}", self); @@ -253,7 +262,6 @@ impl PyObject { pub fn into_ref(self) -> PyObjectRef { Rc::new(RefCell::new(self)) } - } impl<'a> Add<&'a PyObject> for &'a PyObject { @@ -372,7 +380,7 @@ impl PartialEq for PyObject { #[cfg(test)] mod tests { - use super::{PyObjectKind, PyContext}; + use super::{PyContext, PyObjectKind}; #[test] fn test_add_py_integers() { diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 1c13a6360..1bebfe220 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -6,19 +6,19 @@ extern crate rustpython_parser; +use std::cell::RefMut; use std::collections::HashMap; +use std::ops::Deref; use std::path::Path; use std::rc::Rc; -use std::cell::RefMut; -use std::ops::Deref; use self::rustpython_parser::parser; use super::builtins; use super::bytecode; use super::compile; -use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult, PyContext, Executor}; +use super::frame::{Block, BlockType, Frame}; use super::objstr; -use super::frame::{Frame, Block, BlockType}; +use super::pyobject::{Executor, PyContext, PyObject, PyObjectKind, PyObjectRef, PyResult}; // use objects::objects; @@ -130,9 +130,12 @@ impl VirtualMachine { self.push_value(obj); None } else { - let name_error = PyObject::new(PyObjectKind::NameError { - name: name.to_string(), - }, self.get_type()); + let name_error = PyObject::new( + PyObjectKind::NameError { + name: name.to_string(), + }, + self.get_type(), + ); Some(Err(name_error)) } } @@ -232,9 +235,7 @@ impl VirtualMachine { // TODO: // self.invoke('__neg__' match a.kind { - PyObjectKind::Integer { value: ref value1 } => { - Ok(self.ctx.new_int(-*value1)) - } + PyObjectKind::Integer { value: ref value1 } => Ok(self.ctx.new_int(-*value1)), _ => panic!("Not impl {:?}", a), } } @@ -244,7 +245,7 @@ impl VirtualMachine { Ok(value) => { self.push_value(value); None - }, + } Err(value) => Some(Err(value)), } } @@ -293,7 +294,7 @@ impl VirtualMachine { Ok(value) => { self.push_value(value); None - }, + } Err(value) => Some(Err(value)), } } @@ -312,10 +313,8 @@ impl VirtualMachine { PyObjectKind::Function { ref code } => { let frame = Frame::new(Rc::new(code.clone()), HashMap::new(), None); self.run_frame(frame).0 - }, - PyObjectKind::Class { name: _ } => { - self.new_instance(func_ref.clone(), args) - }, + } + PyObjectKind::Class { name: _ } => self.new_instance(func_ref.clone(), args), _ => { println!("Not impl {:?}", f); panic!("Not impl"); @@ -336,7 +335,8 @@ impl VirtualMachine { match compile::compile(&source, compile::Mode::Exec) { Ok(bytecode) => { debug!("Code object: {:?}", bytecode); - let obj = PyObject::new(PyObjectKind::Module { name: name.clone() }, self.get_type()); + let obj = + PyObject::new(PyObjectKind::Module { name: name.clone() }, 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); @@ -390,9 +390,7 @@ impl VirtualMachine { let obj = match value { &bytecode::Constant::Integer { ref value } => self.ctx.new_int(*value), // &bytecode::Constant::Float - &bytecode::Constant::String { ref value } => { - self.new_str(value.clone()) - } + &bytecode::Constant::String { ref value } => self.new_str(value.clone()), &bytecode::Constant::Code { ref code } => { PyObject::new(PyObjectKind::Code { code: code.clone() }, self.get_type()) } @@ -405,9 +403,7 @@ impl VirtualMachine { self.import(name.to_string()); None } - &bytecode::Instruction::LoadName { ref name } => { - self.load_name(name) - } + &bytecode::Instruction::LoadName { ref name } => self.load_name(name), &bytecode::Instruction::StoreName { ref name } => { // take top of stack and assign in scope: self.store_name(name.clone()) @@ -419,13 +415,15 @@ impl VirtualMachine { } &bytecode::Instruction::BuildList { size } => { let elements = self.pop_multiple(size); - let list_obj = PyObject::new(PyObjectKind::List { elements: elements }, self.get_type()); + 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 }, self.get_type()); + let list_obj = + PyObject::new(PyObjectKind::Tuple { elements: elements }, self.get_type()); self.push_value(list_obj); None } @@ -457,42 +455,44 @@ 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 }, self.ctx.type_type.clone()); + let obj = PyObject::new( + PyObjectKind::Slice { start, stop, step }, + self.ctx.type_type.clone(), + ); self.push_value(obj); None } - &bytecode::Instruction::BinaryOperation { ref op } => { - self.execute_binop(op) - } - &bytecode::Instruction::LoadAttr { ref name } => { - self.load_attr(name.to_string()) - } - &bytecode::Instruction::UnaryOperation { ref op } => { - self.execute_unop(op) - } - &bytecode::Instruction::CompareOperation { ref op } => { - self.execute_compare(op) - } + &bytecode::Instruction::BinaryOperation { ref op } => self.execute_binop(op), + &bytecode::Instruction::LoadAttr { ref name } => self.load_attr(name.to_string()), + &bytecode::Instruction::UnaryOperation { ref op } => self.execute_unop(op), + &bytecode::Instruction::CompareOperation { ref op } => self.execute_compare(op), &bytecode::Instruction::ReturnValue => { let value = self.pop_value(); Some(Ok(value)) } &bytecode::Instruction::PushBlock { start, end } => { - self.push_block(Block { block_type: BlockType::A { start, end }, handler: 0 }); + self.push_block(Block { + block_type: BlockType::A { start, end }, + handler: 0, + }); None - }, + } &bytecode::Instruction::PopBlock => { self.pop_block(); None } &bytecode::Instruction::GetIter => { let iterated_obj = self.pop_value(); - let iter_obj = PyObject::new(PyObjectKind::Iterator { - position: 0, iterated_obj: iterated_obj - }, self.ctx.type_type.clone()); + let iter_obj = PyObject::new( + PyObjectKind::Iterator { + position: 0, + iterated_obj: iterated_obj, + }, + self.ctx.type_type.clone(), + ); self.push_value(iter_obj); None - }, + } &bytecode::Instruction::ForIter => { // The top of stack contains the iterator, lets push it forward: let next_obj: Option = { @@ -500,7 +500,7 @@ impl VirtualMachine { let mut ref_mut: RefMut = top_of_stack.deref().borrow_mut(); // We require a mutable pyobject here to update the iterator: let mut iterator = ref_mut; // &mut PyObject = ref_mut.; - // let () = iterator; + // let () = iterator; iterator.nxt() }; @@ -508,15 +508,26 @@ impl VirtualMachine { match next_obj { Some(value) => { self.push_value(value); - }, + } None => { + // Pop iterator from stack: + self.pop_value(); + // End of for loop - let end_label = if let Block { block_type: BlockType::A { start, end }, handler } = self.last_block() { *end } else { panic!("Wrong block type") }; + let end_label = if let Block { + block_type: BlockType::A { start, end }, + handler, + } = self.last_block() + { + *end + } else { + panic!("Wrong block type") + }; self.jump(end_label); } }; None - }, + } &bytecode::Instruction::MakeFunction => { let qualified_name = self.pop_value(); let code = self.pop_value();